};
+static njs_lexer_token_t *njs_lexer_token_push(njs_vm_t *vm,
+ njs_lexer_t *lexer);
+static njs_lexer_token_t *njs_lexer_token_pop(njs_lexer_t *lexer);
+static njs_token_t njs_lexer_token_name_resolve(njs_lexer_t *lexer,
+ njs_lexer_token_t *lt);
static njs_token_t njs_lexer_next_token(njs_lexer_t *lexer,
njs_lexer_token_t *lt);
static njs_token_t njs_lexer_word(njs_lexer_t *lexer, njs_lexer_token_t *lt,
lexer->line = 1;
lexer->keywords_hash = vm->shared->keywords_hash;
- lexer->lexer_token = nxt_mp_alloc(vm->mem_pool, sizeof(njs_lexer_token_t));
- if (nxt_slow_path(lexer->lexer_token == NULL)) {
- return NXT_ERROR;
- }
+ nxt_queue_init(&lexer->preread);
return NXT_OK;
}
njs_token_t
-njs_lexer_token(njs_lexer_t *lexer)
+njs_lexer_token(njs_vm_t *vm, njs_lexer_t *lexer)
{
njs_lexer_token_t *lt;
- lt = lexer->lexer_token;
-
lexer->prev_start = lexer->start;
- lexer->prev_token = lt->token;
-
- lt->token = njs_lexer_next_token(lexer, lt);
- if (lt->token == NJS_TOKEN_NAME) {
- njs_lexer_keyword(lexer, lt);
+ if (lexer->lexer_token != NULL) {
+ lexer->prev_token = lexer->lexer_token->token;
+ nxt_mp_free(vm->mem_pool, lexer->lexer_token);
+ }
- if (lexer->property) {
- lexer->property_token = lt->token;
- return NJS_TOKEN_NAME;
+ if (nxt_queue_is_empty(&lexer->preread)) {
+ lt = njs_lexer_token_push(vm, lexer);
+ if (nxt_slow_path(lt == NULL)) {
+ return NJS_TOKEN_ERROR;
}
}
- return lt->token;
+ lexer->lexer_token = njs_lexer_token_pop(lexer);
+
+ return njs_lexer_token_name_resolve(lexer, lexer->lexer_token);
}
njs_token_t
-njs_lexer_peek_token(njs_lexer_t *lexer)
+njs_lexer_peek_token(njs_vm_t *vm, njs_lexer_t *lexer, size_t offset)
{
- u_char *start;
- njs_token_t token;
+ size_t i;
+ nxt_queue_link_t *link;
+ njs_lexer_token_t *lt;
- start = lexer->start;
+ /* GCC and Clang complain about uninitialized lt. */
+ lt = NULL;
- while (start < lexer->end) {
- token = njs_tokens[*start++];
+ link = nxt_queue_first(&lexer->preread);
- switch (token) {
- case NJS_TOKEN_SPACE:
- case NJS_TOKEN_LINE_END:
- continue;
+ for (i = 0; i <= offset; i++) {
- default:
- return token;
+ if (link != nxt_queue_tail(&lexer->preread)) {
+
+ lt = nxt_queue_link_data(link, njs_lexer_token_t, link);
+
+ /* NJS_TOKEN_DIVISION stands for regexp literal. */
+
+ if (lt->token == NJS_TOKEN_DIVISION
+ || lt->token == NJS_TOKEN_END)
+ {
+ break;
+ }
+
+ link = nxt_queue_next(link);
+
+ } else {
+
+ lt = njs_lexer_token_push(vm, lexer);
+
+ if (nxt_slow_path(lt == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
}
}
- return NJS_TOKEN_END;
+ return njs_lexer_token_name_resolve(lexer, lt);
+}
+
+
+static njs_lexer_token_t *
+njs_lexer_token_push(njs_vm_t *vm, njs_lexer_t *lexer)
+{
+ njs_lexer_token_t *lt;
+
+ lt = nxt_mp_alloc(vm->mem_pool, sizeof(njs_lexer_token_t));
+ if (nxt_slow_path(lt == NULL)) {
+ return NULL;
+ }
+
+ lt->token = njs_lexer_next_token(lexer, lt);
+
+ nxt_queue_insert_tail(&lexer->preread, <->link);
+
+ return lt;
+}
+
+
+static njs_lexer_token_t *
+njs_lexer_token_pop(njs_lexer_t *lexer)
+{
+ nxt_queue_link_t *lnk;
+
+ lnk = nxt_queue_first(&lexer->preread);
+ nxt_queue_remove(lnk);
+
+ return nxt_queue_link_data(lnk, njs_lexer_token_t, link);
+}
+
+
+static njs_token_t
+njs_lexer_token_name_resolve(njs_lexer_t *lexer, njs_lexer_token_t *lt)
+{
+ if (lt->token == NJS_TOKEN_NAME) {
+ njs_lexer_keyword(lexer, lt);
+
+ if (lexer->property) {
+ lexer->property_token = lt->token;
+ return NJS_TOKEN_NAME;
+ }
+ }
+
+ return lt->token;
}
}
}
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
while (token != NJS_TOKEN_END) {
*dest = node;
while (token == NJS_TOKEN_SEMICOLON) {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
break;
}
return njs_parser_try_statement(vm, parser);
case NJS_TOKEN_SEMICOLON:
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
case NJS_TOKEN_OPEN_BRACE:
return njs_parser_block_statement(vm, parser);
default:
if (token == NJS_TOKEN_NAME
- && njs_lexer_peek_token(parser->lexer) == NJS_TOKEN_COLON)
+ && njs_lexer_peek_token(vm, parser->lexer, 0) == NJS_TOKEN_COLON)
{
return njs_parser_labelled_statement(vm, parser);
}
switch (token) {
case NJS_TOKEN_SEMICOLON:
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
case NJS_TOKEN_CLOSE_BRACE:
case NJS_TOKEN_END:
njs_token_t token;
njs_parser_node_t *node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
njs_parser_scope_end(vm, parser);
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
njs_token_t match)
{
if (nxt_fast_path(token == match)) {
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
return njs_parser_unexpected_token(vm, parser, token);
return NJS_TOKEN_ERROR;
}
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
node->token_line = njs_parser_token_line(parser);
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
return NJS_TOKEN_ERROR;
}
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
node->token_line = njs_parser_token_line(parser);
parser->node = node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
return NJS_TOKEN_ERROR;
}
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
if (nxt_slow_path(token == NJS_TOKEN_ELLIPSIS)) {
lambda->rest_parameters = 1;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return NJS_TOKEN_ILLEGAL;
}
}
if (token == NJS_TOKEN_COMMA) {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
index += sizeof(njs_value_t);
}
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
return NJS_TOKEN_ERROR;
}
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
}
}
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
parser->node = node;
- token = njs_lexer_token(parser->lexer);
+ token = njs_lexer_token(vm, parser->lexer);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
switch (token) {
case NJS_TOKEN_LINE_END:
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
case NJS_TOKEN_SEMICOLON:
case NJS_TOKEN_CLOSE_BRACE:
left = NULL;
do {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
return NJS_TOKEN_ERROR;
}
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
if (token == NJS_TOKEN_ASSIGNMENT) {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
stmt = parser->node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
}
if (token == NJS_TOKEN_CASE) {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
branch->token = NJS_TOKEN_DEFAULT;
dflt = branch;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
parser->node = swtch;
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
njs_token_t token;
njs_parser_node_t *node, *stmt;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
condition = NULL;
update = NULL;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
left = NULL;
do {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
return NJS_TOKEN_ERROR;
}
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
if (token == NJS_TOKEN_ASSIGNMENT) {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
njs_token_t token;
njs_parser_node_t *node, *foreach;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
node->token_line = njs_parser_token_line(parser);
parser->node = node;
- token = njs_lexer_token(parser->lexer);
+ token = njs_lexer_token(vm, parser->lexer);
switch (token) {
case NJS_TOKEN_LINE_END:
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
case NJS_TOKEN_NAME:
name = *njs_parser_text(parser);
return NJS_TOKEN_ERROR;
}
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
case NJS_TOKEN_SEMICOLON:
case NJS_TOKEN_CLOSE_BRACE:
try->left = parser->node;
if (token == NJS_TOKEN_CATCH) {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
catch->left = node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
njs_token_t token;
njs_parser_node_t *node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token != NJS_TOKEN_OPEN_BRACE)) {
return NJS_TOKEN_ILLEGAL;
}
return NJS_TOKEN_ERROR;
}
- token = njs_lexer_token(parser->lexer);
+ token = njs_lexer_token(vm, parser->lexer);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
{
njs_token_t token;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
parser->lexer->property = 1;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
parser->lexer->property = 0;
njs_token_t
-njs_parser_token(njs_parser_t *parser)
+njs_parser_token(njs_vm_t *vm, njs_parser_t *parser)
{
njs_token_t token;
do {
- token = njs_lexer_token(parser->lexer);
+ token = njs_lexer_token(vm, parser->lexer);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
if (token == NJS_TOKEN_OPEN_PARENTHESIS) {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
parser->node = node;
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
switch (token) {
case NJS_TOKEN_CLOSE_BRACE:
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
case NJS_TOKEN_NAME:
name = *njs_parser_text(parser);
hash = njs_parser_key_hash(parser);
token_line = njs_parser_token_line(parser);
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
break;
case NJS_TOKEN_NUMBER:
left = stmt;
if (token == NJS_TOKEN_CLOSE_BRACE) {
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
if (nxt_slow_path(token != NJS_TOKEN_COMMA)) {
left = NULL;
for ( ;; ) {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
obj->u.length = index;
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
node->u.operation = operation;
node->left = parser->node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
node->u.operation = operation;
node->left = parser->node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
return token;
}
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
node->left = parser->node;
node->left->dest = cond;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
node->left = parser->node;
node->left->dest = node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
node->left = parser->node;
node->left->dest = node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
return njs_parser_inc_dec_expression(vm, parser, token);
}
- next = njs_parser_token(parser);
+ next = njs_parser_token(vm, parser);
if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) {
return next;
}
return njs_parser_post_inc_dec_expression(vm, parser, token);
}
- next = njs_parser_token(parser);
+ next = njs_parser_token(vm, parser);
if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) {
return next;
}
node->left = parser->node;
parser->node = node;
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
parser->node = func;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
{
njs_parser_node_t *func, *node;
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
parser->node = func;
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
return NJS_TOKEN_ILLEGAL;
}
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
} else {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
return NJS_TOKEN_ERROR;
}
- return njs_parser_token(parser);
+ return njs_parser_token(vm, parser);
}
index = NJS_SCOPE_CALLEE_ARGUMENTS;
do {
- token = njs_parser_token(parser);
+ token = njs_parser_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}