【问题标题】:lemon parser parsing 0 token柠檬解析器解析 0 令牌
【发布时间】:2013-12-20 22:09:57
【问题描述】:

我在使用(可重入)Flex + Lemon 进行解析时遇到问题。我正在使用一个简单的语法和词法分析器here。当我运行它时,我会输入一个数字,后跟一个 EOF 标记 (Ctrl-D)。打印输出将显示:

89

found int of .
AST=0.

第一行是我输入的数字。理论上,AST值应该是我输入的所有内容的总和。

编辑:当我手动调用 Parse() 时,它运行正常。

此外,即使标记为 0(停止标记),柠檬似乎也会运行 atom ::= INT 规则。为什么是这样?我对这种行为感到非常困惑,我找不到任何好的文档。

【问题讨论】:

    标签: c parsing lemon


    【解决方案1】:

    好的,我想通了。原因是 flex 和 lemon 之间发生了特别令人讨厌的(并且记录不充分)的交互。

    为了节省内存,lemon 将保留一个令牌而不进行复制,并将其推送到内部令牌堆栈中。但是,flex 也尝试通过更改 yyget_text 在对输入进行词法分析时指向的值来节省内存。我的示例中的违规行是:

    // in the do loop of main.c...
    Parse(parser, token, yyget_text(lexer));
    

    这应该是:

    Parse(parser, token, strdup(yyget_text(lexer)));
    

    这将确保柠檬在以后减少令牌堆栈时指向的值与您最初传入的值相同。

    (注意:不要忘记,strdup 意味着您必须稍后释放该内存。Lemon 将允许您编写可以执行此操作的令牌“析构函数”,或者如果您正在构建一个 AST树,你应该等到 AST 生命周期结束。)

    【讨论】:

      【解决方案2】:

      您也可以尝试创建一个令牌类型,其中包含指向字符串的指针和字符串的长度。我已经成功了。

      token.h

      #ifndef Token_h
      #define Token_h
      
      typedef struct Token {
        int code;
        char * string;
        int string_length;
      } Token;
      
      #endif // Token_h
      

      main.c

      int main(int argc, char** argv) {
          // Set up the scanner
          yyscan_t scanner;
          yylex_init(&scanner);
          yyset_in(stdin, scanner);
      
          // Set up the parser
          void* parser = ParseAlloc(malloc);
      
          // Do it!
          Token t;
          do {
              t.code = yylex(scanner);
              t.string = yyget_text(scanner);
              t.string_length = yyget_leng(scanner);
              Parse(parser, t.code, t);
          } while (t.code > 0);
      
          if (-1 == t.code) {
              fprintf(stderr, "The scanner encountered an error.\n");
          }
      
          // Cleanup the scanner and parser
          yylex_destroy(scanner);
          ParseFree(parser, free);
          return 0;
      }
      

      language.y(摘录)

      class_interface   ::= INTERFACE IDENTIFIER(A) class_inheritance END.
      {
          printf("defined class %.*s\n", A.string_length, A.string);
      }
      

      看到我的 printf 语句了吗?我正在使用字符串和长度来打印我的令牌。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多