我在我的EBNF和Tatsu实现中有一个问题,Tatsu的提取语法EBNF:
define ='#define' constantename [constante] ;
constante = CONSTANTE ;
CONSTANTE = ( Any | ``true`` ) ;
Any = /.*/ ;
constantename = (/[A-Z0-9_()]*/) ;当我使用以下命令测试时:
#define _TEST01_ "test01"
#define _TEST_
#define _TEST02_ "test02"我得到了:
[
"#define",
"_TEST01_",
"\"test01\""
],
[
"#define",
"_TEST_",
"#define _TEST02_ \"test02\""
]但我想要的是:
[
"#define",
"_TEST01_",
"\"test01\""
],
[
"#define",
"_TEST_",
"true"
],
[
"#define",
"_TEST02_",
"\"test02\""
]我的错误在哪里?
非常感谢。
发布于 2018-11-09 01:24:44
问题是默认情况下,Tatsu会跳过元素之间的空白,包括换行符。因此,当您将规则'#define' constantename [constante]应用于输入时:
#define _TEST_
#define _TEST02_ "test02"它首先将#define与'#define'匹配,然后跳过空格,然后将_TEST_与constantename匹配,然后跳过换行符,然后将#define _TEST02_ "test02"与ANY匹配(通过constante)。
请注意,如果没有换行符,这正是您想要的行为(我假设):
#define _TEST_ #define _TEST02_ "test02"在这里您需要输出["#define", "_TEST_", "#define _TEST02_ \"test02\""],对吗?在这种情况下,至少C预处理器会以同样的方式处理它。
所以这告诉我们换行符是很重要的。因此,你不能忽视它。您可以告诉Tatsu只忽略制表符和空格(而不是换行符),方法是在创建解析器时将whitespace = '\t '作为选项传递,或者将下面这一行添加到语法中:
@@whitespace :: /[\t ]+/现在你需要在换行符应该放到的任何地方显式地提到换行符,所以你的规则变成:
define ='#define' constantename [constante] '\n';现在很明显,常量,如果存在,应该出现在换行符之前,所以对于行#define _TEST_,它会意识到没有常量。
请注意,您还需要一个匹配空行的规则,因此空行不是语法错误。
https://stackoverflow.com/questions/53208564
复制相似问题