static BOOL parse_cc_identifier(parser_ctx_t *ctx, const WCHAR **ret, unsigned *ret_len) { if(*ctx->ptr != '@') { lex_error(ctx, JS_E_EXPECTED_AT); return FALSE; } if(!is_identifier_first_char(*++ctx->ptr)) { lex_error(ctx, JS_E_EXPECTED_IDENTIFIER); return FALSE; } *ret = ctx->ptr; while(++ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr)); *ret_len = ctx->ptr - *ret; return TRUE; }
token lexer::next_token() { skip(); if (current == end) { auto location = make_location(); return token(location, token_type::END_OF_INPUT, "end of file"); } char c = next_char(); auto start = make_location(); if (c == '<') { if (consume_next_if('<')) { return token(start, token_type::OPERATOR, "<<", operator_type::SHIFT_LEFT); } else if (consume_next_if('=')) { return token(start, token_type::OPERATOR, "<=", operator_type::LTE); } else if (consume_next_if('>')) { return token(start, token_type::OPERATOR, "<>", operator_type::NEQ); } } else if (c == '>') { if (consume_next_if('>')) { return token(start, token_type::OPERATOR, "<<", operator_type::SHIFT_RIGHT); } else if (consume_next_if('=')) { return token(start, token_type::OPERATOR, "<=", operator_type::GTE); } } else if (c == '=' && consume_next_if('=')) { return token(start, token_type::OPERATOR, "==", operator_type::EQ); } else if (c == '!' && consume_next_if('=')) { return token(start, token_type::OPERATOR, "!=", operator_type::NEQ); } else if (c == '&' && consume_next_if('&')) { return token(start, token_type::OPERATOR, "&&", operator_type::AND); } else if (c == '|' && consume_next_if('|')) { return token(start, token_type::OPERATOR, "||", operator_type::OR); } else if (c == '\'') { string quoted_string = parse_quoted_string(start, c, true); if (quoted_string.length() == 0) { logger.warning(start, "empty character literal; assuming null terminator"); return token(start, token_type::INTEGER, quoted_string, 0); } if (quoted_string.length() > 1) { logger.error(start, "multi-byte character literal"); } uint8_t value = quoted_string[0]; return token(start, token_type::INTEGER, quoted_string, value); } else if (c == '"') { string quoted_string = parse_quoted_string(start, c, true); return token(start, token_type::QUOTED_STRING, quoted_string, quote_type::DOUBLE_QUOTE); } else if (c == ':' && is_identifier_first_char(peek_char())) { return token(start, token_type::LABEL, append_while(next_char(), &lexer::is_identifier_char)); } else if (c == '$' && is_identifier_first_char(peek_char())) { return token(start, token_type::SYMBOL, append_while(next_char(), &lexer::is_identifier_char), symbol_type::EXPLICIT); } else if (is_identifier_first_char(c)) { string identifier = append_while(c, &lexer::is_identifier_char); if (consume_next_if(':')) { return token(start, token_type::LABEL, identifier); } else { return parse_identifier(start, identifier); } } else if (isdigit(c)) { return parse_number(start, append_while(c, &lexer::is_identifier_char)); } else if (c == '[') { iterator start_pos = current; uint32_t start_col = column; auto stack_op_token = parse_stack_operation(start); if (stack_op_token) { return *stack_op_token; } else { current = start_pos; column = start_col; } } else if (c == '\n') { next_line(); return token(start, token_type::NEWLINE, "newline"); } return token(start, token_type::CHARACTER, c); }