static Expression ParseUnary(Token[] toks, ref int p) { var end = toks.Length; var t = toks[p]; if (t.Type == TokenType.Subtract) { var op = t.Type; p++; var e = ParsePrimary (toks, ref p); return new UnOpExpression (op, e); } else { return ParsePrimary (toks, ref p); } }
static Expression ParseRelational(Token[] toks, ref int p) { var end = toks.Length; var e = ParseAdditive (toks, ref p); if (p < end && (toks[p].Type == TokenType.LessThan || toks[p].Type == TokenType.LessThanOrEqual || toks[p].Type == TokenType.GreaterThan || toks[p].Type == TokenType.GreaterThanOrEqual)) { var op = toks[p].Type; p++; var o = ParseAdditive (toks, ref p); e = new BinOpExpression (op, e, o); } return e; }
static string ParseTypeName(Token[] toks, ref int p) { var sb = new StringBuilder (); var end = toks.Length; var nt = TokenType.Identifier; while (p < end && toks[p].Type == nt) { if (nt == TokenType.Identifier) { sb.Append (toks[p].ToString ()); nt = TokenType.Dot; } else { sb.Append ('.'); nt = TokenType.Identifier; } p++; } return sb.ToString (); }
static ObjectLiteralExpression ParseObjectLiteral(Token[] toks, ref int p) { var e = new ObjectLiteralExpression (); var end = toks.Length; p++; // Consume '{' while (p < end) { var t = toks[p]; if (t.Type == TokenType.Identifier || t.Type == TokenType.String) { var ident = t.ToString (); p++; if (p < end && (toks[p].Type == TokenType.Colon || toks[p].Type == TokenType.Assign)) { p++; if (p < end) { var val = Parse (toks, ref p); e.Add (ident, val); } } } else if (t.Type == TokenType.RightCurly) { p++; break; } else { // Unexpected. Just keep reading until we get to a right curly p++; } } return e; }
static Expression ParsePrimary(Token[] toks, ref int p) { var end = toks.Length; Expression e = null; while (p < end) { var t = toks[p]; if (t.Type == TokenType.Identifier) { p++; var ident = t.ToString (); if (ident == "true") { e = new ConstantExpression (true); } else if (ident == "false") { e = new ConstantExpression (false); } else if (ident == "null") { e = new ConstantExpression (null); } else { e = new VariableExpression (t.ToString ()); } } else if (t.Type == TokenType.String) { p++; e = new ConstantExpression (t.ToString ()); } else if (t.Type == TokenType.Number) { p++; var intVal = 0; if (int.TryParse (t.ToString (), out intVal)) { e = new ConstantExpression (intVal); } else { var doubleVal = 0.0; if (double.TryParse (t.ToString (), out doubleVal)) { e = new ConstantExpression (doubleVal); } else { throw new ParseException ("Cannot interpret number '" + t.ToString () + "'"); } } } else if (t.Type == TokenType.LeftParen) { p++; e = Parse (toks, ref p); if (p < end && toks[p].Type == TokenType.RightParen) { p++; } else { throw new ParseException ("Expected closing ')'"); } } else if (t.Type == TokenType.LeftCurly) { var l = ParseObjectLiteral (toks, ref p); l.Constructor = new NewExpression (); e = l; } else if (t.Type == TokenType.New) { p++; var ne = new NewExpression (); e = ne; if (p < end && toks[p].Type == TokenType.Identifier) { ne.TypeName = ParseTypeName (toks, ref p); } if (p < end && toks[p].Type == TokenType.LeftParen) { var nt = TokenType.LeftParen; while (p < end && toks[p].Type == nt && toks[p].Type != TokenType.RightParen) { p++; var a = Parse (toks, ref p); if (a != null) { ne.Arguments.Add (a); } nt = TokenType.Comma; } if (p < end && toks[p].Type == TokenType.RightParen) { // Good p++; if (p < end && toks[p].Type == TokenType.LeftCurly) { var l = ParseObjectLiteral (toks, ref p); l.Constructor = ne; e = l; } } else { throw new ParseException ("Expected ')'"); } } else { throw new ParseException ("Expected '('"); } } if (p < end && toks[p].Type == TokenType.Dot) { if (p + 1 < end && toks[p + 1].Type == TokenType.Identifier) { e = new MemberExpression (e, toks[p + 1].ToString ()); p += 2; } else { break; } } else { break; } } return e; }
static Expression ParseMultiplicative(Token[] toks, ref int p) { var end = toks.Length; var e = ParseUnary (toks, ref p); while (p < end && (toks[p].Type == TokenType.Multiply || toks[p].Type == TokenType.Divide)) { var op = toks[p].Type; p++; var o = ParseUnary (toks, ref p); e = new BinOpExpression (op, e, o); } return e; }
static Expression ParseEquality(Token[] toks, ref int p) { var end = toks.Length; var e = ParseRelational (toks, ref p); if (p < end && (toks[p].Type == TokenType.Equal || toks[p].Type == TokenType.NotEqual)) { var op = toks[p].Type; p++; var o = ParseRelational (toks, ref p); e = new BinOpExpression (op, e, o); } return e; }
static Expression ParseConditionalOr(Token[] toks, ref int p) { var end = toks.Length; var e = ParseConditionalAnd (toks, ref p); while (p < end && toks[p].Type == TokenType.LogicalOr) { p++; var o = ParseConditionalAnd (toks, ref p); e = new BinOpExpression (TokenType.LogicalOr, e, o); } return e; }
static Expression ParseAdditive(Token[] toks, ref int p) { var end = toks.Length; var e = ParseMultiplicative (toks, ref p); while (p < end && (toks[p].Type == TokenType.Add || toks[p].Type == TokenType.Subtract)) { var op = toks[p].Type; p++; var o = ParseMultiplicative (toks, ref p); e = new BinOpExpression (op, e, o); } return e; }
static Expression Parse(Token[] toks, ref int p) { return ParseConditionalOr (toks, ref p); }