private bool ParseParenExpression(ref ASTNode retn) { if (tokenStream.Current != ExpressionTokenType.ParenOpen) { return(false); } int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose); if (advance == -1) { throw new Exception("Unmatched paren"); // todo just abort } ExpressionParser subParser = CreateSubParser(advance); retn = subParser.ParseLoop(); if (retn.IsCompound) { retn = ASTNode.ParenNode(retn); } ASTNode access = null; if (ParseParenAccessExpression(ref access)) { ParenNode parenNode = (ParenNode)retn; parenNode.accessExpression = (MemberAccessExpressionNode)access; } subParser.Release(); return(true); }
public static ASTNode Parse(TokenStream tokenStream) { ExpressionParser parser = new ExpressionParser(tokenStream); ASTNode retn = parser.ParseLoop(); parser.Release(); return(retn); }
// something.someValue // something[i] // something(*).x(*).y private bool ParseAccessExpression(ref ASTNode retn) { if (tokenStream.Current != ExpressionTokenType.Identifier) { return(false); } string identifier = tokenStream.Current.value; tokenStream.Save(); LightList <ASTNode> parts = LightList <ASTNode> .Get(); tokenStream.Advance(); while (tokenStream.HasMoreTokens) { if (tokenStream.Current == ExpressionTokenType.Dot || tokenStream.Current == ExpressionTokenType.Elvis) { if (tokenStream.Next != ExpressionTokenType.Identifier) { break; } tokenStream.Advance(); parts.Add(ASTNode.DotAccessNode(tokenStream.Current.value, tokenStream.Previous == ExpressionTokenType.Elvis)); tokenStream.Advance(); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.ArrayAccessOpen || tokenStream.Current == ExpressionTokenType.QuestionMark && tokenStream.NextTokenIs(ExpressionTokenType.ArrayAccessOpen)) { bool isElvis = false; if (tokenStream.Current == ExpressionTokenType.QuestionMark) { isElvis = true; tokenStream.Advance(); } int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.ArrayAccessOpen, ExpressionTokenType.ArrayAccessClose); if (advance == -1) { Abort("Unmatched array bracket"); } ExpressionParser subParser = CreateSubParser(advance); parts.Add(ASTNode.IndexExpressionNode(subParser.ParseLoop(), isElvis)); subParser.Release(); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.ParenOpen) { LightList <ASTNode> parameters = null; if (!ParseListExpression(ref parameters, ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose)) { Abort(); } parts.Add(ASTNode.InvokeNode(parameters)); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.LessThan) { // shortcut the << operator since we can't have a << in a generic type node. List<<string>> is invalid for example if (tokenStream.HasMoreTokens && tokenStream.Next == ExpressionTokenType.LessThan) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } TypeLookup typePath = new TypeLookup(); if (!(ParseTypePathGenerics(ref typePath))) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } parts.Add(ASTNode.GenericTypePath(typePath)); if (tokenStream.HasMoreTokens) { continue; } } if (parts.Count == 0) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } retn = ASTNode.MemberAccessExpressionNode(identifier, parts).WithLocation(tokenStream.Peek()); return(true); } ReleaseList(parts); tokenStream.Restore(); return(false); }
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()); }