negative numbers parsing

This commit is contained in:
Timerix22 2023-12-22 20:33:25 +06:00
parent cc6cda554c
commit 5a4b2ce3f6

View File

@ -3,9 +3,11 @@ class Parser
List<Token()> TokenStorage; List<Token()> TokenStorage;
IExpression# RootExpression; IExpression# RootExpression;
TokenLinkedList() TokensInRPN; TokenLinkedList() TokensInRPN;
Token() TokZero;
internal Parser(){ internal Parser(){
RootExpression = new NumericExpression { N = Math.NaN }; RootExpression = new NumericExpression { N = Math.NaN };
TokZero = Token.Create("0", 0, 1, Token.Type_Number);
} }
internal IExpression# Parse!(){ internal IExpression# Parse!(){
@ -22,9 +24,13 @@ class Parser
// Implementation of https://en.wikipedia.org/wiki/Shunting_yard_algorithm // Implementation of https://en.wikipedia.org/wiki/Shunting_yard_algorithm
void SortTokensInRPN!(){ void SortTokensInRPN!(){
Stack<Token>() RPNStack; Stack<Token>() RPNStack;
// is needed for negative numbers recognition
int prevTokType = Token.Type_BracketOpen;
for(int i = 0; i < TokenStorage.Count; i++){ for(int i = 0; i < TokenStorage.Count; i++){
Token tok = TokenStorage[i]; Token tok = TokenStorage[i];
int type = tok.GetType(); int type = tok.GetType();
switch(type){ switch(type){
case Token.Type_Number: case Token.Type_Number:
TokensInRPN.AddToEnd(tok); TokensInRPN.AddToEnd(tok);
@ -35,6 +41,8 @@ class Parser
case Token.Type_OperatorMod: case Token.Type_OperatorMod:
case Token.Type_OperatorAdd: case Token.Type_OperatorAdd:
case Token.Type_OperatorSub: case Token.Type_OperatorSub:
if(type == Token.Type_OperatorSub && prevTokType == Token.Type_BracketOpen)
TokensInRPN.AddToEnd(TokZero);
while(RPNStack.Count != 0 && RPNStack.Peek().GetType() >= type){ while(RPNStack.Count != 0 && RPNStack.Peek().GetType() >= type){
Token op2 = RPNStack.Pop(); Token op2 = RPNStack.Pop();
TokensInRPN.AddToEnd(op2); TokensInRPN.AddToEnd(op2);
@ -47,9 +55,8 @@ class Parser
case Token.Type_BracketClose: case Token.Type_BracketClose:
while(RPNStack.Count != 0){ while(RPNStack.Count != 0){
Token op2 = RPNStack.Pop(); Token op2 = RPNStack.Pop();
if(op2.GetType() == Token.Type_BracketOpen){ if(op2.GetType() == Token.Type_BracketOpen)
break; break;
}
TokensInRPN.AddToEnd(op2); TokensInRPN.AddToEnd(op2);
} }
break; break;
@ -60,6 +67,8 @@ class Parser
ThrowError("unexpected token type"); ThrowError("unexpected token type");
break; break;
} }
prevTokType = type;
} }
// add remaining operators // add remaining operators
@ -76,8 +85,9 @@ class Parser
TokenLinkedListNode? tokenNode = TokensInRPN.GetFirstNode(); TokenLinkedListNode? tokenNode = TokensInRPN.GetFirstNode();
while(tokenNode != null){ while(tokenNode != null){
Token tok = tokenNode.GetValue(); Token tok = tokenNode.GetValue();
int type = tok.GetType();
switch(tok.GetType()){ switch(type){
case Token.Type_Number: case Token.Type_Number:
expressionStack.Push(new NumericExpression { N = StringToDouble(tok.GetStr()) }); expressionStack.Push(new NumericExpression { N = StringToDouble(tok.GetStr()) });
break; break;
@ -100,14 +110,16 @@ class Parser
PushOperatorExpression(expressionStack, tok, new OperatorExpressionSub()); PushOperatorExpression(expressionStack, tok, new OperatorExpressionSub());
break; break;
case Token.Type_BracketClose: case Token.Type_BracketClose:
ThrowError("unexpected (");
break;
case Token.Type_BracketOpen: case Token.Type_BracketOpen:
ThrowError("brackets should be handled at SortTokensInRPN"); ThrowError("unexpected )");
break; break;
case Token.Type_Literal: case Token.Type_Literal:
ThrowError("not implemented"); ThrowError("not implemented");
break; break;
default: default:
ThrowError("unexpected token type"); ThrowError($"unexpected token type: {type}");
break; break;
} }
@ -139,7 +151,7 @@ class Parser
void PushOperatorExpression(Stack<IExpression#>! expressionStack, Token tok, OperatorExpression# opExpr) { void PushOperatorExpression(Stack<IExpression#>! expressionStack, Token tok, OperatorExpression# opExpr) {
if(expressionStack.Count < 2){ if(expressionStack.Count < 2){
ThrowError("input error: unexpected operator "+tok.GetStr()); ThrowError($"unexpected operator: {tok.GetStr()}");
return; return;
} }
IExpression b = expressionStack.Pop(); IExpression b = expressionStack.Pop();