static void test_lex(const char *input) { struct ds output; ds_init(&output); struct lexer lexer; lexer_init(&lexer, input); ds_clear(&output); while (lexer_get(&lexer) != LEX_T_END) { size_t len = output.length; lex_token_format(&lexer.token, &output); /* Check that the formatted version can really be parsed back * losslessly. */ if (lexer.token.type != LEX_T_ERROR) { const char *s = ds_cstr(&output) + len; struct lexer l2; lexer_init(&l2, s); lexer_get(&l2); compare_token(&lexer.token, &l2.token); lexer_destroy(&l2); } ds_put_char(&output, ' '); } lexer_destroy(&lexer); ds_chomp(&output, ' '); puts(ds_cstr(&output)); ds_destroy(&output); }
static void parse_actions(struct action_context *ctx) { /* "drop;" by itself is a valid (empty) set of actions, but it can't be * combined with other actions because that doesn't make sense. */ if (ctx->lexer->token.type == LEX_T_ID && !strcmp(ctx->lexer->token.s, "drop") && lexer_lookahead(ctx->lexer) == LEX_T_SEMICOLON) { lexer_get(ctx->lexer); /* Skip "drop". */ lexer_get(ctx->lexer); /* Skip ";". */ if (ctx->lexer->token.type != LEX_T_END) { action_syntax_error(ctx, "expecting end of input"); } return; } while (ctx->lexer->token.type != LEX_T_END) { if (ctx->lexer->token.type != LEX_T_ID) { action_syntax_error(ctx, NULL); break; } enum lex_type lookahead = lexer_lookahead(ctx->lexer); if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_EXCHANGE || lookahead == LEX_T_LSQUARE) { parse_set_action(ctx); } else if (lexer_match_id(ctx->lexer, "next")) { parse_next_action(ctx); } else if (lexer_match_id(ctx->lexer, "output")) { emit_resubmit(ctx, ctx->output_ptable); } else if (lexer_match_id(ctx->lexer, "ip4.ttl")) { if (lexer_match(ctx->lexer, LEX_T_DECREMENT)) { struct expr *e = expr_parse_string("ip4", ctx->symtab, &ctx->error); ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, e); ofpact_put_DEC_TTL(ctx->ofpacts); } else { action_syntax_error(ctx, "expecting `--'"); } } else if (lexer_match_id(ctx->lexer, "ct_next")) { emit_ct(ctx, true, false); } else if (lexer_match_id(ctx->lexer, "ct_commit")) { emit_ct(ctx, false, true); } else { action_syntax_error(ctx, "expecting action"); } if (!lexer_match(ctx->lexer, LEX_T_SEMICOLON)) { action_syntax_error(ctx, "expecting ';'"); } if (ctx->error) { return; } } }
/* If 'lexer''s current token is the identifier given in 'id', advances 'lexer' * to the next token and returns true. Otherwise returns false. */ bool lexer_match_id(struct lexer *lexer, const char *id) { if (lexer->token.type == LEX_T_ID && !strcmp(lexer->token.s, id)) { lexer_get(lexer); return true; } else { return false; } }
/* If 'lexer''s current token has the given 'type', advances 'lexer' to the * next token and returns true. Otherwise returns false. */ bool lexer_match(struct lexer *lexer, enum lex_type type) { if (lexer->token.type == type) { lexer_get(lexer); return true; } else { return false; } }
bool lexer_get_int(struct lexer *lexer, int *value) { if (lexer_is_int(lexer)) { *value = ntohll(lexer->token.value.integer); lexer_get(lexer); return true; } else { *value = 0; return false; } }
static void parse_actions(struct action_context *ctx) { /* "drop;" by itself is a valid (empty) set of actions, but it can't be * combined with other actions because that doesn't make sense. */ if (ctx->lexer->token.type == LEX_T_ID && !strcmp(ctx->lexer->token.s, "drop") && lexer_lookahead(ctx->lexer) == LEX_T_SEMICOLON) { lexer_get(ctx->lexer); /* Skip "drop". */ lexer_get(ctx->lexer); /* Skip ";". */ if (ctx->lexer->token.type != LEX_T_END) { action_syntax_error(ctx, "expecting end of input"); } return; } while (ctx->lexer->token.type != LEX_T_END) { if (!parse_action(ctx)) { return; } } }
/* Like actions_parse(), but the actions are taken from 's'. */ char * OVS_WARN_UNUSED_RESULT actions_parse_string(const char *s, const struct action_params *ap, struct ofpbuf *ofpacts, struct expr **prereqsp) { struct lexer lexer; char *error; lexer_init(&lexer, s); lexer_get(&lexer); error = actions_parse(&lexer, ap, ofpacts, prereqsp); lexer_destroy(&lexer); return error; }
/* Like actions_parse(), but the actions are taken from 's'. */ char * OVS_WARN_UNUSED_RESULT actions_parse_string(const char *s, const struct shash *symtab, const struct simap *ports, const struct simap *ct_zones, uint8_t first_table, uint8_t n_tables, uint8_t cur_table, uint8_t output_table, struct ofpbuf *ofpacts, struct expr **prereqsp) { struct lexer lexer; char *error; lexer_init(&lexer, s); lexer_get(&lexer); error = actions_parse(&lexer, symtab, ports, ct_zones, first_table, n_tables, cur_table, output_table, ofpacts, prereqsp); lexer_destroy(&lexer); return error; }