【问题标题】:Simple grammar for fluentd?流利的简单语法?
【发布时间】:2018-02-11 11:28:23
【问题描述】:

我是 antlr4 的新手,我正在尝试创建语法以将流利的配置文件解析为树。你能指出我在这里做错了什么吗?

fluentd 语法看起来很像 Apache 的(伪 xml、shell 样式的 cmets、标签中的 kv-pairs),例如:

# Receive events from 24224/tcp
<source>
  @type forward
  port 24224
</source>

# example
<match>
    # file or memory
    buffer_type    file
    <copy>
      file /path
    </copy>
</match>

这是我目前的语法:

grammar Fluentd;

// root element
content: (entry | comment)*;

entry: '<' name tag? '>' (entry | comment | param)* '<' '/' close_ '>';

name: NAME;

close_: NAME;

tag: TAG;

comment: '#' NL;

param: name value NL;

value: ANY;



ANY: .*?;

NL: ('\r'?'\n'|'\n') -> skip;

TAG: ('a'..'z' | 'A'..'Z' | '_' | '0'..'9'| '$' |'.' | '*' | '{' | '}')+;

NAME: ('a'..'z'| 'A..Z' | '@' | '_' | '0'..'9')+;

WS: (' '|'\t') -> skip;

...在上面的输入中它惨遭失败:

line 2:2 mismatched input 'Receive' expecting NL
line 3:1 missing NAME at 'source'
line 4:8 mismatched input 'forward' expecting ANY
line 6:2 mismatched input 'source' expecting NAME
line 8:2 mismatched input 'example' expecting NL
line 9:1 missing NAME at 'match'
line 10:6 mismatched input 'file' expecting NL
line 12:2 mismatched input 'match' expecting NAME

【问题讨论】:

    标签: antlr4 fluentd


    【解决方案1】:

    您必须意识到的第一件事是词法分析器独立于解析器工作。词法分析器通过尝试匹配尽可能多的字符来简单地创建标记。如果两个或多个词法分析器规则匹配相同数量的字符,则首先定义的规则将“获胜”。

    话虽如此,因此输入source 永远不能被标记为NAME,因为TAG 规则也与此匹配,并且在NAME 之前定义。

    解决方案可能是:

    tag  : SIMPLE_ID | TAG;
    name : SIMPLE_ID | NAME;
    
    SIMPLE_ID : [a-zA-Z_0-9]+ ;
    TAG       : [a-zA-Z_0-9$.*{}]+ ;
    NAME      : [a-zA-Z_0-9@]+ ;
    

    这样,foobar 将变为 SIMPLE_IDfoo.barTAG@muNAME

    你的语法还有很多不正确的地方:

    • 在你的词法分析器中,你是 skipping NL 标记,但你也在解析器规则中使用它们:你不能这样做(因为永远不会创建这样的标记)

    • ANY: .*?; 可能匹配一个空字符串(其中有无数个):词法分析器规则必须始终匹配至少 1 个字符!但是,如果您将 .*? 更改为 .+?,它将始终只匹配 1 个字符,因为您使其匹配不贪心(尾随 ?)。而且你不能做.+,因为那样它将匹配整个输入。你应该这样做:

      // Use a parser rule to "glue" all single ANY tokens to each other
      any : ANY+ ;
      
      // all other lexer rules
      
      // This must be very last rule!
      ANY : . ;
      

      如果您没有将ANY 定义为最后一条规则,则X 之类的输入不会被标记为TAG,而是ANY 标记(记住我的第一段)。

    • 规则comment: '#' NL; 没有意义:注释不是# 后跟换行符。我希望这样的事情有一个词法分析器规则:

      COMMENT : '#' ~[\r\n]* -> skip;
      

      并且不需要在此规则中包含换行符:这些已在 NL 中处理。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-06
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 2019-02-21
    相关资源
    最近更新 更多