首页 > 解决方案 > 解析以特定关键字开头和结尾的代码块

问题描述

这个问题之后,我想解析以关键字结尾的特定关键字(例如,、、...)<firstKeyword>开头<secondKeyword>的代码块。在这两者之间,一些语句应该以分号或换行符结尾。到目前为止我所做的可以在这个存储库中看到,但很快:<thirdKeyword>End

grammar <garammarName>

// Parser Rules

statement: EndOfStatment;

statement_list: statement+;

section:
    '<firstKeyword>' statement_list End
    | '<secondKeyword>' statement_list End
    | '<thirdKeyword>' statement_list End

sections: section+ EOF;

// Lexer Rules

End: 'End';

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

WhiteSpace: [ \t\r\n]+ -> skip;

EndOfStatment: ';' | NewLine;

但是,问题在于,当代码块不以关键字结尾时,TestRig / grun 工具(指令)不会引发错误。End例如,示例代码<exampleFile>

<firstKeyword>
End

<secondKeyword>

<thirdKeyword>
End

不返回任何错误

grun <garammarName> sections -tree < <exampleFile>

如果您能帮助我了解问题以及如何解决,我将不胜感激。

标签: antlrantlr4

解决方案


当我运行类似于您在此处给出的输入时,我得到:

➜ grun ElmerSolver sections -tree  < examples/ex001.sif
line 6:0 missing 'End' at 'Equation'
(sections (section Simulation statement_list End) (section Constants statement_list <missing 'End'>) (section Equation 1 statement_list End) <EOF>)

第 6 行缺少 'End' 是特别错误的。( line 6:0 missing 'End' at 'Equation')

ANTLR 错误恢复确实提供了缺失的“结束”来恢复并继续解析,但它会指出错误。

作为参考,这是我正在使用的完整语法:

grammar ElmerSolver;

// Parser Rules

// eostmt: ';' | CR;

statement: EndOfStatment;

statement_list: statement*;

sections: section+ EOF;
// section: SectionName /* statement_list */ End;

// Lexer Rules

fragment DIGIT: [0-9];
Integer: DIGIT+;

Float:
    [+-]? (DIGIT+ ([.]DIGIT*)? | [.]DIGIT+) ([Ee][+-]? DIGIT+)?;

section:
    'Header' statement_list End                         # headerSection
    | 'Simulation' statement_list End                   # simulatorSection
    | 'Constants' statement_list End                    # constantsSection
    | 'Body' Integer statement_list End                 # bodySection
    | 'Material' Integer statement_list End             # materialSection
    | 'Body Force' Integer statement_list End           # bodyForceSection
    | 'Equation' Integer statement_list End             # equationSection
    | 'Solver' Integer statement_list End               # solverSection
    | 'Boundary Condition' Integer statement_list End   # boundaryConditionSection
    | 'Initial Condition' Integer statement_list End    # initialConditionSection
    | 'Component' Integer statement_list End            # componentSection;

End: 'End';

// statementEnd: ';' NewLine*;

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

LineJoining:
    '\\' WhiteSpace? ('\r'? '\n' | '\r' | '\f') -> skip;

WhiteSpace: [ \t\r\n]+ -> skip;

LineComment: '#' ~( '\r' | '\n')* -> skip;

EndOfStatment: ';' | NewLine;

EndOfStatement((我对Lexer 规则进行了更改)

这是我使用的输入文件:

Simulation
End

Constants 

Equation 1
End

-gui这是我使用grun 选项获得的图形视图;

在此处输入图像描述


回复:你对EndOfStatment规则的改变。

EndOfStatment 可能应该是一个解析器规则(小写)。

此外,按照您的语法,'\n' 将始终被识别为具有将其排除在 tokenStream 之外NewLine的规则的标记。-> skip

grun使用选项运行-tokens,您将看不到任何EndOfStatement标记。(除非您在源文件中添加了“;”。)

➜ grun ElmerSolver sections -tree -tokens < examples/ex001.sif
[@0,0:9='Simulation',<'Simulation'>,1:0]
[@1,11:13='End',<'End'>,2:0]
[@2,16:24='Constants',<'Constants'>,4:0]
[@3,28:35='Equation',<'Equation'>,6:0]
[@4,37:37='1',<Integer>,6:9]
[@5,39:41='End',<'End'>,7:0]
[@6,42:41='<EOF>',<EOF>,7:3]
line 6:0 missing 'End' at 'Equation'
(sections (section Simulation statement_list End) (section Constants statement_list <missing 'End'>) (section Equation 1 statement_list End) <EOF>)

如果您希望 NewLine 在语法上有意义(即您可以在语法中使用它),您需要删除-> skip.

但是,一旦你这样做了,你就必须具体说明 NewLine 有效的所有地方(但我看到你的 LineJoining 令牌,所以看起来这应该有一点 Python 的感觉,所以这可能是你要做什么)。(同样的评论:-> skip适用于此)。如果您要走“类似 Python”的路线,请了解 Pythongs EOL 和缩进处理是众所周知的为解析器添加的(并且“The Definitive ANTLR 4 Reference”有一节专门介绍必须做什么来处理它)。您还可以参考ANTLR Python 语法中的 Python 语法


推荐阅读