CiExpr ParsePrimaryExpr()
{
if (See(CiToken.Increment) || See(CiToken.Decrement) || See(CiToken.Minus) || See(CiToken.Not)) {
CiToken op = this.CurrentToken;
NextToken();
CiExpr inner = ParsePrimaryExpr();
return new CiUnaryExpr { Op = op, Inner = inner };
}
if (Eat(CiToken.CondNot)) {
CiExpr inner = ParsePrimaryExpr();
return new CiCondNotExpr { Inner = inner };
}
CiExpr result;
if (See(CiToken.IntConstant)) {
result = new CiConstExpr(this.CurrentInt);
NextToken();
}
else if (See(CiToken.StringConstant)) {
result = new CiConstExpr(this.CurrentString);
NextToken();
}
else if (Eat(CiToken.LeftParenthesis)) {
result = ParseExpr();
Expect(CiToken.RightParenthesis);
}
else if (See(CiToken.Id)) {
string name = ParseId();
if (name == "BinaryResource")
result = ParseBinaryResource();
else {
CiSymbol symbol = this.Symbols.TryLookup(name);
if (symbol is CiMacro) {
Expand((CiMacro) symbol);
Expect(CiToken.LeftParenthesis);
result = ParseExpr();
Expect(CiToken.RightParenthesis);
}
else {
if (symbol == null)
symbol = new CiUnknownSymbol { Name = name };
result = new CiSymbolAccess { Symbol = symbol };
}
}
}
else if (Eat(CiToken.New)) {
CiType newType = ParseType();
if (!(newType is CiClassStorageType || newType is CiArrayStorageType))
throw new ParseException("'new' syntax error");
result = new CiNewExpr { NewType = newType };
}
else
throw new ParseException("Invalid expression");
for (;;) {
if (Eat(CiToken.Dot))
result = new CiUnknownMemberAccess { Parent = result, Name = ParseId() };
else if (Eat(CiToken.LeftParenthesis)) {
CiMethodCall call = new CiMethodCall();
call.Obj = result;
List<CiExpr> args = new List<CiExpr>();
if (!See(CiToken.RightParenthesis)) {
do
args.Add(ParseExpr());
while (Eat(CiToken.Comma));
}
Expect(CiToken.RightParenthesis);
call.Arguments = args.ToArray();
result = call;
}
else if (Eat(CiToken.LeftBracket)) {
CiExpr index = ParseExpr();
Expect(CiToken.RightBracket);
result = new CiIndexAccess { Parent = result, Index = index };
}
else if (See(CiToken.Increment) || See(CiToken.Decrement)) {
CiToken op = this.CurrentToken;
NextToken();
return new CiPostfixExpr { Inner = result, Op = op };
}
else
return result;
}
}