Var*_*yan 1 compiler-construction parsing 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 = 0; \
reportError( gzerror(gz_yyin, &errNumber)); } \
\
result = n > 0 ? n : YY_NULL; \
} while (0)
Run Code Online (Sandbox Code Playgroud)
我有一些叫做YYACCEPT宏的语法规则.如果在YYACCEPT之后我调用了gztell(或ftell),那么我得到一个错误的数字,因为解析器已经读取了一些不必要的数据.
那么如果我有一些叫做YYACCEPT的规则,我怎么能得到当前的位置(一个坏的解决方案是逐个字符地阅读)
(我已经做过这样的事情:
#define YY_USER_ACTION do { \
current_position += yyleng; \
} while (0)
Run Code Online (Sandbox Code Playgroud)
但似乎不起作用)
你必须自己跟踪偏移量.一个简单而烦人的解决方案是:
offset += yyleng;
Run Code Online (Sandbox Code Playgroud)
在每个弹性动作中.幸运的是,您可以通过定义YY_USER_ACTION宏来隐式地执行此操作,该宏在令牌操作之前执行.
这可能仍然不适合你的语法,因为bison通常会提前读取一个标记.因此,您还需要将值附加offset到每个词法标记,最方便的是使用location facility(yylloc).
修改:添加了有关位置跟踪的更多详情.
以下未经过测试.您应该阅读有关位置跟踪flex的bison手册和手册中的章节.
的yylloc全局变量和它的默认类型被包括在所产生的野牛代码如果使用--locations命令行选项或%locations指令,或者如果你简单地指的位置值在一些规则,使用该@语法,这是类似于$句法(即是,@n是语义值为的右侧对象的位置值$n.不幸的是,yylloc使用ints 的默认类型,其宽度不足以容纳文件偏移量,尽管您可能没有计划解析重要的文件.无论如何,它很容易改变; 你只需要在文件顶部#define的YYLTYPE宏bison.默认YYLTYPE为:
typedef struct YYLTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
Run Code Online (Sandbox Code Playgroud)
对于最小的修改,我建议保持名称不变; 否则你还需要修复文件中的YYLLOC_DEFAULT宏bison.默认YYLLOC_DEFAULT确保非终端获得一个位置值,其first_line与first_column成员来自于非终端的RHS它的第一个元素,并last_line与last_column成员来自最后一个元素.由于它是一个宏,它将适用于各种成员的任何可分配类型,因此将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;
Run Code Online (Sandbox Code Playgroud)
然后在您的flex输入中,您可以定义YY_USER_ACTION宏:
offset_t offset;
extern YYLTYPE yylloc;
#define YY_USER_ACTION \
offset += yyleng; \
yylloc.last_line = yylineno; \
yylloc.last_column = offset;
Run Code Online (Sandbox Code Playgroud)
与所有的完成,相应的初始化,你应该能够使用适当@n.last_column的ACCEPT规则来提取在接受输入的最后一个记号的末尾的偏移量.
| 归档时间: |
|
| 查看次数: |
2745 次 |
| 最近记录: |