Ragel是强大的机器,但我在语法中遇到'可选'元素有问题。我有简单的数字或字符串。麻烦在于空白。我不知道如何在','和变量之间正确选择空格。输入将是令牌之间的每个位置。结束行是';'或输入。我需要使用$ err()函数来解决错误。
这是我的测试集: 好
this , is , a , test ; and, this,
is,ok
next, trouble
How,produce,good
grammar;
ok
输出:
线(这一点,是,一,测试)
线(和,由此,是,OK)
线(下,麻烦)
线(如何,产生,良好)
线(语法)
线(OK)
并失败(这不是=没有',')(',,'没有数字或变量)
this not , working
and,
this,, too
当我使用这个语法时,我会在行尾获得单独的字符或错误
whitespace = [ \t\v\f] ;
enter = [\r\n] ;
string = (alnum | '_')+ ;
number = ('+'|'-')?[0-9]+'.'[0-9]+( [eE] ('+'|'-')? [0-9]+ )? ;
var = string | number ;
koniec = (';' | enter) ;
line = var whitespace* ( ',' whitespace* var )* whitespace* koniec ;
main := whitespace* ( line )* ;
答案 0 :(得分:0)
当你没有完整的语法规范时,有点难以给出明确的答案,但至少要试着让你的例子以你想要的方式工作,那么你应该能够在需要时纠正它。
所以,你在Github中的完整示例中有一些打印操作,实际上讲述了状态机中发生了什么(在使用Ragel时你应该定期检查的另一件事是状态它可以为您生产的机器图)。在其初始规范中(与问题相同),它在运行时输出以下内容:
[this]< >,< >[is]
所以进入第三个变量时遇到问题。这是为什么?好吧,那是因为您的line
只指定了一个( ',' whitespace* var)
元素,但是如果您尝试通过指定( ',' whitespace* var)*
来解决这个问题,那么它也不会起作用,因为现在您和#39;要求你的var
立即,然后重复逗号,没有任何空格。让我们尝试这个(有意删除的动作),将空白移动到重复组中:
line = var whitespace* ( ',' whitespace* var whitespace*)* koniec;
现在你在输出中得到这个:
[this]< >,< >[is]< >,< >[a]< >< >< >,< >[test]< >
这是一个明显的改进。那为什么它现在失败了?嗯,那是因为在你的koniec
机器想要包装到下一个line
之后,但为了做到这一点,它需要看到var
。但是我们在输入;
之后有空格。因此,我们需要更改行的定义以在开头启用一些空格,但这也会使main
中的空白多余,所以让我们尝试这些定义:
line = whitespace* var whitespace* ( ',' whitespace* var whitespace*)* koniec;
main:= line*;
现在我们有了这个输出:
[this]< >,< >[is]< >,< >[a]< >< >< >,< >[test]< >
< >[and],< >[this]
哪个更好,但仍然不够好。现在你可以看到它在换行上窒息,这对我来说实际上有点不清楚。你说那个
结束行是&#39 ;;&#39;或输入
但你想得到
线(和,由此,是,OK)
因此,我们假设enter开始一个新的line
,除非你在行尾有一个逗号。要在语法中指定,请执行以下操作:
line = whitespace* var whitespace* ( ',' (whitespace | enter)* var whitespace*)* koniec;
现在你在输出中得到这个:
[this]< >,< >[is]< >,< >[a]< >< >< >,< >[test]< >
< >[and],< >[this],[is],[ok]
为什么不进一步?这是因为我们的line
必须有var
,但我们在输入中有一个空行。这也提出了一个只有空白行的问题,所以让我们的line
使用仅限空格的内容:
line = whitespace* (var whitespace* ( ',' (whitespace | enter)* var whitespace*)*)? koniec;
砰!突然,你在输出中拥有了你想要的所有单词组。但是你也有一些过多的行,实际上很容易修复,你只需要将pisz_enter
动作从koniec
移到这样的行中:
vargroup = var whitespace* ( ',' %pisz_przecinek (whitespace | enter)* var whitespace*)* %pisz_enter;
line = whitespace* vargroup? koniec;
那就是它。我能注意到的另外两件事是:
您希望number
类似于
number = (('+'|'-')?[0-9]+'.'[0-9]+( [eE] ('+'|'-')? [0-9]+ )?) >Poczatek_Napisu %pisz_stala ;
要正确打印
poczatek_napisu
)在你的行动中。如果令牌在块之间分割(在任何长度超过sizeof bufor
的文件中很可能发生),那么您将遇到问题(并且它不是FSM问题,机器将工作很好,这只是你在行动中做的事情),但这超出了当前问题的范围。