static struct block *cast_expression(struct block *block) { struct typetree *type; struct token tok; struct symbol *sym; /* This rule needs two lookahead; to see beyond the initial parenthesis if * it is actually a cast or an expression. */ if (peek().token == '(') { tok = peekn(2); switch (tok.token) { case IDENTIFIER: sym = sym_lookup(&ns_ident, tok.strval); if (!sym || sym->symtype != SYM_TYPEDEF) break; case FIRST(type_name): consume('('); type = declaration_specifiers(NULL); if (peek().token != ')') { type = declarator(type, NULL); } consume(')'); block = cast_expression(block); block->expr = eval_cast(block, block->expr, type); return block; default: break; } } return unary_expression(block); }
Expression *ExpressionBuilder::unary_expression() { switch (next()) { case '+': return createUnaryExpression('+', unary_expression()); case '-': return createUnaryExpression('-', unary_expression()); case '!': return createUnaryExpression('!', unary_expression()); case '~': return createUnaryExpression('~', unary_expression()); case Token_defined: { int identifierIndex = 0; if (test(Token_identifier)) { identifierIndex = i - 1; } else if (test('(')) { if (test(Token_identifier)) identifierIndex = i -1; test(')'); } return createMacroReference(MacroReference::DefinedRef, createTokenList(identifierIndex)); } default: prev(); return primary_expression(); } }
/** 乘除类表达式 <multiplicative_expression>::=<unary_expression> {<TK_STAR><unary_expression> |<TK_DIVIDE><unary_expression> |<TK_MOD><unary_expression>} */ void multiplicative_expression(){ unary_expression(); while(TK_STAR == token || TK_DIVIDE == token || TK_MOD == token){ get_token(); unary_expression(); } }
static sl_node_base_t* mul_expression(sl_parse_state_t* ps) { sl_node_base_t* left = unary_expression(ps); sl_node_base_t* right; sl_token_t* tok; while(peek_token(ps)->type == SL_TOK_TIMES || peek_token(ps)->type == SL_TOK_DIVIDE || peek_token(ps)->type == SL_TOK_MOD) { tok = next_token(ps); right = unary_expression(ps); left = sl_make_send_node(ps, left, sl_intern2(ps->vm, tok->str), 1, &right); } return left; }
int assignment_expression(void) { if( conditional_expression() ) { } else if( unary_expression() ) { assignment_operator(); assignment_expression(); } }
static sl_node_base_t* unary_expression(sl_parse_state_t* ps) { sl_node_base_t* expr; sl_token_t* tok; switch(peek_token(ps)->type) { case SL_TOK_MINUS: tok = next_token(ps); expr = unary_expression(ps); return sl_make_send_node(ps, expr, sl_intern(ps->vm, "negate"), 0, NULL); case SL_TOK_TILDE: tok = next_token(ps); expr = unary_expression(ps); return sl_make_send_node(ps, expr, sl_intern2(ps->vm, tok->str), 0, NULL); case SL_TOK_NOT: next_token(ps); expr = unary_expression(ps); return sl_make_unary_node(ps, expr, SL_NODE_NOT); case SL_TOK_RETURN: tok = next_token(ps); if(!(ps->scope->flags & SL_PF_CAN_RETURN)) { error(ps, sl_make_cstring(ps->vm, "Can't return outside of a method or lambda"), tok); } switch(peek_token(ps)->type) { case SL_TOK_SEMICOLON: case SL_TOK_CLOSE_BRACE: case SL_TOK_CLOSE_TAG: /* in these case we want to allow for postfix control structures: */ case SL_TOK_IF: case SL_TOK_UNLESS: return sl_make_unary_node(ps, sl_make_immediate_node(ps, ps->vm->lib.nil), SL_NODE_RETURN); default: return sl_make_unary_node(ps, low_precedence_logical_expression(ps), SL_NODE_RETURN); } break; case SL_TOK_THROW: next_token(ps); return sl_make_unary_node(ps, low_precedence_logical_expression(ps), SL_NODE_THROW); case SL_TOK_USE: return use_expression(ps); default: return power_expression(ps); } }
// Parse a unary expression. // // unary-expression: // postfix-expression // '!' unary-expression // '-' unary-expression // '+' unary-expression // '~' unary-expression // Expr& Parser::unary_expression() { if (Token tok = match_if(tk::bang_tok)) { Expr& e = unary_expression(); return on_logical_not_expression(tok, e); } else if (Token tok = match_if(tk::minus_tok)) { Expr& e = unary_expression(); return on_neg_expression(tok, e); } else if (Token tok = match_if(tk::plus_tok)) { Expr& e = unary_expression(); return on_pos_expression(tok, e); } else if (Token tok = match_if(tk::caret_tok)) { Expr& e = unary_expression(); return on_compl_expression(tok, e); } else { return postfix_expression(); } }
int PP_Expression::unary_expression() { switch (next()) { case PP_PLUS: return unary_expression(); case PP_MINUS: return -unary_expression(); case PP_NOT: return !unary_expression(); case PP_TILDE: return ~unary_expression(); case PP_MOC_TRUE: return 1; case PP_MOC_FALSE: return 0; default: prev(); return primary_expression(); } }
int cast_expression(void) { if ( unary_expression() ) { } else if ( lookaheadT.type == LPAREN ) { match(LPAREN); type_name(); match(RPAREN); cast_expression(); } else { abort(); } }
struct Symbol* cast_expression(struct CastExpression* node) { struct Symbol* symbol = 0; if (node->type == 0) return unary_expression(node->unaryExpression, &symbol); int specifier = 0, stars = 0; typename2specifier(node->typeName, &specifier, &stars); symbol = cast_expression(node->castExpression); symbol = load_symbol(symbol); symbol = cast_symbol(symbol, specifier, stars); return cast_expression(node->castExpression); }
// Parse a multiplicative expression. // // multiplicative-expression: // unary-expression: // multiplicative-expression '*' unary-expression // multiplicative-expression '/' unary-expression // multiplicative-expression '%' unary-expression Expr& Parser::multiplicative_expression() { Expr* e1 = &unary_expression(); while (true) { // Use a switch? if (Token tok = match_if(tk::star_tok)) { Expr& e2 = unary_expression(); e1 = &on_mul_expression(tok, *e1, e2); } else if (Token tok = match_if(tk::slash_tok)) { Expr& e2 = unary_expression(); e1 = &on_div_expression(tok, *e1, e2); } else if (Token tok = match_if(tk::percent_tok)) { Expr& e2 = unary_expression(); e1 = &on_rem_expression(tok, *e1, e2); } else { break; } } return *e1; }
/** 一元表达式 <unary_expression>::=<postfix_expression> |<TK_AND><unary_expression> |<TK_STAE><unary_expression> |<TK_PLUS><unary_expression> |<TK_MINUS><unary_expression> |<sizeof_expression> */ void unary_expression(){ switch(token){ case TK_AND:case TK_STAR:case TK_PLUS:case TK_MINUS: get_token(); unary_expression(); break; case KW_SIZEOF: sizeof_expression(); break; default: postfix_expression(); break; } }
Expression *ExpressionBuilder::multiplicative_expression() { Expression *value = unary_expression(); switch (next()) { case '*': return createBinaryExpression('*', value, multiplicative_expression()); case '%': return createBinaryExpression('%', value, multiplicative_expression()); case '/': return createBinaryExpression('/', value, multiplicative_expression()); default: prev(); return value; }; }
int unary_expression(void) { if( postfix_expression() ) { } else if( lookaheadT.type == INC_OP ) { match(INC_OP); unary_expression(); } else if( lookaheadT.type == DEC_OP ) { match(DEC_OP); unary_expression(); } else if( unary_operator() ) { cast_expression(); } else if( lookaheadT.type == SIZEOF ) { match(SIZEOF); if( unary_expression() ) { } else if( lookaheadT.type == LPAREN ) { match(LPAREN); type_name(); match(RPAREN); } else { abort(); } } else { abort(); } }
// Parse an additive expression. // // additive-expression: // multiplicative-expression: // additive-expression '+' multiplicative-expression // additive-expression '-' multiplicative-expression Expr& Parser::additive_expression() { Expr* e1 = &multiplicative_expression(); while (true) { if (Token tok = match_if(tk::plus_tok)) { Expr& e2 = multiplicative_expression(); e1 = &on_add_expression(tok, *e1, e2); } else if (Token tok = match_if(tk::minus_tok)) { Expr& e2 = unary_expression(); e1 = &on_sub_expression(tok, *e1, e2); } else { break; } } return *e1; }
int PP_Expression::multiplicative_expression() { int value = unary_expression(); switch (next()) { case PP_STAR: return value * multiplicative_expression(); case PP_PERCENT: { int remainder = multiplicative_expression(); return remainder ? value % remainder : 0; } case PP_SLASH: { int div = multiplicative_expression(); return div ? value / div : 0; } default: prev(); return value; }; }
struct Symbol* unary_expression(struct UnaryExpression* node, struct Symbol** orig_symbol) { int len; struct Symbol *symbol, *symbol1 = NULL; switch (node->type) { case 0: return postfix_expression(node->postfixExpression, orig_symbol); case 1: case 2: symbol = load_symbol(unary_expression(node->unaryExpression, orig_symbol)); test_changeable(*orig_symbol); if (node->type == 2) symbol1 = test_calculable(symbol, '-'); else symbol1 = test_calculable(symbol, '+'); if (symbol1) return symbol1; ADDSTRING(" "); symbol1 = new_symbol("", symbol->storage, symbol->qualifier, symbol->specifier, symbol->stars - 1, 0, symbol->length); code_gen_symbol('%', symbol1); ADDSTRING(" = "); if ((symbol->specifier & (3 << 6)) > 0) { ADDSTRING("f"); } if (node->type == 1) { ADDSTRING("add "); } else { ADDSTRING("sub "); } code_gen_type_specifier(symbol->specifier,1,symbol->length, symbol->stars); ADDSTRING(" "); code_gen_symbol('%', symbol); ADDSTRING(", "); if ((symbol->specifier & (3 << 6)) > 0) { ADDSTRING("1.000000e+00\n"); } else { ADDSTRING("1\n"); } ADDSTRING(" store "); code_gen_type_specifier(symbol->specifier,0,symbol->length, symbol->stars); ADDSTRING(" "); code_gen_symbol('%', symbol1); ADDSTRING(", "); code_gen_type_specifier(symbol->specifier,0,symbol->length, symbol->stars); ADDSTRING("* "); code_gen_symbol('%', *orig_symbol); ADDSTRING(", align "); int l = len_gen_type_specifier(symbol->specifier); sprintf(buf, "%d", l); ADDSTRING(buf); ADDSTRING("\n"); *orig_symbol = 0; break; case 3: symbol = cast_expression(node->castExpression); switch (node->unaryOperator) { case 1: test_pointable(symbol); symbol = symbol->reference; *orig_symbol = 0; symbol1 = new_symbol("", symbol->storage, 2, symbol->specifier, symbol->stars + 1, 0, symbol->length); ADDSTRING(" "); code_gen_symbol('%', symbol1); ADDSTRING(" = getelementptr inbounds "); code_gen_type_specifier(symbol->specifier, 0, symbol->length, symbol1->stars); ADDSTRING(" "); code_gen_symbol('%', symbol); ADDSTRING(", "); ADDSTRING(PTR_LEN_TYPE); ADDSTRING(" 0\n"); break; case 2: test_referenceable(symbol); symbol = load_symbol(symbol); symbol1 = new_symbol("", symbol->storage, 0, symbol->specifier, symbol->stars - 1, 0, symbol->length); *orig_symbol = symbol1; if (symbol1->stars == 0) symbol1->specifier = 32; symbol1->reference = symbol; ADDSTRING(" "); code_gen_symbol('%', symbol1); ADDSTRING(" = load "); code_gen_type_specifier(symbol->specifier, 0, symbol->length, symbol->stars); ADDSTRING(" "); code_gen_symbol('%', symbol); ADDSTRING(" "); code_gen_symbol('%', symbol); ADDSTRING(", align 8\n"); break; case 3: test_regular(symbol); symbol1 = symbol; *orig_symbol = 0; break; case 4: test_regular(symbol); symbol = load_symbol(symbol); symbol1 = test_calculable(symbol, 'n'); if (symbol1) { return symbol1; } symbol1 = new_symbol("", symbol->storage, 2, symbol->specifier, symbol->stars, 0, 0); *orig_symbol = symbol; ADDSTRING(" "); code_gen_symbol('%', symbol1); if ((symbol->specifier & (3 << 6)) != 0) { ADDSTRING(" = f"); } else { ADDSTRING(" = "); } ADDSTRING("sub "); code_gen_type_specifier(symbol->specifier,1, symbol->length, symbol->stars); ADDSTRING(" "); if ((symbol->specifier & (3 << 6)) != 0) { ADDSTRING("0.000000e+00"); } else { ADDSTRING("0"); } ADDSTRING(", "); code_gen_symbol('%', symbol); ADDSTRING("\n"); *orig_symbol = 0; break; case 5: test_integer(symbol); symbol = load_symbol(symbol); symbol1 = test_calculable(symbol, '~'); if (symbol1) { return symbol1; } *orig_symbol = 0; symbol = cast_symbol(symbol, 16, 0); symbol1 = new_symbol("", symbol->storage, symbol->qualifier, symbol->specifier, symbol->stars, 0, symbol->length); ADDSTRING(" "); code_gen_symbol('%', symbol1); ADDSTRING(" = xor "); code_gen_type_specifier(symbol->specifier,0, symbol->length, symbol->stars); ADDSTRING(" "); code_gen_symbol('%', symbol); ADDSTRING(", -1"); ADDSTRING("\n"); break; case 6: *orig_symbol = 0; symbol1 = test_calculable(symbol, '!'); symbol = load_symbol(symbol); if (symbol1) { return symbol1; } symbol1 = new_symbol("0", 0, 2, 16, 0, 2, 0); symbol1 = equality_symbol(symbol, symbol1, 2, 1); break; default: break; } break; case 4: *orig_symbol = 0; symbol = unary_expression(node->unaryExpression, orig_symbol); if (symbol->stars > (symbol->length > 0)) len = PTR_LENGTH; else { len = len_gen_type_specifier(symbol->specifier); if (symbol->length) len *= symbol->length; } sprintf(buf, "%d", len); symbol1 = new_symbol(buf, 0, 2, 4, 0, 2, 0); break; case 5: *orig_symbol = 0; len = len_gen_type_name(node->typeName); sprintf(buf, "%d", len); symbol1 = new_symbol(buf, 0, 2, 4, 0, 2, 0); break; default: break; } return symbol1; }
struct Symbol* assignment_expression(struct AssignmentExpression* node) { if (node->type == 0) return conditional_expression(node->conditionalExpression); // to do struct Symbol* orig_symbol; struct Symbol* symbol2 = load_symbol(assignment_expression(node->assignmentExpression)); struct Symbol* symbol1 = unary_expression(node->unaryExpression, &orig_symbol); struct Symbol* symbol3 = 0; int specifier = symbol1->specifier; test_changeable(orig_symbol); if (node->assignmentOperator > 1) { switch (node->assignmentOperator) { case 2: symbol3 = multiplicative_symbol(symbol1, symbol2, 1); break; case 3: symbol3 = multiplicative_symbol(symbol1, symbol2, 2); break; case 4: symbol3 = multiplicative_symbol(symbol1, symbol2, 3); break; case 5: symbol3 = additive_symbol(symbol1, symbol2, 1); break; case 6: symbol3 = additive_symbol(symbol1, symbol2, 2); break; case 7: symbol3 = shift_symbol(symbol1, symbol2, 1); break; case 8: symbol3 = shift_symbol(symbol1, symbol2, 2); break; case 9: symbol3 = and_symbol(symbol1, symbol2, 1); break; case 10: symbol3 = exclusive_or_symbol(symbol1, symbol2, 1); break; case 11: symbol3 = inclusive_or_symbol(symbol1, symbol2, 1); break; default: break; } } else symbol3 = symbol2; symbol3 = cast_symbol(symbol3, orig_symbol->specifier, orig_symbol->stars); ADDSTRING(" store "); code_gen_type_specifier(symbol1->specifier,0,symbol1->length,symbol1->stars); ADDSTRING(" "); code_gen_symbol('%', symbol3); ADDSTRING(", "); code_gen_type_specifier(orig_symbol->specifier,0,orig_symbol->length,orig_symbol->stars); ADDSTRING("* "); code_gen_symbol('%',orig_symbol); ADDSTRING(", align "); int l = len_gen_type_specifier(specifier); sprintf(buf, "%d", l); ADDSTRING(buf); ADDSTRING("\n"); return symbol3; }
static struct block *unary_expression(struct block *block) { struct var value; switch (peek().token) { case '&': consume('&'); block = cast_expression(block); block->expr = eval_addr(block, block->expr); break; case '*': consume('*'); block = cast_expression(block); block->expr = eval_deref(block, block->expr); break; case '!': consume('!'); block = cast_expression(block); block->expr = eval_expr(block, IR_OP_EQ, var_int(0), block->expr); break; case '~': consume('~'); block = cast_expression(block); block->expr = eval_expr(block, IR_NOT, block->expr); break; case '+': consume('+'); block = cast_expression(block); block->expr.lvalue = 0; break; case '-': consume('-'); block = cast_expression(block); block->expr = eval_expr(block, IR_OP_SUB, var_int(0), block->expr); break; case SIZEOF: { struct typetree *type; struct block *head = cfg_block_init(), *tail; consume(SIZEOF); if (peek().token == '(') { switch (peekn(2).token) { case FIRST(type_name): consume('('); type = declaration_specifiers(NULL); if (peek().token != ')') { type = declarator(type, NULL); } consume(')'); break; default: tail = unary_expression(head); type = (struct typetree *) tail->expr.type; break; } } else { tail = unary_expression(head); type = (struct typetree *) tail->expr.type; } if (is_function(type)) { error("Cannot apply 'sizeof' to function type."); } if (!size_of(type)) { error("Cannot apply 'sizeof' to incomplete type."); } block->expr = var_int(size_of(type)); break; } case INCREMENT: consume(INCREMENT); block = unary_expression(block); value = block->expr; block->expr = eval_expr(block, IR_OP_ADD, value, var_int(1)); block->expr = eval_assign(block, value, block->expr); break; case DECREMENT: consume(DECREMENT); block = unary_expression(block); value = block->expr; block->expr = eval_expr(block, IR_OP_SUB, value, var_int(1)); block->expr = eval_assign(block, value, block->expr); break; default: block = postfix_expression(block); break; } return block; }