/// <summary> /// Analyses the tokens to produce an AST of Expr. /// When <paramref name="allowGlobalUse"/> is true and <see cref="Config.GlobalScope"/> is true, the top-level declarations /// go into the global scope. /// </summary> /// <param name="p">Tokeinzer to analyse.</param> /// <param name="allowGlobalUse">False to scope declarations to this analysis.</param> /// <returns>The AST (that may be a <see cref="SyntaxErrorExpr"/> or contains such errors).</returns> public Expr Analyse(JSTokenizer p, bool allowGlobalUse = true) { _parser = p; if (!(allowGlobalUse && _scope.GlobalScope)) { _scope.OpenScope(); } return(HandleBlock(Expression(0))); }
Expr HandleAssign(Expr left, bool pureAssign = false) { var location = _parser.Location; AccessorExpr a = left as AccessorExpr; if (a == null) { return(new SyntaxErrorExpr(location, "Invalid assignment left-hand side.")); } if (pureAssign || _parser.Match(JSTokenizerToken.Assign)) { return(new AssignExpr(location, a, Expression(JSTokenizer.PrecedenceLevel(JSTokenizerToken.Comma)))); } JSTokenizerToken binaryTokenType = JSTokenizer.FromAssignOperatorToBinary(_parser.CurrentToken); _parser.Forward(); return(new AssignExpr(location, a, new BinaryExpr(location, left, binaryTokenType, Expression(0)))); }
Expr HandleUnaryExpr() { var loc = _parser.Location; var t = _parser.CurrentToken; _parser.Forward(); // Unary operators are JSTokenizerToken.OpLevel14, except Minus and Plus that are classified as binary operators and are associated to OpLevel12. var right = Expression(JSTokenizer.PrecedenceLevel(JSTokenizerToken.OpLevel14)); if (t == JSTokenizerToken.PlusPlus || t == JSTokenizerToken.MinusMinus) { AccessorExpr a = right as AccessorExpr; if (a == null) { return(new SyntaxErrorExpr(loc, "invalid increment operand.")); } return(new PrePostIncDecExpr(loc, a, t == JSTokenizerToken.PlusPlus, true, right.IsStatement)); } return(new UnaryExpr(loc, t, right)); }
Expr HandleCall(Expr left) { SourceLocation loc = _parser.PrevNonCommentLocation; IList <Expr> parameters = null; if (!_parser.Match(JSTokenizerToken.ClosePar)) { for ( ; ;) { Debug.Assert(JSTokenizer.PrecedenceLevel(JSTokenizerToken.Comma) == 2); Expr e = Expression(2); if (e is SyntaxErrorExpr) { return(e); } if (parameters == null) { parameters = new List <Expr>(); } parameters.Add(e); if (_parser.Match(JSTokenizerToken.ClosePar)) { break; } if (!_parser.Match(JSTokenizerToken.Comma)) { return(new SyntaxErrorExpr(_parser.Location, "Expected ) opened at {0}.", loc)); } } } var arguments = parameters != null?parameters.ToArray() : Expr.EmptyArray; return(new AccessorCallExpr(loc, left, arguments, _parser.Match(JSTokenizerToken.SemiColon))); }
NotImplementedException UnsupportedOperatorException() { string msg = String.Format("Unsupported binary operator: '{0}' ({1}).", JSTokenizer.Explain(Expr.BinaryOperatorToken), (int)Expr.BinaryOperatorToken); return(new NotImplementedException(msg)); }
/// <summary> /// This is just to ease debugging. /// </summary> /// <returns>Readable expression.</returns> public override string ToString() { return(Left.ToString() + JSTokenizer.Explain(BinaryOperatorToken) + Right.ToString()); }
public override string ToString() { return(JSTokenizer.Explain(TokenType) + Expression.ToString()); }
Expr HandleLogicalExpr(Expr left) { _parser.Forward(); // Right associative operators to support short-circuit (hence the -1 on the level). return(new BinaryExpr(_parser.PrevNonCommentLocation, left, _parser.PrevNonCommentToken, Expression(JSTokenizer.PrecedenceLevel(_parser.PrevNonCommentToken) - 1))); }
Expr HandleBinaryExpr(Expr left) { _parser.Forward(); return(new BinaryExpr(_parser.PrevNonCommentLocation, left, _parser.PrevNonCommentToken, Expression(JSTokenizer.PrecedenceLevel(_parser.PrevNonCommentToken)))); }
NotSupportedException UnsupportedOperatorException() { string msg = String.Format("Unsupported unary operator: '{0}' ({1}).", JSTokenizer.Explain(Expr.TokenType), (int)Expr.TokenType); return(new NotSupportedException(msg)); }