如何在简单的语法中使用空间

时间:2018-08-27 09:51:24

标签: antlr antlr4 ebnf

我是antlr和ebnf的初学者。

我在antlr4中表达以下语法:

grammar RecordGrammar;

Record: 'record';
EndRecord: 'endrecord';

Track: 'track';
EndTrack: 'endtrack';

Length: 'length';

Name: [a-zA-Z]+;
Number: [0-9]+;
WS: [ \t\r\n]+;

records: (record)+ EOF;

record: Record WS Name WS
            tracks WS?
        EndRecord WS?;

tracks: track WS? (track WS)*;

track: Track WS
          length
       EndTrack WS?;

length: Length WS Number WS?;

当我在文本上使用上面的语法(与antlr结合使用)时:

record help
    track
     length 2
    endtrack
    track
       length 4
    endtrack
    track
       length 42
    endtrack
endrecord

...效果很好,很漂亮。

但是我想在EBNF中扩展“名称”规则以也接受空格。

所以我也希望语法也接受该文本文件:

record help me
    track
     length 2
    endtrack
    track
       length 4
    endtrack
    track
       length 42
    endtrack
endrecord

观察记录标签右侧的文本“帮助我”。

如何在语法上做到这一点?由于Space是自然的分隔符,因此在我的规则中需要对此进行某种特殊处理。感谢您的所有帮助,我可以得到...

2 个答案:

答案 0 :(得分:0)

您可以创建与多个SELECT TIMESTAMPDIFF(YEAR, dob, NOW()) AS age_group, COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) <25, 1, 0 ) ) AS ag_C, COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) BETWEEN 25 AND 35 , 1, 0 ) ) AS ag_B, COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) BETWEEN 35 AND 50 , 1, 0 ) ) AS ag_C, COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) >50, 1, 0 ) ) AS ag_D FROM emp GROUP BY age_group 令牌匹配的name解析器规则:

Name

但是由于您实际上并没有对空格做任何事情,因此请注意,在标记化过程中,通过向其添加name : Name (WS+ Name)*; 并从解析器规则中删除所有-> skip来丢弃它们:

WS

这将导致以下分析树:

enter image description here

答案 1 :(得分:0)

您应该首先确定如何确定名称的实际结尾。在最初的语法中,这很容易-它是一个单词,因此以空格字符结尾。在Bart的回答中,它是单词'record'和'track' * 之间的每个单词。但这是您的情况,还是名称实际上包含“ track”一词?

您可能还需要考虑以下选项:

  • 在该行的结尾处终止名称(在这种情况下,空格变得很重要,您需要在名称中允许该单词,使其成为非保留关键字)。
  • 在引号(")或撇号(')中加上多字名称-在这种情况下,空格并不重要,可以按照Bart的回答跳过。

*)比实际上要复杂得多-但这是如何查找记录名称结尾的基本概念。