Parsing 莱克斯;yacc获取当前位置
在lex&yacc中,有一个名为YY_INPUT的宏,可以用这种方式重新定义它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 =
#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