bool token::is_stack_operation(stack_operation operation) const { if (is_stack_operation()) { return get_stack_operation() == operation; } return false; }
dcpu16operand parseoperand(list *labels) { dcpu16operand op = {0}; dcpu16token tok; op.addressing = IMMEDIATE; if ((tok = nexttoken()) == T_IDENTIFIER) { /* label */ op.type = LABEL; op.label = getnewlabel(labels, cur_tok.string)->label; } else if (tok == T_NUMBER) { /* numeric */ op.type = LITERAL; op.numeric = cur_tok.number; } else if (is_register(tok) || is_status_register(tok) || is_stack_operation(tok)) { /* register */ /* * For all intents and purposes, stack operations, registers and * status registers are equivalent in usage for immediate addressing, * so we might as well classify them all as REGISTER */ op.type = REGISTER; op.token = tok; } else if (tok == T_LBRACK) { /* [reference] */ dcpu16token a = nexttoken(); op.addressing = REFERENCE; if (a == T_NUMBER) { /* [numeric] */ op.type = LITERAL; op.numeric = cur_tok.number; } else if (is_register(a)) { /* [register] */ op.type = REGISTER; op.token = a; } else if (a == T_IDENTIFIER) { /* [label] */ op.type = LABEL; op.label = getnewlabel(labels, cur_tok.string)->label; } else { error("Expected numeric, register or label, got %s", toktostr(a)); } /* First part parsed correctly so far, now either ']' or '+' * follows */ if (((tok = nexttoken()) != T_RBRACK) && (tok != T_PLUS)) error("Expected '+' or ']', got %s", toktostr(tok)); if (tok == T_RBRACK) { /* [numeric], [register], [label] checks out */ return op; } else { dcpu16token b = nexttoken(); op.type = REGISTER_OFFSET; if (is_register(a)) { /* [register + label], [register + numeric] */ if (b == T_IDENTIFIER) { op.register_offset.type = LABEL; op.register_offset.register_index = a; op.register_offset.label = getnewlabel(labels, cur_tok.string)->label; } else if (b == T_NUMBER) { op.register_offset.type = LITERAL; op.register_offset.register_index = a; op.register_offset.offset = cur_tok.number; } else { error("Expected numeric or label, got %s", toktostr(b)); } } else { /* [numeric + register], [label + register] */ if (is_register(b)) { op.register_offset.register_index = b; if (a == T_NUMBER) { op.register_offset.type = LITERAL; op.register_offset.offset = cur_tok.number; } else { op.register_offset.type = LABEL; op.register_offset.label = getnewlabel(labels, cur_tok.string)->label; } } else { error("Expected register, got %s", toktostr(b)); } } if (nexttoken() != T_RBRACK) error("Expected ']'"); } } else { error("Expected register, label, numeric or '[', got %s", toktostr(tok)); } return op; }