简单的Ragel语法,带有可选的空格

时间:2017-03-07 16:25:54

标签: ragel

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 )* ;

这是我的整个代码https://github.com/and09/simple_grammar

1 个答案:

答案 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问题,机器将工作很好,这只是你在行动中做的事情),但这超出了当前问题的范围。