Parsing 莱克斯;yacc获取当前位置

Parsing 莱克斯;yacc获取当前位置,parsing,compiler-construction,lex,lexical-analysis,Parsing,Compiler Construction,Lex,Lexical Analysis,在lex&yacc中,有一个名为YY_INPUT的宏,可以用这种方式重新定义它 #define YY_INPUT(buf,result,maxlen) do { \ const int n = gzread(gz_yyin, buf, maxlen); \ if (n < 0) { \ int errNumber =

在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)
但它似乎不起作用
)您必须自己跟踪偏移量。一个简单但烦人的解决方案是:

offset += yyleng;
在每一个灵活的行动。幸运的是,您可以通过定义
YY_USER_ACTION
宏隐式地实现这一点,该宏在令牌操作之前执行

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

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

以下内容尚未测试。您应该阅读
flex
bison
手册中有关位置跟踪的章节

如果使用
--locations
命令行选项或
%locations
指令,或者使用与
$
语法类似的
@
语法在某些规则中引用位置值,则生成的bison代码中将包含
yylloc
全局变量及其默认类型(即,
@n
是语义值为
$n
的右侧对象的位置值)。不幸的是,
yylloc
的默认类型使用
int
s,其宽度不足以容纳文件偏移量,尽管您可能不打算解析与此相关的文件。在任何情况下,更改都很容易;您只需在
biso顶部定义
YYLTYPE
宏即可n
文件。默认的
YYLTYPE
为:

typedef struct YYLTYPE
     {
       int first_line;
       int first_column;
       int last_line;
       int last_column;
     } YYLTYPE;
对于最小的修改,我建议保持名称不变;否则您还需要修复
bison
文件中的
YYLLOC\u DEFAULT
宏。默认的
YYLLOC\u DEFAULT
确保非终端获得一个位置值,其
第一行
第一列
成员来自fi非终端RHS中的rst元素,其
last_line
last_column
成员来自last元素。由于它是一个宏,它将与各种成员的任何可分配类型一起工作,因此将
column
成员更改为
long
size_t
offset\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_动作
宏:

offset_t offset;
extern YYLTYPE yylloc;

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

完成所有这些操作并进行适当的初始化后,您应该能够使用
ACCEPT
规则中适当的
@n.last\u列
,以提取接受输入中最后一个标记末尾的偏移量。

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

offset += yyleng;
幸运的是,您可以通过定义
YY_USER_action
宏隐式地执行此操作,该宏在令牌操作之前执行

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

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

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

如果使用
--locations
命令行选项或
%locations
指令,或者使用与
$
语法类似的
@
语法在某些规则中引用位置值,则生成的bison代码中将包含
yylloc
全局变量及其默认类型(即,
@n
是语义值为
$n
的右侧对象的位置值)。不幸的是,
yylloc
的默认类型使用
int
s,其宽度不足以容纳文件偏移量,尽管您可能不打算解析与此相关的文件。在任何情况下,更改都很容易;您只需在
biso顶部定义
YYLTYPE
宏即可n
文件。默认的
YYLTYPE
为:

typedef struct YYLTYPE
     {
       int first_line;
       int first_column;
       int last_line;
       int last_column;
     } YYLTYPE;
对于最小的修改,我建议保持名称不变;否则您还需要修复
bison
文件中的
YYLLOC\u DEFAULT
宏。默认的
YYLLOC\u DEFAULT
确保非终端获得一个位置值,其
第一行
第一列
成员来自fi非终端RHS中的rst元素,其
last_line
last_column
成员来自last元素。由于它是一个宏,它将与各种成员的任何可分配类型一起工作,因此将
column
成员更改为
long
size_t
offset\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_动作
宏:

offset_t offset;
extern YYLTYPE yylloc;

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

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

您能更详细地解释答案的最后部分吗(因此,您还需要使用定位工具(yylloc)将偏移量的值附加到每个词汇标记上,您可能已经在使用该工具来跟踪行号)。对于那些正在努力将其编译的人,我发现这很有帮助。您能更详细地解释答案的最后部分吗(因此,还需要将偏移量的值附加到e