ocaml / byterun / parsing.c

/* The PDA automaton for parsers generated by camlyacc */

#include <stdio.h>
#include "config.h"
#include "mlvalues.h"
#include "memory.h"
#include "alloc.h"

struct parser_tables {    /* Mirrors parse_tables in ../stdlib/parsing.mli */
  value actions;
  value transl_const;
  value transl_block;
  char * lhs;
  char * len;
  char * defred;
  char * dgoto;
  char * sindex;
  char * rindex;
  char * gindex;
  value tablesize;
  char * table;
  char * check;
};

struct parser_env {       /* Mirrors parser_env in ../stdlib/parsing.ml */
  value s_stack;
  value v_stack;
  value symb_start_stack;
  value symb_end_stack;
  value stacksize;
  value curr_char;
  value lval;
  value symb_start;
  value symb_end;
  value asp;
  value rule_len;
  value rule_number;
  value sp;
  value state;
};

#ifdef BIG_ENDIAN
#define Short(tbl,n) \
  (*((unsigned char *)((tbl) + (n) * sizeof(short))) + \
          (*((schar *)((tbl) + (n) * sizeof(short) + 1)) << 8))
#else
#define Short(tbl,n) (((short *)(tbl))[n])
#endif

#ifdef DEBUG
int parser_trace = 0;
#define Trace(act) if(parser_trace) act
#else
#define Trace(act)
#endif

/* Input codes */
/* Mirrors parser_input in ../stdlib/parsing.ml */
#define START 0
#define TOKEN_READ 1
#define STACKS_GROWN_1 2
#define STACKS_GROWN_2 3
#define SEMANTIC_ACTION_COMPUTED 4

/* Output codes */
/* Mirrors parser_output in ../stdlib/parsing.ml */
#define READ_TOKEN Val_int(0) 
#define RAISE_PARSE_ERROR Val_int(1)
#define GROW_STACKS_1 Val_int(2)
#define GROW_STACKS_2 Val_int(3)
#define COMPUTE_SEMANTIC_ACTION Val_int(4)

/* The pushdown automata */

value parse_engine(tables, env, cmd, arg) /* ML */
     struct parser_tables * tables;
     struct parser_env * env;
     value cmd;
     value arg;
{
  int state;
  mlsize_t sp;
  int n, n1, n2, m, state1;

  switch(Int_val(cmd)) {

  case START:
    state = 0;
    sp = Int_val(env->sp);

  loop:
    Trace(printf("Loop %d\n", state));
    n = Short(tables->defred, state);
    if (n != 0) goto reduce;
    if (Int_val(env->curr_char) >= 0) goto testshift;
    env->sp = Val_int(sp);
    env->state = Val_int(state);
    return READ_TOKEN;
                                /* The ML code calls the lexer and updates */
                                /* symb_start and symb_end */
  case TOKEN_READ:
    sp = Int_val(env->sp);
    state = Int_val(env->state);
    if (Is_block(arg)) {
      env->curr_char = Field(tables->transl_block, Tag_val(arg));
      modify(&env->lval, Field(arg, 0));
    } else {
      env->curr_char = Field(tables->transl_const, Int_val(arg));
      env->lval = Val_long(0);
    }
    Trace(printf("Token %d (0x%lx)\n", Int_val(env->curr_char), env->lval));
    
  testshift:
    n1 = Short(tables->sindex, state);
    n2 = n1 + Int_val(env->curr_char);
    if (n1 != 0 && n2 >= 0 && n2 <= Int_val(tables->tablesize) &&
        Short(tables->check, n2) == Int_val(env->curr_char)) goto shift;
    n1 = Short(tables->rindex, state);
    n2 = n1 + Int_val(env->curr_char);
    if (n1 != 0 && n2 >= 0 && n2 <= Int_val(tables->tablesize) &&
        Short(tables->check, n2) == Int_val(env->curr_char)) {
      n = Short(tables->table, n2);
      goto reduce;
    }
    env->sp = Val_int(sp);
    env->state = Val_int(state);
    return RAISE_PARSE_ERROR;
                                /* The ML code raises the Parse_error exn */
  shift:
    state = Short(tables->table, n2);
    Trace(printf("Shift %d\n", state));
    sp++;
    if (sp < Long_val(env->stacksize)) goto push;
    env->sp = Val_int(sp);
    env->state = Val_int(state);
    return GROW_STACKS_1;
                                /* The ML code resizes the stacks */
  case STACKS_GROWN_1:
    sp = Int_val(env->sp);
    state = Int_val(env->state);
  push:
    Field(env->s_stack, sp) = Val_int(state);
    modify(&Field(env->v_stack, sp), env->lval);
    Field(env->symb_start_stack, sp) = env->symb_start;
    Field(env->symb_end_stack, sp) = env->symb_end;
    env->curr_char = Val_int(-1);
    goto loop;

  reduce:
    Trace(printf("Reduce %d\n", n));
    m = Short(tables->len, n);
    env->asp = Val_int(sp);
    env->rule_number = Val_int(n);
    env->rule_len = Val_int(m);
    sp = sp - m + 1;
    m = Short(tables->lhs, n);
    state1 = Int_val(Field(env->s_stack, sp - 1));
    n1 = Short(tables->gindex, m);
    n2 = n1 + state1;
    if (n1 != 0 && n2 >= 0 && n2 <= Int_val(tables->tablesize) &&
        Short(tables->check, n2) == state1) {
      state = Short(tables->table, n2);
    } else {
      state = Short(tables->dgoto, m);
    }
    if (sp < Long_val(env->stacksize)) goto semantic_action;
    env->sp = Val_int(sp);
    env->state = Val_int(state);
    return GROW_STACKS_2;
                                /* The ML code resizes the stacks */
  case STACKS_GROWN_2:
    sp = Int_val(env->sp);
    state = Int_val(env->state);
  semantic_action:
    env->sp = Val_int(sp);
    env->state = Val_int(state);
    return COMPUTE_SEMANTIC_ACTION;
                                /* The ML code calls the semantic action */
  case SEMANTIC_ACTION_COMPUTED:
    sp = Int_val(env->sp);
    state = Int_val(env->state);
    Field(env->s_stack, sp) = Val_int(state);
    modify(&Field(env->v_stack, sp), arg);
    Field(env->symb_end_stack, sp) =
      Field(env->symb_end_stack, Int_val(env->asp));
    goto loop;
  }
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.