查看以下语法,就解析器生成器而言,它有一个明显的缺陷:
"Start Symbol" = <Foo>
"Case Sensitive" = True
"Character Mapping" = 'Unicode'
{A} = {Digit}
{B} = [abcdefABCDEF]
{C} = {A} + {B}
Integer = {A}+
HexNumber = {C}+
<ContextA> ::= '[' HexNumber ']'
<ContextB> ::= '{' Integer '}'
<Number> ::= <ContextA> | <ContextB>
<Foo> ::= <Number> <Foo>
| <>
这种语法有缺陷的原因是,扫描仪无法区分终端[Integer;HexNumber]
。 (1234
是整数还是十六进制数??)。
在本例中编写的作品中,这与位无关,但可能存在语法,其中制作的上下文将阐明是否需要整数或十六进制数,并且扫描程序仍然拒绝协作。 / p>
因此,扫描程序需要知道解析器状态,以便能够对十六进制或整数标记做出正确的决定。
现在是术语的问题。这是怎么回事......呃......语法?词法?然后?一个上下文敏感的词法分析器?或者有人会说这是一个上下文敏感的语法,即使它显然是一个扫描仪问题?还有其他术语用于描述这种现象吗?
答案 0 :(得分:2)
上下文敏感意味着完全不同的东西。
如果你使用更正式的符号,你会发现你的原始语法含糊不清,正如Ignacio Vazquez-Abrams所说,你编辑的语法可以通过LR(1)(甚至是LL)处理得很好( 1))解析器生成器。这是一个没有问题的野牛语法:
%start number
%%
digit : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
hex : digit
| 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
| 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
decnum: digit | decnum digit
hexnum: hex | hexnum hex
number: '[' decnum ']'
| '{' hexnum '}'
当然,使用野牛制作扫描仪并不常见,但这当然是可能的。
我认为您正在考虑的问题是:如果我们使用flex构建扫描程序,它将如下所示:
[[:digit:]]+ { yylval.string = strdup(yytext); return DECNUM; }
[[:xdigit:]]+ { yylval.string = strdup(yytext); return HEXNUM; }
Flex无法返回模糊标记,因此在输入(下一部分)1234
的情况下,flex需要返回DECNUM或HEXNUM。第一个最长(“最大munch”)规则意味着在可以以任一方式解析的令牌的情况下,在flex定义中首先出现的哪个模式将获胜。这意味着DECNUM模式需要首先出现,否则它将无法触发(并且flex将在这种情况下提供警告)。
但是现在语法存在一个小问题,因为当语法期待一个HEXNUM时,需要准备好找到一个DECNUM。这不是问题,如果语法是明确的。我们只需要创建几个非终端:
decnum: DECNUM { $$ = strtol($1, NULL, 10); free($1); }
hexnum: DECNUM | HEXNUM { $$ = strtol($1, NULL, 16); free($1); }
这不会产生歧义,甚至不会产生语法中尚未存在的转移/减少冲突。
如果你想尝试这个,你需要在你的野牛序言中声明一些类型:
%union {
char* string;
long integer;
}
%token <string> HEXNUM DECNUM
%type <integer> hexnum decnum
答案 1 :(得分:0)
该语法可以描述为ambiguous。