+static bool
+parse_action(struct action_context *ctx)
+{
+ if (ctx->lexer->token.type != LEX_T_ID) {
+ action_syntax_error(ctx, NULL);
+ return false;
+ }
+
+ 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, "ip.ttl")) {
+ if (lexer_match(ctx->lexer, LEX_T_DECREMENT)) {
+ add_prerequisite(ctx, "ip");
+ 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 ';'");
+ }
+ return !ctx->error;
+}
+