如何在语法中表达要求的 'RETURN' 语句
How to express a required 'RETURN' statement in the grammar
我仍然是 ANTLR 的新手,很抱歉,如果我发布了一个明显的问题。
我的语法比较简单。我需要的是让用户能够输入如下内容:
if (condition)
{
return true
}
else if (condition)
{
return false
}
else
{
if (condition)
{
return true
}
return false
}
在我下面的语法中,有没有办法确保在输入字符串不包含 'return' 语句时标记错误?如果不能,我可以通过 Listener 实现吗?如果可以,怎么做?
grammar Evaluator;
parse
: block EOF
;
block
: statement
;
statement
: return_statement
| if_statement
;
return_statement
: RETURN (TRUE | FALSE)
;
if_statement
: IF condition_block (ELSE IF condition_block)* (ELSE statement_block)?
;
condition_block
: expression statement_block
;
statement_block
: OBRACE block CBRACE
;
expression
: MINUS expression #unaryMinusExpression
| NOT expression #notExpression
| expression op=(MULT | DIV) expression #multiplicationExpression
| expression op=(PLUS | MINUS) expression #additiveExpression
| expression op=(LTEQ | GTEQ | LT | GT) expression #relationalExpression
| expression op=(EQ | NEQ) expression #equalityExpression
| expression AND expression #andExpression
| expression OR expression #orExpression
| atom #atomExpression
;
atom
: function #functionAtom
| OPAR expression CPAR #parenExpression
| (INT | FLOAT) #numberAtom
| (TRUE | FALSE) #booleanAtom
| ID #idAtom
;
function
: ID OPAR (parameter (',' parameter)*)? CPAR
;
parameter
: expression #expressionParameter
;
OR : '||';
AND : '&&';
EQ : '==';
NEQ : '!=';
GT : '>';
LT : '<';
GTEQ : '>=';
LTEQ : '<=';
PLUS : '+';
MINUS : '-';
MULT : '*';
DIV : '/';
NOT : '!';
OPAR : '(';
CPAR : ')';
OBRACE : '{';
CBRACE : '}';
ASSIGN : '=';
RETURN : 'return';
TRUE : 'true';
FALSE : 'false';
IF : 'if';
ELSE : 'else';
// ID either starts with a letter then followed by any number of a-zA-Z_0-9
// or starts with one or more numbers, then followed by at least one a-zA-Z_ then followed
// by any number of a-zA-Z_0-9
ID
: [a-zA-Z] [a-zA-Z_0-9]*
| [0-9]+ [a-zA-Z_]+ [a-zA-Z_0-9]*
;
INT
: [0-9]+
;
FLOAT
: [0-9]+ '.' [0-9]*
| '.' [0-9]+
;
SPACE
: [ \t\r\n] -> skip
;
// Anything not recognized above will be an error
ErrChar
: .
;
我以前从未玩过 Listener。
通过访问者,在 VisitStatement(StatementContext context) 方法中,检查 context.return_statement() (ReturnStatementContext) 是否为空。如果为null,则抛出异常。
我也是新手。我正在考虑强迫词法分析器通过
需要一个 return 语句,所以而不是:
statement
: return_statement
| if_statement
;
这表示一个语句是 if_statement 或 return_statement 我会尝试类似的东西:
statement
: (if_statement)? return_statement
;
(我相信)说 if_statement 是可选的,但 return_statement 必须始终出现。但你可能想尝试类似的东西:
block_data : statements+ return_statement;
Where 语句可以是 if_statements 等,并且允许其中的一个或多个。
我对以上所有内容都持保留态度,因为我只使用 ANTLR4 一周左右。我有 4 个 .g4 文件在工作,并且对 ANTLR 很满意,但实际上你的 ANTLR 坚持时间可能比我多。
-问候
罗斯的回答完全正确。您设计语法以接受特定输入。如果输入流不对应,解析器就会报错。
请允许我这样重写你的语法:
grammar Question;
/* enforce each block to end with a return statement */
a_grammar
: if_statement EOF
;
if_statement
: 'if' expression statement+ ( 'else' statement+ )?
;
statement
: if_statement
// other statements
| statement_block
;
statement_block
: '{' statement* return_statement '}'
;
return_statement
: 'return' ( 'true' | 'false' )
;
expression // reduced to a strict minimum to answer the OP question
: atom
| atom '<=' atom
| '(' expression ')'
;
atom
: ID
| INT
;
ID
: [a-zA-Z] [a-zA-Z_0-9]*
| [0-9]+ [a-zA-Z_]+ [a-zA-Z_0-9]*
;
INT : [0-9]+ ;
WS : [ \t\r\n] -> skip ;
// Anything not recognized above will be an error
ErrChar
: .
;
使用以下输入
if (a <= 7)
{
return true
}
else
if (xyz <= 99)
{
return false
}
else incor@#!$rect
{
if (b <= a)
{
return true
}
return false
}
你得到这些代币
[@0,0:1='if',<'if'>,1:0]
[@1,3:3='(',<'('>,1:3]
[@2,4:4='a',<ID>,1:4]
[@3,6:7='<=',<'<='>,1:6]
...
[@21,82:85='else',<'else'>,10:1]
[@22,87:91='incor',<ID>,10:6]
[@23,92:92='@',<ErrChar>,10:11]
[@24,93:93='#',<ErrChar>,10:12]
[@25,94:94='!',<ErrChar>,10:13]
[@26,95:95='$',<ErrChar>,10:14]
[@27,96:99='rect',<ID>,10:15]
[@28,102:102='{',<'{'>,11:1]
...
line 10:6 mismatched input 'incor' expecting {'if', '{'}
如果您 运行 带有 -gui 选项的测试装置,它会显示带有错误标记的解析树,并以粉红色很好地显示!
grun Question a_grammar -gui data.txt
我仍然是 ANTLR 的新手,很抱歉,如果我发布了一个明显的问题。
我的语法比较简单。我需要的是让用户能够输入如下内容:
if (condition)
{
return true
}
else if (condition)
{
return false
}
else
{
if (condition)
{
return true
}
return false
}
在我下面的语法中,有没有办法确保在输入字符串不包含 'return' 语句时标记错误?如果不能,我可以通过 Listener 实现吗?如果可以,怎么做?
grammar Evaluator;
parse
: block EOF
;
block
: statement
;
statement
: return_statement
| if_statement
;
return_statement
: RETURN (TRUE | FALSE)
;
if_statement
: IF condition_block (ELSE IF condition_block)* (ELSE statement_block)?
;
condition_block
: expression statement_block
;
statement_block
: OBRACE block CBRACE
;
expression
: MINUS expression #unaryMinusExpression
| NOT expression #notExpression
| expression op=(MULT | DIV) expression #multiplicationExpression
| expression op=(PLUS | MINUS) expression #additiveExpression
| expression op=(LTEQ | GTEQ | LT | GT) expression #relationalExpression
| expression op=(EQ | NEQ) expression #equalityExpression
| expression AND expression #andExpression
| expression OR expression #orExpression
| atom #atomExpression
;
atom
: function #functionAtom
| OPAR expression CPAR #parenExpression
| (INT | FLOAT) #numberAtom
| (TRUE | FALSE) #booleanAtom
| ID #idAtom
;
function
: ID OPAR (parameter (',' parameter)*)? CPAR
;
parameter
: expression #expressionParameter
;
OR : '||';
AND : '&&';
EQ : '==';
NEQ : '!=';
GT : '>';
LT : '<';
GTEQ : '>=';
LTEQ : '<=';
PLUS : '+';
MINUS : '-';
MULT : '*';
DIV : '/';
NOT : '!';
OPAR : '(';
CPAR : ')';
OBRACE : '{';
CBRACE : '}';
ASSIGN : '=';
RETURN : 'return';
TRUE : 'true';
FALSE : 'false';
IF : 'if';
ELSE : 'else';
// ID either starts with a letter then followed by any number of a-zA-Z_0-9
// or starts with one or more numbers, then followed by at least one a-zA-Z_ then followed
// by any number of a-zA-Z_0-9
ID
: [a-zA-Z] [a-zA-Z_0-9]*
| [0-9]+ [a-zA-Z_]+ [a-zA-Z_0-9]*
;
INT
: [0-9]+
;
FLOAT
: [0-9]+ '.' [0-9]*
| '.' [0-9]+
;
SPACE
: [ \t\r\n] -> skip
;
// Anything not recognized above will be an error
ErrChar
: .
;
我以前从未玩过 Listener。 通过访问者,在 VisitStatement(StatementContext context) 方法中,检查 context.return_statement() (ReturnStatementContext) 是否为空。如果为null,则抛出异常。
我也是新手。我正在考虑强迫词法分析器通过 需要一个 return 语句,所以而不是:
statement
: return_statement
| if_statement
;
这表示一个语句是 if_statement 或 return_statement 我会尝试类似的东西:
statement
: (if_statement)? return_statement
;
(我相信)说 if_statement 是可选的,但 return_statement 必须始终出现。但你可能想尝试类似的东西:
block_data : statements+ return_statement;
Where 语句可以是 if_statements 等,并且允许其中的一个或多个。
我对以上所有内容都持保留态度,因为我只使用 ANTLR4 一周左右。我有 4 个 .g4 文件在工作,并且对 ANTLR 很满意,但实际上你的 ANTLR 坚持时间可能比我多。
-问候
罗斯的回答完全正确。您设计语法以接受特定输入。如果输入流不对应,解析器就会报错。
请允许我这样重写你的语法:
grammar Question;
/* enforce each block to end with a return statement */
a_grammar
: if_statement EOF
;
if_statement
: 'if' expression statement+ ( 'else' statement+ )?
;
statement
: if_statement
// other statements
| statement_block
;
statement_block
: '{' statement* return_statement '}'
;
return_statement
: 'return' ( 'true' | 'false' )
;
expression // reduced to a strict minimum to answer the OP question
: atom
| atom '<=' atom
| '(' expression ')'
;
atom
: ID
| INT
;
ID
: [a-zA-Z] [a-zA-Z_0-9]*
| [0-9]+ [a-zA-Z_]+ [a-zA-Z_0-9]*
;
INT : [0-9]+ ;
WS : [ \t\r\n] -> skip ;
// Anything not recognized above will be an error
ErrChar
: .
;
使用以下输入
if (a <= 7)
{
return true
}
else
if (xyz <= 99)
{
return false
}
else incor@#!$rect
{
if (b <= a)
{
return true
}
return false
}
你得到这些代币
[@0,0:1='if',<'if'>,1:0]
[@1,3:3='(',<'('>,1:3]
[@2,4:4='a',<ID>,1:4]
[@3,6:7='<=',<'<='>,1:6]
...
[@21,82:85='else',<'else'>,10:1]
[@22,87:91='incor',<ID>,10:6]
[@23,92:92='@',<ErrChar>,10:11]
[@24,93:93='#',<ErrChar>,10:12]
[@25,94:94='!',<ErrChar>,10:13]
[@26,95:95='$',<ErrChar>,10:14]
[@27,96:99='rect',<ID>,10:15]
[@28,102:102='{',<'{'>,11:1]
...
line 10:6 mismatched input 'incor' expecting {'if', '{'}
如果您 运行 带有 -gui 选项的测试装置,它会显示带有错误标记的解析树,并以粉红色很好地显示!
grun Question a_grammar -gui data.txt