【发布时间】:2013-06-16 15:31:34
【问题描述】:
我最近一直在为基于 C 的语言编写解析器。我正在使用 CUP(Yacc for Java)。
我想实现“The lexer hack”(http://eli.thegreenplace.net/2011/05/02/the-context-sensitivity-of-c%E2%80%99s-grammar-revisited/ 或 https://en.wikipedia.org/wiki/The_lexer_hack),以区分 typedef 名称和变量/函数名称等。启用与前面声明的类型同名的声明变量(来自第一个链接的示例):
typedef int AA;
void foo() {
AA aa; /* OK - define variable aa of type AA */
float AA; /* OK - define variable AA of type float */
}
我们必须引入一些新的产品,其中变量/函数名称可以是IDENTIFIER 或TYPENAME。这就是困难发生的时刻——语法冲突。
我试图不为 gcc 3.4 (http://yaxx.googlecode.com/svn-history/r2/trunk/gcc-3.4.0/gcc/c-parse.y) 使用这个凌乱的 Yacc 语法,但这次我不知道如何自己解决冲突。我看了一下Yacc语法:
declarator:
after_type_declarator
| notype_declarator
;
after_type_declarator:
...
| TYPENAME
;
notype_declarator:
...
| IDENTIFIER
;
fndef:
declspecs_ts setspecs declarator
// some action code
// the rest of production
...
setspecs: /* empty */
// some action code
declspecs_ts 表示声明说明符,其中
“是否见过类型说明符;在类型说明符之后,typedef 名称是要重新声明的标识符(_ts 或 _nots)。”
从 declspecs_ts 我们可以到达
typespec_nonreserved_nonattr:
TYPENAME
...
;
乍一看,我不敢相信 shift/reduce 冲突没有出现!
setspecs 是空的,所以我们有declspecs_ts 后跟declarator,因此我们可以预期解析器应该混淆TYPENAME 是来自declspecs_ts 还是来自declarator。
谁能简要(甚至准确地)解释一下。提前致谢!
编辑: 有用链接:http://www.gnu.org/software/bison/manual/bison.html#Semantic-Tokens
【问题讨论】:
标签: parsing compilation grammar context-sensitive-grammar