代码之家  ›  专栏  ›  技术社区  ›  user5549921

语句匹配后需要换行符或EOF

  •  1
  • user5549921  · 技术社区  · 7 年前

    这个 ;

    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
    

    汪,我们有两个在同一条线上!

    关于我如何实现这一点,有什么想法吗?我感谢你的帮助。

    1 回复  |  直到 7 年前
        1
  •  0
  •   TomServo    7 年前

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

    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]
    

    [@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]
    

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

    编辑

    statement 为了减少重复:

    语法测试NL;

    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;