【问题标题】:lex & yacc get current positionlex & yacc 获取当前位置
【发布时间】:2014-08-12 07:17:49
【问题描述】:

在 lex & yacc 中有一个名为 YY_INPUT 的宏,可以重新定义,例如以这种方式

#define YY_INPUT(buf,result,maxlen) do { \
 const int n = gzread(gz_yyin, buf, maxlen); \                                                                              
 if (n < 0) { \
       int errNumber = 0; \
       reportError( gzerror(gz_yyin, &errNumber)); } \
     \
     result = n > 0 ? n : YY_NULL; \
  } while (0)

我有一些称为 YYACCEPT 宏的语法规则。 如果在 YYACCEPT 之后我调用了 gztell(或 ftell),那么我得到了一个错误的号码,因为解析器已经读取了一些不必要的数据。

那么,如果我有一些称为 YYACCEPT 的规则,我如何获得当前位置(一个不好的解决方案是逐个字符读取)

(我已经做过这样的事情了:

#define YY_USER_ACTION do { \
        current_position += yyleng; \
} while (0)   

但似乎它不起作用 )

【问题讨论】:

    标签: parsing compiler-construction lex lexical-analysis


    【解决方案1】:

    您必须自己跟踪偏移量。一个简单但烦人的解决方案是:

    offset += yyleng;
    

    每个 flex 动作中。幸运的是,您可以通过定义 YY_USER_ACTION 宏来隐式执行此操作,该宏在令牌操作之前执行。

    这可能仍然不适合您的语法,因为bison 经常提前读取一个标记。因此,您还需要将 offset 的值附加到每个词法标记,最方便的是使用定位工具 (yylloc)。

    编辑:添加了有关位置跟踪的更多详细信息。

    以下内容未经测试。您应该阅读flexbison 手册中有关位置跟踪的部分。

    如果您使用--locations 命令行选项或%locations 指令,或者如果您只是在某些规则中引用位置值,则yylloc 全局变量及其默认类型将包含在生成的野牛代码中,使用@ 语法,类似于$ 语法(即@n 是语义值为$n 的右侧对象的位置值)。不幸的是,yylloc 的默认类型使用ints,它的宽度不足以容纳文件偏移量,尽管您可能不打算解析这很重要的文件。无论如何,改变很容易;你只需要#define YYLTYPE 宏在你的bison 文件的顶部。默认YYLTYPE 是:

    typedef struct YYLTYPE
         {
           int first_line;
           int first_column;
           int last_line;
           int last_column;
         } YYLTYPE;
    

    对于最小的修改,我建议保持名称不变;否则,您还需要修复 bison 文件中的 YYLLOC_DEFAULT 宏。默认的YYLLOC_DEFAULT确保非终端获得一个位置值,其first_linefirst_column成员来自非终端RHS中的第一个元素,其last_linelast_column成员来自最后一个元素.由于它是一个宏,因此它适用于各种成员的任何可分配类型,因此将column 成员更改为longsize_toffset_t 就足够了,只要你觉得合适:

    #define YYLTYPE yyltype;
    typedef struct yyltype {
      int first_line;
      offset_t first_column;
      int last_line;
      offset_t last_column;
    } yyltype;
    

    然后在您的flex 输入中,您可以定义YY_USER_ACTION 宏:

    offset_t offset;
    extern YYLTYPE yylloc;
    
    #define YY_USER_ACTION         \
      offset += yyleng;            \
      yylloc.last_line = yylineno; \
      yylloc.last_column = offset;
    

    完成所有这些并进行适当的初始化后,您应该能够在ACCEPT 规则中使用适当的@n.last_column 来提取已接受输入中最后一个标记结尾的偏移量。

    【讨论】:

    • rici 您能否更详细地解释一下答案的最后一部分(因此您还需要使用定位工具(yylloc)将偏移量的值附加到每个词法标记,它您可能已经在使用它来跟踪行号)。
    • 对于任何正在努力编译的人,我发现this question and answer 很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多