private Expression PrimaryExpression() { if (Current.Kind == TokenKind.StringStart) return ReadString(); if (Current.Kind == TokenKind.ID) { Token id = Consume(); Expression exp; // if ( follows ID, we have a function call if (Current.Kind == TokenKind.LParen) { Consume(); // consume LParen Expression[] args = ReadArguments(); Consume(TokenKind.RParen); exp = new FunctionCallExpression(id.Line, id.Column, id.Text, args); } else // else, we just have id exp = new IdExpression(id.Line, id.Column, id.Text); // while we have ".", keep chaining up field access or method call while (Current.Kind == TokenKind.Dot || Current.Kind == TokenKind.LBracket) { if (Current.Kind == TokenKind.Dot) { Consume(); // consume DOT Token field = Consume(TokenKind.ID); // consume ID after dot // if "(" after ID, then it's a method call if (Current.Kind == TokenKind.LParen) { Consume(); // consume "(" Expression[] args = ReadArguments(); Consume(TokenKind.RParen); // read ")" exp = new MethodCallExpression(field.Line, field.Column, exp, field.Text, args); } else exp = new FieldAccessExpression(field.Line, field.Column, exp, field.Text); } else { // must be LBracket // array access Token bracket = Current; Consume(); // consume [ Expression indexExp = TopExpression(); Consume(TokenKind.RBracket); exp = new ArrayAccessExpression(bracket.Line, bracket.Column, exp, indexExp); } } return exp; } if (Current.Kind == TokenKind.Integer) { int value = Int32.Parse(Current.Text); IntegerLiteralExpression intLiteral = new IntegerLiteralExpression(Current.Line, Current.Column, value); Consume(); // consume int return intLiteral; } if (Current.Kind == TokenKind.Double) { double value = Double.Parse(Current.Text); DoubleLiteralExpression dLiteral = new DoubleLiteralExpression(Current.Line, Current.Column, value); Consume(); // consume int return dLiteral; } if (Current.Kind == TokenKind.BooleanTrue) { BooleanLiteralExpression bLiteral = new BooleanLiteralExpression(Current.Line, Current.Column, true); Consume(); return bLiteral; } if (Current.Kind == TokenKind.BooleanFalse) { BooleanLiteralExpression bLiteral = new BooleanLiteralExpression(Current.Line, Current.Column, false); Consume(); return bLiteral; } if (Current.Kind == TokenKind.LParen) { Consume(); // eat ( Expression exp = TopExpression(); Consume(TokenKind.RParen); // eat ) return exp; } throw new ParseException("Invalid token in expression: " + Current.Kind + ". Was expecting ID or string.", Current.Line, Current.Column); }
private object EvaluateArrayAccess(ArrayAccessExpression arrayAccess) { object obj = EvaluateExpression(arrayAccess.Expression); object index = EvaluateExpression(arrayAccess.Index); if (obj is Array) { Array array = (Array)obj; if (index is int) return array.GetValue((int)index); throw new TemplateException("Index of array has to be integer", arrayAccess.Line, arrayAccess.Column); } return EvaluateMethodCall(obj, "get_Item", new object[] { index }); }