Configuring Bison and Flex without global or static variable

前端 未结 1 1482
一个人的身影
一个人的身影 2021-02-04 12:28

i am working in a small language/IDE. And I need to know how to configure flex and bison to work together but without using any global or static variable. I need to pass to biso

相关标签:
1条回答
  • 2021-02-04 12:55

    First, here's a C reentrant flex parser and pure bison example that parses a grammar that matches the following:

    ()
    (())
    (()())
    
    ()()(())()()
    

    lexer.l

    %option bison-bridge
    %option bison-locations
    %option ecs
    %option nodefault
    %option noyywrap
    %option reentrant
    %option stack
    %option warn
    %option yylineno
    
    %{
      #include "parser.h"
    %}
    
    %%
    
    "(" { return (LPAREN); }
    ")" { return (RPAREN); }
    
    [ \f\r\t\v\n]+ /* eat whitespace */
    
    %%
    
    /* don't use lexer.l for code, organize it logically elsewhere */
    

    parser.y

    %define parse.error verbose
    %define api.pure true
    %locations
    %token-table
    %glr-parser
    %lex-param {void *scanner}
    %parse-param {void *scanner}
    
    %{
    /* your top code here */
    %}
    
    %union {
      int value; // or whatever else here
    }
    
    %token LPAREN
    %token RPAREN
    
    %%
    
    document
        : exprs
    
    exprs
        : %empty
        | expr exprs
    
    expr
        : parens
    
    parens
        : LPAREN exprs RPAREN
    
    
    %%
    
    int
    yyerror(YYLTYPE *locp, char *msg) {
      if (locp) {
        fprintf(stderr, "parse error: %s (:%d.%d -> :%d.%d)\n",
                        msg,
                        locp->first_line, locp->first_column,
                        locp->last_line,  locp->last_column
        );
        /* todo: add some fancy ^^^^^ error handling here */
      } else {
        fprintf(stderr, "parse error: %s\n", msg);
      }
      return (0);
    }
    

    main.c

    #include "parser.h"
    #include "lexer.h"
    
    int
    main(int argc, char **argv) {
      int result;
      yyscan_t scanner;
    
      yylex_init(&scanner);
      result = (yyparse(scanner));
      yylex_destroy(scanner);
      return (result);
    }
    

    Building

    flex --header-file=lexer.h --outfile=lexer.c lexer.l
    bison --output-file=parser.c --defines=parser.h --warnings=all --feature=all parser.y
    cc lexer.c parser.c main.c -o parser
    ./parser
    

    Note: OSX's built-in bison is outdated, so install 3.x:

    brew install bison
    

    And then run it like /usr/local/opt/bison/bin/bison ....

    Now, to migrate to C++

    • copy .l to .lxx and .y to .yxx
    • change names for output files to *.cxx and *.hxx respectively.

    lexer.lxx

    • add %option c++
    • remove reentrant, bison-bridge and bison-locations
    • change all tokens like the following: LPAREN to yy::parser::token::LPAREN

    parser.yxx

    • add %skeleton "lalr1.cc"
    • remove api.pure
    • remove yyerror

    main.cxx

    • rewrite it for C++

    Hooking up the lexer and parser objects is an exercise for the reader.

    See also: https://github.com/bingmann/flex-bison-cpp-example but beware it uses the old bison 2.x interfaces.

    GNU Bison 3.x C++ Example docs

    0 讨论(0)
提交回复
热议问题