Skip to content

Commit

Permalink
Fixed an issue with the Parser where if the token at the top of the o…
Browse files Browse the repository at this point in the history
…perator stack is a parenthesis, that it would attempt to convert it into a function and crash.
  • Loading branch information
Carson-McCombs committed Jun 26, 2024
1 parent f62c358 commit 2693f05
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 24 deletions.
10 changes: 5 additions & 5 deletions app/src/main/java/model/parser/evaluator/ShuntingYardParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class ShuntingYardParser {
val baseParseResult = ParseResult(isStatic = isStatic, globalDependencyIds = globalDependencyIds, localDependencyIds = localDependencyIds)
val outputQueue = ArrayDeque<Token>()
val operatorStack = ArrayDeque<Token>()
//println(tokens.joinToString ("\n "))
for (token in tokens) {
//println("-------------")
//println("Token: ${token.text}")
Expand All @@ -117,7 +118,6 @@ class ShuntingYardParser {

while (operatorStack.first().text != "(") {
if (operatorStack.isEmpty()) return baseParseResult.copy( errorText = "No opening parenthesis found")
//outputQueue.addLast(operatorStack.removeFirst())
//println("-------------")
//println("Token: ${operatorStack.first().text}")
//println("Output Queue: ${outputQueue.map { t -> t.text }}")
Expand All @@ -138,12 +138,13 @@ class ShuntingYardParser {
operatorStack.addFirst(token)
continue
}
//var functionA = Function.functionMap[token.text] ?: return Pair(null, Error("Unknown Function \"${operatorStack.first()}\""))
//var functionB = Function.functionMap[operatorStack.first().text] ?: return Pair(null, Error("Unknown Function \"${operatorStack.first()}\""))
if (operatorStack.first().tokenType == TokenType.PUNCTUATION){
operatorStack.addFirst(token)
continue
}
val tokenFunction = token.value as Function
var otherFunction = operatorStack.first().value as Function
while ((otherFunction.name != "(") && (tokenFunction.precedence > otherFunction.precedence) || (tokenFunction.precedence == otherFunction.precedence && tokenFunction.associativity == AssociativityDirection.LeftToRight)) {
//outputQueue.addLast(operatorStack.removeFirst())
//println("-------------")
//println("Token: ${operatorStack.first().text}")
//println("Output Queue: ${outputQueue.map { t -> t.text }}")
Expand All @@ -164,7 +165,6 @@ class ShuntingYardParser {
//println("Output Queue: ${outputQueue.map { t -> t.text }}")
//println("Operator Stack: ${operatorStack.map { t -> t.text }}")
if (operatorStack.last().text == "(") return baseParseResult.copy( errorText = "Cannot end statement with an open parenthesis")
//outputQueue.addLast(operatorStack.removeFirst())
val err = addToOutputQueue(outputQueue, operatorStack.removeFirst())
if (err != null) return baseParseResult.copy( errorText = err.message ?: "")
}
Expand Down
24 changes: 24 additions & 0 deletions app/src/main/java/view/expressionGroupScreen/ErrorPopupView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package view.expressionGroupScreen

import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.window.Popup

@Composable
fun ErrorPopupView(title: String, error: Error){
Popup {
Text(
text = title,
style = MaterialTheme.typography.titleLarge
)
Text(text = error.message ?: "empty error message")
}
}

@Preview
@Composable
fun ErrorPopupView_Preview(){
ErrorPopupView(title = "Error Preview", error = Error("Example Error Text"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fun GroupScreenView(
addChildGroup = { viewModel.addChildExpressionGroup() },
expressionEvents = remember(viewModel.id, "expressionEvents") { ExpressionEvents.fromViewModel(viewModel)},
groupEvents = remember(viewModel.id, "expressionEvents") { GroupEvents.fromViewModel(viewModel) },
groupScreenEvents = groupScreenEvents
groupScreenEvents = groupScreenEvents,
)
}

Expand All @@ -89,7 +89,7 @@ private fun GroupScreenView(
addChildGroup: () -> Unit,
expressionEvents: ExpressionEvents,
groupEvents: GroupEvents,
groupScreenEvents: GroupScreenEvents
groupScreenEvents: GroupScreenEvents,
){

Scaffold(
Expand Down
41 changes: 24 additions & 17 deletions app/src/main/java/viewModel/GroupScreenViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class GroupScreenViewModel(
initialValue = emptyMap()
)

val unhandledErrorState: Pair<String,Error>? = null

private val _expressionTextFieldStateMap: MutableMap<Long, TextFieldState> = mutableMapOf()

fun getExpressionTextFieldState(expressionId: Long): TextFieldState {
Expand Down Expand Up @@ -188,23 +190,28 @@ class GroupScreenViewModel(
val name = getExpressionNameTextFieldState(expressionId).text.toString()
val rawText = getExpressionTextFieldState(expressionId).text.toString()
var expression = childExpressionsMap.value[expressionId]!!
val parseResult = ShuntingYardParser.evaluate(
id = expressionId,
rawText = rawText,
getGroupPath = { exprId ->
repository.getExpressionGroupPath(exprId)
},
getExpressionId = { expressionFullPath: String ->
repository.expressionFullPathToIdMap.value[expressionFullPath]
},
getExpression = { exprId: Long ->
repository.expressionMap.value[exprId]
},
getOverlappingDependencies = {exprId, otherIds -> repository.getOverlappingDependencies(exprId, otherIds) }
)
expression = expression.copy(name = name, text = rawText, parseResult = parseResult, updated = true)
repository.upsertExpression(expression)
if (oldText != rawText) repository.updateDependentExpressions(expression = expression)
try {
val parseResult = ShuntingYardParser.evaluate(
id = expressionId,
rawText = rawText,
getGroupPath = { exprId ->
repository.getExpressionGroupPath(exprId)
},
getExpressionId = { expressionFullPath: String ->
repository.expressionFullPathToIdMap.value[expressionFullPath]
},
getExpression = { exprId: Long ->
repository.expressionMap.value[exprId]
},
getOverlappingDependencies = {exprId, otherIds -> repository.getOverlappingDependencies(exprId, otherIds) }
)
expression = expression.copy(name = name, text = rawText, parseResult = parseResult, updated = true)
repository.upsertExpression(expression)
if (oldText != rawText) repository.updateDependentExpressions(expression = expression)
} catch (error: Error) {
println(error)
}

}
}

Expand Down

0 comments on commit 2693f05

Please sign in to comment.