private bool ParseLiteralValue(ref ASTNode retn) { tokenStream.Save(); // todo if we support bitwise not, add it here if (tokenStream.Current == ExpressionTokenType.Not && tokenStream.Next == ExpressionTokenType.Boolean) { bool value = bool.Parse(tokenStream.Next.value); retn = ASTNode.BooleanLiteralNode((!value).ToString()).WithLocation(tokenStream.Current); tokenStream.Advance(2); return(true); } if (tokenStream.Current == ExpressionTokenType.Minus && tokenStream.Next == ExpressionTokenType.Number && (tokenStream.Previous.IsOperator || !tokenStream.HasPrevious)) { retn = ASTNode.NumericLiteralNode("-" + tokenStream.Next.value).WithLocation(tokenStream.Current); tokenStream.Advance(2); return(true); } if (tokenStream.Current == ExpressionTokenType.Plus && tokenStream.Next == ExpressionTokenType.Number && (tokenStream.Previous.IsOperator || !tokenStream.HasPrevious)) { retn = ASTNode.NumericLiteralNode(tokenStream.Next.value).WithLocation(tokenStream.Current); tokenStream.Advance(2); return(true); } switch (tokenStream.Current.expressionTokenType) { case ExpressionTokenType.Null: retn = ASTNode.NullLiteralNode(tokenStream.Current.value).WithLocation(tokenStream.Current); break; case ExpressionTokenType.String: retn = ASTNode.StringLiteralNode(tokenStream.Current.value).WithLocation(tokenStream.Current); break; case ExpressionTokenType.Boolean: retn = ASTNode.BooleanLiteralNode(tokenStream.Current.value).WithLocation(tokenStream.Current); break; case ExpressionTokenType.Number: retn = ASTNode.NumericLiteralNode(tokenStream.Current.value).WithLocation(tokenStream.Current); break; case ExpressionTokenType.Default: // todo -- allow a type expression a-la default(List<float>); retn = ASTNode.DefaultLiteralNode(tokenStream.Current.value).WithLocation(tokenStream.Current); break; default: return(false); } tokenStream.Advance(); return(true); }
private ASTNode ParseLoop() { while (tokenStream.HasMoreTokens) { ASTNode operand = default; if (ParseExpression(ref operand)) { if (tokenStream.Current == ExpressionTokenType.Increment) { tokenStream.Advance(); expressionStack.Push(ASTNode.UnaryExpressionNode(ASTNodeType.UnaryPostIncrement, operand)); } else if (tokenStream.Current == ExpressionTokenType.Decrement) { tokenStream.Advance(); expressionStack.Push(ASTNode.UnaryExpressionNode(ASTNodeType.UnaryPostDecrement, operand)); } else { expressionStack.Push(operand); } continue; } if (expressionStack.Count == 0) { Abort(); } if (tokenStream.Current == ExpressionTokenType.QuestionMark && !tokenStream.NextTokenIs(ExpressionTokenType.QuestionMark)) { while (operatorStack.Count != 0) { OperatorNode opNode = operatorStack.Pop(); opNode.right = expressionStack.Pop(); opNode.left = expressionStack.Pop(); expressionStack.Push(opNode); } OperatorNode condition = ASTNode.OperatorNode(OperatorType.TernaryCondition); OperatorNode selection = ASTNode.OperatorNode(OperatorType.TernarySelection); condition.WithLocation(tokenStream.Previous); tokenStream.Advance(); int idx = tokenStream.FindMatchingTernaryColon(); if (idx != -1) { TokenStream stream = tokenStream.AdvanceAndReturnSubStream(idx); // parse the left side of the : operator ExpressionParser parser = new ExpressionParser(stream); ASTNode leftNode = parser.ParseLoop(); parser.Release(); tokenStream.Advance(); // step over colon ExpressionParser parserRight = new ExpressionParser(tokenStream); ASTNode rightNode = parserRight.ParseLoop(); tokenStream.Set(parserRight.tokenStream.CurrentIndex); parserRight.Release(false); selection.left = leftNode; selection.right = rightNode; condition.left = expressionStack.Pop(); condition.right = selection; expressionStack.Push(condition); } else { // read to end use implicit default value for left hand side ExpressionParser parserLeft = new ExpressionParser(tokenStream); ASTNode leftNode = parserLeft.ParseLoop(); tokenStream.Set(parserLeft.tokenStream.CurrentIndex); parserLeft.Release(false); selection.left = leftNode; selection.right = ASTNode.DefaultLiteralNode("default"); condition.left = expressionStack.Pop(); condition.right = selection; expressionStack.Push(condition); } continue; } OperatorNode op; if (!ParseOperatorExpression(out op)) { Abort(); break; } while (operatorStack.Count != 0 && op.priority <= operatorStack.Peek().priority) { OperatorNode opNode = operatorStack.Pop(); opNode.right = expressionStack.Pop(); opNode.left = expressionStack.Pop(); expressionStack.Push(opNode); } operatorStack.Push(op); } while (operatorStack.Count != 0) { OperatorNode opNode = operatorStack.Pop(); opNode.right = expressionStack.Pop(); opNode.left = expressionStack.Pop(); expressionStack.Push(opNode); } if (expressionStack.Count != 1) { Abort(); } return(expressionStack.Pop()); }