【问题标题】:Require newline or EOF after statement match语句匹配后需要换行符或 EOF
【发布时间】:2018-01-01 04:13:52
【问题描述】:

只是寻找一种让 ANTLR4 生成解析器的简单方法,该解析器将执行以下操作(忽略 ; 之后的任何内容):

int #i ;    defines an int
int #j ;    see how I have to go to another line for another statement?

我的解析器如下:

compilationUnit:
    (statement END?)*
    statement END?
    EOF
;

statement:
    intdef |
    WS
;

// 10 - 1F block.

intdef:
    'intdef' Identifier
;

// Lexer.

Identifier: '#' Letter LetterOrDigit*;
fragment Letter: [a-zA-Z_];
fragment LetterOrDigit: [a-zA-Z0-9$_];

// Whitespace, fragments and terminals.

WS: [ \t\r\n\u000C]+ -> skip;
//COMMENT: '/*' .*? '*/' -> channel(HIDDEN);
END: (';' ~[\r\n]*) | '\n';

本质上,任何时候我有一个statement,我都需要它在输入另一个之前需要一个换行符。我不在乎是否有 3 个新行,然后在第二个新行上保留一堆标签,只要有一个新行。

问题是,ANTLR4 解析树似乎在输入错误,例如:

.

(假装点不存在,它实际上没有输入)

int #i int #j

糟糕,我们有两个在同一行!

关于如何实现这一目标的任何想法?感谢您的帮助。

【问题讨论】:

    标签: parsing antlr4 semantics


    【解决方案1】:

    我已经稍微简化了你的语法,但它要求在每条语句之后都有一个行尾序列才能正确解析。

    grammar Testnl;
    
    program: (statement )* EOF ;
    
    statement: 'int' Identifier EOL;
    
    Identifier: '#' Letter LetterOrDigit*;
    fragment Letter: [a-zA-Z_];
    fragment LetterOrDigit: [a-zA-Z0-9$_];
    
    EOL: ';' .*? '\r\n'
    | ';' .*? '\n'
    ;
    
    WS: [ \t\r\n\u000C]+ -> skip;
    

    它解析

    int #i ;
    int #j;
    
    
    [@0,0:2='int',<'int'>,1:0]
    [@1,4:5='#i',<Identifier>,1:4]
    [@2,7:9=';\r\n',<EOL>,1:7]
    [@3,10:12='int',<'int'>,2:0]
    [@4,14:15='#j',<Identifier>,2:4]
    [@5,16:18=';\r\n',<EOL>,2:6]
    [@6,19:18='<EOF>',<EOF>,3:0]
    

    它还会忽略分号后面的内容,作为 EOL 令牌的一部分:

    [@0,0:2='int',<'int'>,1:0]
    [@1,4:5='#i',<Identifier>,1:4]
    [@2,7:20='; ignore this\n',<EOL>,1:7]
    [@3,21:23='int',<'int'>,2:0]
    [@4,25:26='#j',<Identifier>,2:4]
    [@5,27:28=';\n',<EOL>,2:6]
    [@6,29:28='<EOF>',<EOF>,3:0]
    

    使用换行或回车换行就可以了。这就是你要找的东西吗?

    编辑

    根据 OP 评论,做了一个小改动以允许连续 EOL 令牌,并将 EOL 令牌移动到 statement 以减少重复:

    语法测试;

    program: ( statement EOL )* EOF ;
    
    statement: 'int' Identifier;
    
    Identifier: '#' Letter LetterOrDigit*;
    fragment Letter: [a-zA-Z_];
    fragment LetterOrDigit: [a-zA-Z0-9$_];
    
    EOL: ';' .*? ('\r\n')+
    | ';' .*? ('\n')+
    ;
    
    WS: [ \t\r\n\u000C]+ -> skip;
    

    【讨论】:

    • 感谢您的回答!这正是我正在寻找的。​​span>
    • 实际上,快速提问,有没有办法让我在语句之间和最后一个语句之后有换行符?目前,它们必须彼此直接插入,没有杂散的换行符。
    • @finnrayment 确定,完成,请参阅上面的编辑语法。干杯!
    • 非常感谢!如果可以的话,我会再次投票。欣赏它。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 2012-09-19
    • 1970-01-01
    相关资源
    最近更新 更多