private Expression ParsePrimaryExpression() { int start, end, globalStart; Expression ret; // lambda handling List<Parameter> parameters = new List<Parameter>(); Parameter param; bool startBody = false; switch (PeekToken().Kind) { case TokenKind.Name: NameToken nameToken = (NameToken)NextToken(); globalStart = GetStart(); if (_sink != null) _sink.StartName(GetSourceSpan(), nameToken.Name); ret = new NameExpression(nameToken.Name); ret.SetLoc(_globalParent, GetStart(), GetEnd()); if (MaybeEat(TokenKind.Arrow)) { param = new Parameter(nameToken.Name); param.SetLoc(_globalParent, ret.IndexSpan); parameters.Add(param); startBody = true; goto lambda; } return ret; case TokenKind.Constant: ConstantValueToken constantToken = (ConstantValueToken)NextToken(); start = GetStart(); object cv = constantToken.Value; if (cv == null) { ret = new ConstantExpression(null); } else if (cv is bool) { ret = new ConstantExpression((bool)cv); } else if (cv is string) { ret = new ConstantExpression((string)cv); } else if (cv is int) { ret = new ConstantExpression((int)cv); } else if (cv is Uninitialized) { ret = new ConstantExpression(Uninitialized.Instance); } else if (cv is double) { ret = new ConstantExpression((double)cv); } else if (cv is BigInteger) { ret = new ConstantExpression((BigInteger)cv); } else { throw Assert.Unreachable; } ret.SetLoc(_globalParent, GetStart(), GetEnd()); return ret; case TokenKind.LeftParenthesis: NextToken(); start = GetStart(); globalStart = GetStart(); if (PeekToken().Kind == TokenKind.Name) // may be lambda: (a = 2) => a; { NameToken nt = (NameToken)NextToken(); if (PeekToken().Kind == TokenKind.RightParenthesis) { end = GetEnd(); start = GetStart(); NextToken(); if (MaybeEat(TokenKind.Arrow)) { param = new Parameter(nt.Name); param.SetLoc(_globalParent, GetStart(), end); parameters.Add(param); startBody = true; goto lambda; } else { ret = new NameExpression(nt.Name); ret.SetLoc(_globalParent, start, end); ret = new ParenthesisExpression(ret); ret.SetLoc(_globalParent, globalStart, GetEnd()); return ret; } } else if (PeekToken().Kind == TokenKind.Assign) { end = GetEnd(); start = GetStart(); NextToken(); var left = new NameExpression(nt.Name); left.SetLoc(_globalParent, start, end); var right = ParseExpression(); if (PeekToken().Kind == TokenKind.RightParenthesis) { end = GetEnd(); NextToken(); if (MaybeEat(TokenKind.Arrow)) { param = new Parameter(nt.Name, right); param.SetLoc(_globalParent, left.StartIndex, right.EndIndex); parameters.Add(param); startBody = true; goto lambda; } else { ret = new AssignExpression(TokenKind.Assign, left, right); ret.SetLoc(_globalParent, start, end); ret = new ParenthesisExpression(ret); ret.SetLoc(_globalParent, globalStart, GetEnd()); return ret; } } else if (PeekToken().Kind == TokenKind.Comma) { param = new Parameter(nt.Name, right); param.SetLoc(_globalParent, start, GetEnd()); parameters.Add(param); goto lambda; } else { throw Assert.Unreachable; } } else if (PeekToken().Kind == TokenKind.Comma) { param = new Parameter(nt.Name); param.SetLoc(_globalParent, GetStart(), GetEnd()); parameters.Add(param); goto lambda; } else { throw Assert.Unreachable; } } else if (PeekToken(TokenKind.RightParenthesis)) { goto lambda; } else // not NameToken nor RightParen { ret = new ParenthesisExpression(ParseExpression()); Eat(TokenKind.RightParenthesis); ret.SetLoc(_globalParent, globalStart, GetEnd()); return ret; } lambda: // parse the rest of the lambda if (!startBody) { while (MaybeEat(TokenKind.Comma)) { NameToken nt = (NameToken)NextToken(TokenKind.Name); start = GetStart(); Expression defaultVal = MaybeEat(TokenKind.Assign) ? ParseExpression() : null; param = new Parameter(nt.Name, defaultVal); param.SetLoc(_globalParent, start, GetEnd()); parameters.Add(param); } Eat(TokenKind.RightParenthesis); Eat(TokenKind.Arrow); } return ParseLambdaBody(globalStart, parameters.ToArray()); case TokenKind.LeftBracket: return ParseArrayLiteral(); default: return null; // syntax error } }
// assignment_expression: conditional_expression ( '=' conditional_expression )* private Expression ParseAssignmentExpression() { Expression ret = ParseConditionalExpression(); if (ret == null) return ret; while (IsAssignToken(PeekToken())) { var token = NextToken(); var start = ret.StartIndex; ret = new AssignExpression(token.Kind, ret, ParseConditionalExpression()); ret.SetLoc(_globalParent, start, GetEnd()); } return ret; }
public override bool Walk(AssignExpression node) { node.Parent = _currentScope; return true; }