static int run_grammar(VALUE self, char *filename, VALUE rb_input, char *input, bool run_callbacks) {
  reset_terminal_error();
  
  struct bc_read_stream *s = bc_rs_open_file(filename);
  if (!s)
    return 1; // should raise an invalid file format error in ruby instead

  struct gzl_grammar *g = gzl_load_grammar(s);
  bc_rs_close_stream(s);
  
  ParseState *state = gzl_alloc_parse_state();
  mk_user_data(state, self, input, rb_input);
  
  BoundGrammar bg = {
    .grammar           = g,
    .error_char_cb     = error_char_callback,
    .error_terminal_cb = error_terminal_callback
  };
  
  if (run_callbacks) {
    bg.end_rule_cb = end_rule_callback;
    bg.terminal_cb = terminal_callback;
  }
  
  rb_gzl_parse(input, state, &bg);

  return 0;
}
Example #2
0
int main(int argc, char *argv[])
{
    if(argc > 1 && strcmp(argv[1], "--help") == 0)
    {
        usage();
        exit(0);
    }

    if(argc < 3)
    {
        fprintf(stderr, "Not enough arguments.\n");
        usage();
        return 1;
    }

    int arg_offset = 1;
    bool dump_json = false;
    bool dump_total = false;
    while(arg_offset < argc && argv[arg_offset][0] == '-')
    {
        if(strcmp(argv[arg_offset], "--dump-json") == 0)
            dump_json = true;
        else if(strcmp(argv[arg_offset], "--dump-total") == 0)
            dump_total = true;
        else
        {
            fprintf(stderr, "Unrecognized option '%s'.\n", argv[arg_offset]);
            usage();
            exit(1);
        }
        arg_offset++;
    }

    /* Load the grammar file. */
    if(arg_offset+1 >= argc)
    {
        fprintf(stderr, "Must specify grammar file and input file.\n");
        usage();
        return 1;
    }
    struct bc_read_stream *s = bc_rs_open_file(argv[arg_offset++]);
    if(!s)
    {
        printf("Couldn't open bitcode file '%s'!\n\n", argv[1]);
        usage();
        return 1;
    }
    struct gzl_grammar *g = gzl_load_grammar(s);
    bc_rs_close_stream(s);

    /* Open the input file. */
    FILE *file;
    if(strcmp(argv[arg_offset], "-") == 0)
    {
        file = stdin;
    }
    else
    {
        file = fopen(argv[arg_offset], "r");
        if(!file)
        {
            printf("Couldn't open file '%s' for reading: %s\n\n", argv[2], strerror(errno));
            usage();
            return 1;
        }
    }

    struct gzlparse_state user_state;
    INIT_DYNARRAY(user_state.first_child, 1, 16);
    user_state.first_child[0] = true;

    struct gzl_parse_state *state = gzl_alloc_parse_state();
    struct gzl_bound_grammar bg = {
        .grammar = g,
        .error_char_cb = error_char_callback,
        .error_terminal_cb = error_terminal_callback,
    };
    if(dump_json) {
        bg.terminal_cb = terminal_callback;
        bg.did_start_rule_cb = start_rule_callback;
        bg.will_end_rule_cb = end_rule_callback;
        fputs("{\"parse_tree\":", stdout);
    }
    gzl_init_parse_state(state, &bg);
    enum gzl_status status = gzl_parse_file(state, file, &user_state, 50 * 1024);

    switch(status)
    {
        case GZL_STATUS_OK:
        case GZL_STATUS_HARD_EOF:
        {
            if(dump_json)
                fputs("\n}\n", stdout);

            if(dump_total)
            {
                fprintf(stderr, "gzlparse: %zu bytes parsed", state->offset.byte);
                if(status == GZL_STATUS_HARD_EOF)
                    fprintf(stderr, "(hit grammar EOF before file EOF)");
                fprintf(stderr, ".\n");
            }
            break;
        }

        case GZL_STATUS_ERROR:
            fprintf(stderr, "gzlparse: parse error, aborting.\n");

        case GZL_STATUS_CANCELLED:
            /* TODO: when we support length caps. */
            break;

        case GZL_STATUS_RESOURCE_LIMIT_EXCEEDED:
            /* TODO: more informative message about what limit was exceeded. */
            fprintf(stderr, "gzlparse: resource limit exceeded.\n");
            break;

        case GZL_STATUS_IO_ERROR:
            perror("gzlparse");
            break;

        case GZL_STATUS_PREMATURE_EOF_ERROR:
            fprintf(stderr, "gzlparse: premature eof.\n");
            break;
    }

    gzl_free_parse_state(state);
    gzl_free_grammar(g);
    FREE_DYNARRAY(user_state.first_child);
    fclose(file);
}