/* Reading the pattern itself */ static int lex_pattern(usenet_parser_t self, int ch) { /* Watch for EOF or linefeed */ if (ch == EOF || ch == '\n') { /* Null-terminate the token */ if (append_char(self, '\0') < 0) { return -1; } /* Do something interesting with the expression */ if (accept_expression(self, self->field, self->operator, self->token) < 0) { return -1; } /* This is also the end of the group entry */ if (accept_group(self, self->has_not, self->group) < 0) { return -1; } free(self->group); /* Let the start state deal with the EOF or linefeed */ return lex_start(self, ch); } /* Watch for the escape character */ if (ch == '\\') { self->state = lex_pattern_esc; return 0; } /* Watch for other whitespace */ if (isspace(ch)) { /* Record the position of the whitespace for later trimming */ self->token_mark = self->token_pointer; self->state = lex_pattern_ws; return append_char(self, ch); } /* Watch for a separator */ if (ch == '/') { /* Null-terminate the token */ if (append_char(self, '\0') < 0) { return -1; } /* Do something interesting with the expression */ self->token_pointer = self->token; self->state = lex_field_start; return accept_expression(self, self->field, self->operator, self->token); } /* Anything else is part of the pattern */ return append_char(self, ch); }
/* Reading trailing whitespace after a pattern */ static int lex_pattern_ws(usenet_parser_t self, int ch) { /* Watch for EOF and newline */ if (ch == EOF || ch == '\n') { /* Trim off the trailing whitespace */ *self->token_mark = '\0'; /* Do something interesting with the expression */ if (accept_expression(self, self->field, self->operator, self->token) < 0) { return -1; } /* This is also the end of the group entry */ if (accept_group(self, self->has_not, self->group) < 0) { return -1; } free(self->group); /* Let the start state deal with the EOF or newline */ return lex_start(self, ch); } /* Skip any other whitespace */ if (isspace(ch)) { return append_char(self, ch); } /* Watch for an escape character */ if (ch == '\\') { self->state = lex_pattern_esc; return 0; } /* Watch for a separator */ if (ch == '/') { /* Trim off the trailing whitespace */ *self->token_mark = '\0'; /* Do something interesting with the expression */ self->token_pointer = self->token; self->state = lex_field_start; return accept_expression(self, self->field, self->operator, self->token); } /* Anything else is more of the pattern */ self->state = lex_pattern; return append_char(self, ch); }
shared_ptr<Statement> Parser::accept_var_statement(const shared_ptr<Environment> environment) { if (!accept(Token(Token::IDENTIFIER, "var"))) return nullptr; Token identifier; expect(Token::IDENTIFIER, identifier); shared_ptr<Expression> initializer = make_shared<UndefinedValue>(); if (accept(Token(Token::OPERATOR, "=")) && !(initializer = accept_expression(environment))) expected("initializer"); expect(Token::SEMICOLON); return make_shared<VarStatement>(identifier.string, initializer); }