/** * conditional-expression: * logical-OR-expression * logical-OR-expression ? expression : conditional-expression */ static AstExpression ParseConditionalExpression(void) { AstExpression expr; expr = ParseBinaryExpression(Prec[OP_OR]); if (CurrentToken == TK_QUESTION) { AstExpression condExpr; CREATE_AST_NODE(condExpr, Expression); condExpr->op = OP_QUESTION; condExpr->kids[0] = expr; NEXT_TOKEN; CREATE_AST_NODE(condExpr->kids[1], Expression); condExpr->kids[1]->op = OP_COLON; condExpr->kids[1]->kids[0] = ParseExpression(); Expect(TK_COLON); condExpr->kids[1]->kids[1] = ParseConditionalExpression(); return condExpr; } return expr; }
/** * Check if the initializer expression is address constant. * e.g. * int a; * int b = &a; */ static AstExpression CheckAddressConstant(AstExpression expr) { AstExpression addr; AstExpression p; int offset = 0; if (! IsPtrType(expr->ty)) return NULL; if (expr->op == OP_ADD || expr->op == OP_SUB) { addr = CheckAddressConstant(expr->kids[0]); if (addr == NULL || expr->kids[1]->op != OP_CONST) return NULL; expr->kids[0] = addr->kids[0]; expr->kids[1]->val.i[0] += (expr->op == OP_ADD ? 1 : -1) * addr->kids[1]->val.i[0]; return expr; } if (expr->op == OP_ADDRESS) addr = expr->kids[0]; else addr = expr; while (addr->op == OP_INDEX || addr->op == OP_MEMBER) { if (addr->op == OP_INDEX) { if (addr->kids[1]->op != OP_CONST) return NULL; offset += addr->kids[1]->val.i[0] * addr->ty->size; } else { Field fld = addr->val.p; offset += fld->offset; } addr = addr->kids[0]; } if (addr->op != OP_ID || (expr->op != OP_ADDRESS && ! addr->isarray && ! addr->isfunc)) return NULL; ((Symbol)addr->val.p)->ref++; CREATE_AST_NODE(p, Expression); p->op = OP_ADD; p->ty = expr->ty; p->kids[0] = addr; p->kids[1] = Constant(addr->coord, T(INT), p->val); return p; }
static AstExpression CastExpression(Type ty, AstExpression expr) { AstExpression cast; if (expr->op == OP_CONST && ty->categ != VOID) return FoldCast(ty, expr); CREATE_AST_NODE(cast, Expression); cast->coord = expr->coord; cast->op = OP_CAST; cast->ty = ty; cast->kids[0] = expr; return cast; }
/** * Construct an expression to divide diff by size */ static AstExpression PointerDifference(AstExpression diff, int size) { AstExpression expr; union value val; CREATE_AST_NODE(expr, Expression); expr->ty = diff->ty; expr->op = OP_DIV; expr->kids[0] = diff; val.i[1] = 0; val.i[0] = size; expr->kids[1] = Constant(diff->coord, diff->ty, val); return expr; }
/** * Construct an expression to multiply offset by scale. */ static AstExpression ScalePointerOffset(AstExpression offset, int scale) { AstExpression expr; union value val; CREATE_AST_NODE(expr, Expression); expr->ty = offset->ty; expr->op = OP_MUL; expr->kids[0] = offset; val.i[1] = 0; val.i[0] = scale; expr->kids[1] = Constant(offset->coord, offset->ty, val); return FoldConstant(expr); }
static AstExpression TransformIncrement(AstExpression expr) { AstExpression casgn; union value val; val.i[1] = 0; val.i[0] = 1; CREATE_AST_NODE(casgn, Expression); casgn->coord = expr->coord; casgn->op = (expr->op == OP_POSTINC || expr->op == OP_PREINC) ? OP_ADD_ASSIGN : OP_SUB_ASSIGN; casgn->kids[0] = expr->kids[0]; casgn->kids[1] = Constant(expr->coord, T(INT), val); expr->kids[0] = CheckExpression(casgn); expr->ty = expr->kids[0]->ty; return expr; }
/** * expression: * assignment-expression * expression , assignment-expression */ AstExpression ParseExpression(void) { AstExpression expr, comaExpr; expr = ParseAssignmentExpression(); while(CurrentToken == TK_COMMA) { CREATE_AST_NODE(comaExpr, Expression); comaExpr->op = OP_COMMA; comaExpr->kids[0] = expr; NEXT_TOKEN; comaExpr->kids[1] = ParseAssignmentExpression(); expr = comaExpr; } return expr; }
static AstExpression BORBitField(AstExpression expr1, AstExpression expr2) { AstExpression bor; if (expr1->op == OP_CONST && expr2->op == OP_CONST) { expr1->val.i[0] |= expr2->val.i[0]; return expr1; } CREATE_AST_NODE(bor, Expression); bor->coord = expr1->coord; bor->ty = expr1->ty; bor->op = OP_BITOR; bor->kids[0] = expr1; bor->kids[1] = expr2; return bor; }
static AstExpression CheckAssignmentExpression(AstExpression expr) { int ops[] = { OP_BITOR, OP_BITXOR, OP_BITAND, OP_LSHIFT, OP_RSHIFT, OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD }; Type ty; expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 0); expr->kids[1] = Adjust(CheckExpression(expr->kids[1]), 1); if (! CanModify(expr->kids[0])) { Error(&expr->coord, "The left operand cannot be modified"); } if (expr->op != OP_ASSIGN) { AstExpression lopr; CREATE_AST_NODE(lopr, Expression); lopr->coord = expr->coord; lopr->op = ops[expr->op - OP_BITOR_ASSIGN]; lopr->kids[0] = expr->kids[0]; lopr->kids[1] = expr->kids[1]; expr->kids[1] = (*BinaryOPCheckers[lopr->op - OP_OR])(lopr); } ty = expr->kids[0]->ty; if (! CanAssign(ty, expr->kids[1])) { Error(&expr->coord, "Wrong assignment"); } else { expr->kids[1] = Cast(ty, expr->kids[1]); } expr->ty = ty; return expr; }
/** * assignment-expression: * conditional-expression * unary-expression assignment-operator assignment-expression * assignment-operator: * = *= /= %= += -= <<= >>= &= ^= |= * There is a little twist here: the parser always treats the first nonterminal * as a conditional expression. */ AstExpression ParseAssignmentExpression(void) { AstExpression expr; expr = ParseConditionalExpression(); if (CurrentToken >= TK_ASSIGN && CurrentToken <= TK_MOD_ASSIGN) { AstExpression asgnExpr; CREATE_AST_NODE(asgnExpr, Expression); asgnExpr->op = BINARY_OP; asgnExpr->kids[0] = expr; NEXT_TOKEN; asgnExpr->kids[1] = ParseAssignmentExpression(); return asgnExpr; } return expr; }
static AstExpression PlaceBitField(Field fld, AstExpression expr) { AstExpression lsh; union value val; if (expr->op == OP_CONST) { expr->val.i[0] <<= fld->pos; return expr; } CREATE_AST_NODE(lsh, Expression); lsh->coord = expr->coord; lsh->ty = expr->ty; lsh->op = OP_LSHIFT; lsh->kids[0] = expr; val.i[1] = 0; val.i[0] = fld->pos; lsh->kids[1] = Constant(expr->coord, T(INT), val); return lsh; }
/** * Parse a binary expression, from logical-OR-expresssion to multiplicative-expression */ static AstExpression ParseBinaryExpression(int prec) { AstExpression binExpr; AstExpression expr; int newPrec; expr = ParseUnaryExpression(); /// while the following binary operater's precedence is higher than current /// binary operator's precedence, parses a higer precedence expression while (IsBinaryOP(CurrentToken) && (newPrec = Prec[BINARY_OP]) >= prec) { CREATE_AST_NODE(binExpr, Expression); binExpr->op = BINARY_OP; binExpr->kids[0] = expr; NEXT_TOKEN; binExpr->kids[1] = ParseBinaryExpression(newPrec + 1); expr = binExpr; } return expr; }
/** * primary-expression: * ID * constant * string-literal * ( expression ) */ static AstExpression ParsePrimaryExpression(void) { AstExpression expr; switch (CurrentToken) { case TK_ID: CREATE_AST_NODE(expr, Expression); expr->op = OP_ID; expr->val = TokenValue; NEXT_TOKEN; return expr; /// Notice: Only when parsing constant and string literal, /// ty member in astExpression is used since from OP_CONST /// and OP_STR alone the expression's type can't be determined case TK_INTCONST: case TK_UINTCONST: case TK_LONGCONST: case TK_ULONGCONST: case TK_LLONGCONST: case TK_ULLONGCONST: case TK_FLOATCONST: case TK_DOUBLECONST: case TK_LDOUBLECONST: CREATE_AST_NODE(expr, Expression); if (CurrentToken >= TK_FLOATCONST) CurrentToken++; /// nasty, requires that both from TK_INTCONST to TK_LDOUBLECONST /// and from INT to LDOUBLE are consecutive expr->ty = T(INT + CurrentToken - TK_INTCONST); expr->op = OP_CONST; expr->val = TokenValue; NEXT_TOKEN; return expr; case TK_STRING: case TK_WIDESTRING: CREATE_AST_NODE(expr, Expression); expr->ty = ArrayOf(((String)TokenValue.p)->len + 1, CurrentToken == TK_STRING ? T(CHAR) : WCharType); expr->op = OP_STR; expr->val = TokenValue; NEXT_TOKEN; return expr; case TK_LPAREN: NEXT_TOKEN; expr = ParseExpression(); Expect(TK_RPAREN); return expr; default: Error(&TokenCoord, "Expect identifier, string, constant or ("); return Constant0; } }
/** * unary-expression: * postfix-expression * unary-operator unary-expression * ( type-name ) unary-expression * sizeof unary-expression * sizeof ( type-name ) * * unary-operator: * ++ -- & * + - ! ~ */ static AstExpression ParseUnaryExpression() { AstExpression expr; int t; switch (CurrentToken) { case TK_INC: case TK_DEC: case TK_BITAND: case TK_MUL: case TK_ADD: case TK_SUB: case TK_NOT: case TK_COMP: CREATE_AST_NODE(expr, Expression); expr->op = UNARY_OP; NEXT_TOKEN; expr->kids[0] = ParseUnaryExpression(); return expr; case TK_LPAREN: /// When current token is (, it may be a type cast expression /// or a primary expression, we need to look ahead one token, /// if next token is type name, the expression is treated as /// a type cast expression; otherwise a primary expresion BeginPeekToken(); t = GetNextToken(); if (IsTypeName(t)) { EndPeekToken(); CREATE_AST_NODE(expr, Expression); expr->op = OP_CAST; NEXT_TOKEN; expr->kids[0] = (AstExpression)ParseTypeName(); Expect(TK_RPAREN); expr->kids[1] = ParseUnaryExpression(); return expr; } else { EndPeekToken(); return ParsePostfixExpression(); } break; case TK_SIZEOF: /// this case hase the same issue with TK_LPAREN case CREATE_AST_NODE(expr, Expression); expr->op = OP_SIZEOF; NEXT_TOKEN; if (CurrentToken == TK_LPAREN) { BeginPeekToken(); t = GetNextToken(); if (IsTypeName(t)) { EndPeekToken(); NEXT_TOKEN; /// In this case, the first kid is not an expression, /// but thanks to both type name and expression have a /// kind member to discriminate them. expr->kids[0] = (AstExpression)ParseTypeName(); Expect(TK_RPAREN); } else { EndPeekToken(); expr->kids[0] = ParseUnaryExpression(); } } else { expr->kids[0] = ParseUnaryExpression(); } return expr; default: return ParsePostfixExpression(); } }
/** * postfix-expression: * primary-expression * postfix-expression [ expression ] * postfix-expression ( [argument-expression-list] ) * postfix-expression . identifier * postfix-expression -> identifier * postfix-expression ++ * postfix-expression -- */ static AstExpression ParsePostfixExpression(void) { AstExpression expr, p; expr = ParsePrimaryExpression(); while (1) { switch (CurrentToken) { case TK_LBRACKET: CREATE_AST_NODE(p, Expression); p->op = OP_INDEX; p->kids[0] = expr; NEXT_TOKEN; p->kids[1] = ParseExpression(); Expect(TK_RBRACKET); expr = p; break; case TK_LPAREN: CREATE_AST_NODE(p, Expression); p->op = OP_CALL; p->kids[0] = expr; NEXT_TOKEN; if (CurrentToken != TK_RPAREN) { AstNode *tail; /// function call expression's second kid is actually /// a list of expression instead of a single expression p->kids[1] = ParseAssignmentExpression(); tail = &p->kids[1]->next; while (CurrentToken == TK_COMMA) { NEXT_TOKEN; *tail = (AstNode)ParseAssignmentExpression(); tail = &(*tail)->next; } } Expect(TK_RPAREN); expr = p; break; case TK_DOT: case TK_POINTER: CREATE_AST_NODE(p, Expression); p->op = (CurrentToken == TK_DOT ? OP_MEMBER : OP_PTR_MEMBER); p->kids[0] = expr; NEXT_TOKEN; if (CurrentToken != TK_ID) { Error(&p->coord, "Expect identifier as struct or union member"); } else { p->val = TokenValue; NEXT_TOKEN; } expr = p; break; case TK_INC: case TK_DEC: CREATE_AST_NODE(p, Expression); p->op = (CurrentToken == TK_INC) ? OP_POSTINC : OP_POSTDEC; p->kids[0] = expr; NEXT_TOKEN; expr = p; break; default: return expr; } } }