// Parse an expression terminal ast.ExprNode ParseExpressionTerminal(ParseContext ctx) { switch (t.token) { case Token.literal: { var temp = new ast.ExprNodeLiteral(t.GetBookmark(), t.literal); t.Next(); return temp; } case Token.openRound: { var bmk = t.GetBookmark(); t.Next(); var temp = ParseCompositeExpressionNode(0); t.SkipRequired(Token.closeRound); return new ast.ExprNodeParens(bmk, temp); } case Token.identifier: { var temp = new ast.ExprNodeIdentifier(t.GetBookmark(), t.identifier); t.Next(); return temp; } case Token.openSquare: { // Array literal t.Next(); var temp = new ast.ExprNodeArrayLiteral(t.GetBookmark()); while (true) { if (t.token == Token.closeSquare) break; // Empty expression if (t.token == Token.comma) { t.Next(); temp.Values.Add(null); } else { // Non-empty expression temp.Values.Add(ParseSingleExpressionNode(0)); // End of list? if (!t.SkipOptional(Token.comma)) break; } // Trailing blank element? if (t.token == Token.closeSquare) { t.Compiler.RecordWarning(t.GetBookmark(), "trailing comma in array literal"); temp.Values.Add(null); } } t.SkipRequired(Token.closeSquare); return temp; } case Token.openBrace: { // Create the literal var temp = new ast.ExprNodeObjectLiteral(t.GetBookmark()); // Object literal t.Next(); while (true) { if (t.token == Token.closeBrace) break; // Key // - can be an identifier, or string/number literal object key; if (t.token == Token.identifier) { key = new ast.ExprNodeIdentifier(t.GetBookmark(), t.identifier); } else { t.Require(Token.literal); key = t.literal; } t.Next(); // Key/value delimiter t.SkipRequired(Token.colon); // Value temp.Values.Add(new ast.KeyExpressionPair(key, ParseSingleExpressionNode(0))); // Another key/value pair if (!t.SkipOptional(Token.comma)) break; if (t.token == Token.closeBrace) { t.Compiler.RecordWarning(t.GetBookmark(), "trailing comma in object literal"); } } t.SkipRequired(Token.closeBrace); return temp; } case Token.divide: case Token.divideAssign: { // Regular expressions return new ast.ExprNodeRegEx(t.GetBookmark(), t.ParseRegEx()); } case Token.kw_function: { t.Next(); return ParseFunction(); } case Token.kw_new: { var bmk = t.GetBookmark(); t.Next(); // Parse the type var newType = ParseExpressionMember(ctx | ParseContext.NoFunctionCalls); // Create the new operator var newOp = new ast.ExprNodeNew(bmk, newType); // Parse parameters if (t.SkipOptional(Token.openRound)) { if (t.token != Token.closeRound) { while (true) { newOp.Arguments.Add(ParseSingleExpressionNode(0)); if (t.SkipOptional(Token.comma)) continue; else break; } } t.SkipRequired(Token.closeRound); } return newOp; } case Token.kw_delete: { var bmk = t.GetBookmark(); t.Next(); return new ast.ExprNodeUnary(bmk, ParseExpressionMember(ctx), Token.kw_delete); } } throw new CompileError(string.Format("Invalid expression, didn't expect {0}", t.DescribeCurrentToken()), t); }
// Parse an expression terminal ast.ExprNode ParseExpressionTerminal(ParseContext ctx) { switch (t.token) { case Token.literal: { var temp = new ast.ExprNodeLiteral(t.GetBookmark(), t.literal); t.Next(); return(temp); } case Token.openRound: { var bmk = t.GetBookmark(); t.Next(); var temp = ParseCompositeExpressionNode(0); t.SkipRequired(Token.closeRound); return(new ast.ExprNodeParens(bmk, temp)); } case Token.identifier: { var temp = new ast.ExprNodeIdentifier(t.GetBookmark(), t.identifier); t.Next(); return(temp); } case Token.openSquare: { // Array literal t.Next(); var temp = new ast.ExprNodeArrayLiteral(t.GetBookmark()); while (true) { if (t.token == Token.closeSquare) { break; } // Empty expression if (t.token == Token.comma) { t.Next(); temp.Values.Add(null); } else { // Non-empty expression temp.Values.Add(ParseSingleExpressionNode(0)); // End of list? if (!t.SkipOptional(Token.comma)) { break; } } // Trailing blank element? if (t.token == Token.closeSquare) { t.Compiler.RecordWarning(t.GetBookmark(), "trailing comma in array literal"); temp.Values.Add(null); } } t.SkipRequired(Token.closeSquare); return(temp); } case Token.openBrace: { // Create the literal var temp = new ast.ExprNodeObjectLiteral(t.GetBookmark()); // Object literal t.Next(); while (true) { if (t.token == Token.closeBrace) { break; } // Key // - can be an identifier, or string/number literal object key; if (t.token == Token.identifier) { key = new ast.ExprNodeIdentifier(t.GetBookmark(), t.identifier); } else { t.Require(Token.literal); key = t.literal; } t.Next(); // Key/value delimiter t.SkipRequired(Token.colon); // Value temp.Values.Add(new ast.KeyExpressionPair(key, ParseSingleExpressionNode(0))); // Another key/value pair if (!t.SkipOptional(Token.comma)) { break; } if (t.token == Token.closeBrace) { t.Compiler.RecordWarning(t.GetBookmark(), "trailing comma in object literal"); } } t.SkipRequired(Token.closeBrace); return(temp); } case Token.divide: case Token.divideAssign: { // Regular expressions return(new ast.ExprNodeRegEx(t.GetBookmark(), t.ParseRegEx())); } case Token.kw_function: { t.Next(); return(ParseFunction()); } case Token.kw_new: { var bmk = t.GetBookmark(); t.Next(); // Parse the type var newType = ParseExpressionMember(ctx | ParseContext.NoFunctionCalls); // Create the new operator var newOp = new ast.ExprNodeNew(bmk, newType); // Parse parameters if (t.SkipOptional(Token.openRound)) { if (t.token != Token.closeRound) { while (true) { newOp.Arguments.Add(ParseSingleExpressionNode(0)); if (t.SkipOptional(Token.comma)) { continue; } else { break; } } } t.SkipRequired(Token.closeRound); } return(newOp); } case Token.kw_delete: { var bmk = t.GetBookmark(); t.Next(); return(new ast.ExprNodeUnary(bmk, ParseExpressionMember(ctx), Token.kw_delete)); } } throw new CompileError(string.Format("Invalid expression, didn't expect {0}", t.DescribeCurrentToken()), t); }