如何在野牛中使用"literal string tokens"



我正在学习Flex/Bison。野牛的手册说:

文字字符串标记的编写方式类似于 C 字符串常量;对于 例如,"<="是一个文本字符串标记。文本字符串标记 不需要声明,除非需要指定其语义 值数据类型

但是我不知道如何使用它,也没有找到一个例子。

我有以下代码用于测试:

例子.l

%option noyywrap nodefault
%{
#include "example.tab.h"
%}
%%
[ tn] {;}
[0-9] { return NUMBER; }
. { return yytext[0]; }
%%

例子.y

%{
#include <stdio.h>
#define YYSTYPE char *
%}
%token NUMBER
%%
start: %empty | start tokens
tokens:
NUMBER "<=" NUMBER { printf("<="); }
| NUMBER "=>" NUMBER { printf("=>n"); }
| NUMBER '>' NUMBER { printf(">n"); }
| NUMBER '<' NUMBER { printf("<n"); }
%%
main(int argc, char **argv) {
yyparse();
}
yyerror(char *s) {
fprintf(stderr, "error: %sn", s);
}

生成文件

#!/usr/bin/make
# by RAM
all: example
example.tab.c example.tab.h: example.y
bison -d $<
lex.yy.c: example.l example.tab.h
flex $<
example: lex.yy.c example.tab.c
cc -o $@ example.tab.c lex.yy.c -lfl
clean:
rm -fr example.tab.c example.tab.h lex.yy.c example

当我运行它时:

$ ./example 
3<4
<
6>9
>
6=>9
error: syntax error

知道吗?


更新:我想澄清一下,我知道解决它的替代方法,但我想使用文字字符串标记

一种选择:使用多个"文字字符标记":

tokens:
NUMBER '<' '=' NUMBER { printf("<="); }
| NUMBER '=' '>' NUMBER { printf("=>n"); }
| NUMBER '>' NUMBER { printf(">n"); }
| NUMBER '<' NUMBER { printf("<n"); }

当我运行它时:

$ ./example 
3<=9
<=

其他选择:

example.l中:

"<="  { return LE; }
"=>"  { return GE; }

示例 .y中:

...
%token NUMBER
%token LE "<="
%token GE "=>"
%%
start: %empty | start tokens
tokens:
NUMBER "<=" NUMBER { printf("<="); }
| NUMBER "=>" NUMBER { printf("=>n"); }
| NUMBER '>' NUMBER { printf(">n"); }
| NUMBER '<' NUMBER { printf("<n"); }
...

当我运行它时:

$ ./example 
3<=4
<=

但手册上说:

除非

需要声明文本字符串标记,否则不需要声明 指定其语义值数据类型

引用的手动段落是正确的,但您还需要阅读下一段:

可以使用 %token 声明将文本字符串标记与符号名称作为别名相关联(请参阅令牌声明)。如果不这样做,词法分析器必须从yytname表中检索文本字符串标记的令牌号。

所以你不需要声明文字字符串标记,但你仍然需要安排词法分析器发送正确的令牌编号,如果你没有声明关联的令牌名称,找到正确值的唯一方法是在yytname表中搜索代码。

简而言之,将LEGE定义为别名的最后一个示例是迄今为止最常见的方法。将令牌分成单独的字符不是一个好主意;它可能会产生 shift-reduce 冲突,并且肯定会允许无效输入,例如在字符之间放置空格。

如果您想尝试yytname解决方案,野牛手册中有示例代码。但请注意,此代码会发现 bison的内部令牌编号,该编号不是需要从扫描仪返回的数字。没有办法获得简单、便携和记录的外部令牌号;简单且未记录的方法是查找yytoknum的令牌编号,但由于该数组未记录并且以预处理器宏为条件,因此无法保证它会起作用。另请注意,这些表是static声明的,因此依赖于它们的函数必须包含在 bison 输入文件中。(当然,这些函数可以具有外部链接,以便可以从词法分析器调用它们。但你不能直接在词法分析器中使用yytname

我已经有一段时间没有使用 flex/bison 了,但有两件事:

.据我所知只匹配一个字符。yytext是指向以 null 结尾的字符串的指针char*因此 yytext[0] 是一个char这意味着您无法以这种方式匹配字符串。您可能需要将其更改为return yytext.否则.可能会创建一个令牌 PER 字符,您可能必须编写NUMBER '<' '=' NUMBER.

相关内容

最新更新