protected object EvalArrayAccess(ArrayAccess arrayAccess) { object obj = EvalExpression(arrayAccess.Exp); object index = EvalExpression(arrayAccess.Index); if (obj is Array) { Array array = (Array)obj; if (index is Int32) { return array.GetValue((int)index); } else throw new TemplateRuntimeException("Index of array has to be integer", arrayAccess.Line, arrayAccess.Col); } else return EvalMethodCall(obj, "get_Item", new object[] { index }); }
Expression PrimaryExpression() { if (Current.TokenKind == TokenKind.StringStart) return ReadString(); else if (Current.TokenKind == TokenKind.ID) { Token id = Consume(); Expression exp = null; // if ( follows ID, we have a function call if (Current.TokenKind == TokenKind.LParen) { Consume(); // consume LParen Expression[] args = ReadArguments(); Consume(TokenKind.RParen); exp = new FCall(id.Line, id.Col, id.Data, args); } else // else, we just have id exp = new Name(id.Line, id.Col, id.Data); // while we have ".", keep chaining up field access or method call while (Current.TokenKind == TokenKind.Dot || Current.TokenKind == TokenKind.LBracket) { if (Current.TokenKind == 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.TokenKind == TokenKind.LParen) { Consume(); // consume "(" Expression[] args = ReadArguments(); Consume(TokenKind.RParen); // read ")" exp = new MethodCall(field.Line, field.Col, exp, field.Data, args); } else exp = new FieldAccess(field.Line, field.Col, exp, field.Data); } else // must be LBracket { // array access Token bracket = Current; Consume(); // consume [ Expression indexExp = TopExpression(); Consume(TokenKind.RBracket); exp = new ArrayAccess(bracket.Line, bracket.Col, exp, indexExp); } } return exp; } else if (Current.TokenKind == TokenKind.Integer) { int value = Int32.Parse(Current.Data); IntLiteral intLiteral = new IntLiteral(Current.Line, Current.Col, value); Consume(); // consume int return intLiteral; } else if (Current.TokenKind == TokenKind.Double) { double value = Double.Parse(Current.Data); DoubleLiteral dLiteral = new DoubleLiteral(Current.Line, Current.Col, value); Consume(); // consume int return dLiteral; } else if (Current.TokenKind == TokenKind.LParen) { Consume(); // eat ( Expression exp = TopExpression(); Consume(TokenKind.RParen); // eat ) return exp; } else throw new ParseException("Invalid token in expression: " + Current.TokenKind + ". Was expecting ID or string.", Current.Line, Current.Col); }