某些语法场景的语法验证问题
Issue with syntax validations for certain scenarios with grammar
我已经编写了用于创建简单表达式的基本语法(add、mul、div、mod、min 以及使用带有一些参数的函数)。
语法:
grammar ExpressionGrammar;
parse: expr EOF;
expr:
MIN expr
| expr ( MUL | DIV) expr
| expr ( ADD | MIN) expr
| expr ( MOD ) expr
| NUM
| ID
| STRING
| function
| '(' expr ')';
function: ID '(' arguments? ')';
arguments: expr ( ',' expr)*;
/* Tokens */
MUL: '*';
DIV: '/';
MIN: '-';
ADD: '+';
MOD: '%';
OPEN_PAR: '(';
CLOSE_PAR: ')';
NUM: ([0-9]*[.])?[0-9]+;
STRING: '"' ~ ["]* '"';
fragment ID_NODE: [a-zA-Z_$][a-zA-Z0-9_$]*;
ID: ID_NODE ('.' ID_NODE)*;
COMMENT: '/*' .*? '*/' -> skip;
LINE_COMMENT
: '//' ~[\r\n]* -> skip
;
WS: [ \r\t\n]+ -> skip;
有效表达式示例:
1. 1+2 - simple add, multiply, divide and mod operations.
2. "adadfasdf" -- simply return a string
3. 233.4234234 -- return a number
4. field.value1 -- field is a fieldType on which value exists ( field with multiple values)
3. SUBSTR("asdfasdf","adsfasdff","asd"); -- a built in function ( such as SUBSTR, ADD, MIN, etc ) which takes arguments.
4. ABS(field.value1)
5. ADD( field.value1,field.value2)
6. MAX( field.value1,field.value3, 2)
7. field.value1 % field.value2
8. It can even span multiple lines
ADD(
field.value1,
2,
ABS(field.valu2) -- can have another function inside this function.
)
ANTLR 在某些情况下当用户输入错误的语法时抛出语法错误
但以下情况未显示为错误。
允许多个右括号:trim(fields.value1))))))))
允许多个表达式之间没有任何运算符(当使用两个字段之间没有任何运算符时不会抛出任何错误):
field.v1 field.v2
当我在多行中有两个不同的表达式时也不会抛出错误(可能是上述情况的扩展)。
field.v1 + 2
field.v2 + 3
当有多个收盘价时不显示任何错误 - "adfadsfad""""""
以上所有情况都可能与我的语法问题有关?不确定。
谁能帮我纠正我的语法以发现这些错误?
这些是您调用的规则中没有 EOF 的典型症状。
如果不包含 EOF,那么 ANTLR4 将解析所有匹配的输入并退出(在输入流结束之前,如果没有其他匹配)。
在你的每个例子中,如果你把它看成“有一些有效的东西,然后是无效的输入”,你会发现它们都是合适的。
这就是为什么 @sepp2k 询问您调用了哪个规则。
很明显您可能调用了 expr
规则而不是 parse
规则(因为 parse
规则确实包含 EOF 标记,它将继续解析直到它看到一个 EOF,并会在此过程中报告错误)。
当您生成 ANTLR 代码时,它会生成 methods/functions 以从您想要的任何规则开始。您必须编写一些代码来创建输入流,然后从该流创建一个 Lexer,然后从您从 Lexer 获得的 TokenStream 创建一个 Parser。最后,一旦您拥有解析器对象,您将选择要调用的解析器规则。
将该规则从 expr()
更改为 parse()
,您应该会开始收到预期的错误。
基本上,解析器规则中的 EOF 表示整个输入必须匹配此规则(即它还必须使用“文件结束”标记)。如果没有该标记,规则可以(并且将会)匹配任何与规则匹配的内容,并在无法再找到有效输入时停止。
只看到一个以 EOF 结尾的“顶级”或“入口”规则是很常见的。这通常是一个线索,表明它是您调用的解析器规则。
几个例外:
- 也许您想要只解析您可以匹配的任何内容而忽略其余部分。然后使用没有终端 EOF 的规则。 (这可能相当罕见)。
- 也许在某些情况下,您知道自己的输入只能是
expr
,但您的顶级规则类似于 stmts
或 compilationUnit
。在这种情况下,您可以创建一个 exprOnly: expr EOF;
规则,然后调用该规则来解析表达式,除非整个输入与 expr
的语法匹配,否则该表达式将失败。您不会有任何其他规则引用 exprOnly
规则,有效地使其成为顶级或入口规则。没有什么可以阻止您有多个顶级规则可供选择。
任何规则中的 EOF 被另一个规则引用,但期望匹配 EOF,很可能(几乎可以肯定)是一个错误。
注意:毫无疑问,您会发现顶级规则不以 EOF 标记结尾的语法。这被认为是一种不好的做法(正是由于您遇到的原因;它可以在不消耗所有输入的情况下成功解析。
我已经编写了用于创建简单表达式的基本语法(add、mul、div、mod、min 以及使用带有一些参数的函数)。
语法:
grammar ExpressionGrammar;
parse: expr EOF;
expr:
MIN expr
| expr ( MUL | DIV) expr
| expr ( ADD | MIN) expr
| expr ( MOD ) expr
| NUM
| ID
| STRING
| function
| '(' expr ')';
function: ID '(' arguments? ')';
arguments: expr ( ',' expr)*;
/* Tokens */
MUL: '*';
DIV: '/';
MIN: '-';
ADD: '+';
MOD: '%';
OPEN_PAR: '(';
CLOSE_PAR: ')';
NUM: ([0-9]*[.])?[0-9]+;
STRING: '"' ~ ["]* '"';
fragment ID_NODE: [a-zA-Z_$][a-zA-Z0-9_$]*;
ID: ID_NODE ('.' ID_NODE)*;
COMMENT: '/*' .*? '*/' -> skip;
LINE_COMMENT
: '//' ~[\r\n]* -> skip
;
WS: [ \r\t\n]+ -> skip;
有效表达式示例:
1. 1+2 - simple add, multiply, divide and mod operations.
2. "adadfasdf" -- simply return a string
3. 233.4234234 -- return a number
4. field.value1 -- field is a fieldType on which value exists ( field with multiple values)
3. SUBSTR("asdfasdf","adsfasdff","asd"); -- a built in function ( such as SUBSTR, ADD, MIN, etc ) which takes arguments.
4. ABS(field.value1)
5. ADD( field.value1,field.value2)
6. MAX( field.value1,field.value3, 2)
7. field.value1 % field.value2
8. It can even span multiple lines
ADD(
field.value1,
2,
ABS(field.valu2) -- can have another function inside this function.
)
ANTLR 在某些情况下当用户输入错误的语法时抛出语法错误 但以下情况未显示为错误。
允许多个右括号:
trim(fields.value1))))))))
允许多个表达式之间没有任何运算符(当使用两个字段之间没有任何运算符时不会抛出任何错误):
field.v1 field.v2
当我在多行中有两个不同的表达式时也不会抛出错误(可能是上述情况的扩展)。
field.v1 + 2 field.v2 + 3
当有多个收盘价时不显示任何错误 -
"adfadsfad""""""
以上所有情况都可能与我的语法问题有关?不确定。
谁能帮我纠正我的语法以发现这些错误?
这些是您调用的规则中没有 EOF 的典型症状。
如果不包含 EOF,那么 ANTLR4 将解析所有匹配的输入并退出(在输入流结束之前,如果没有其他匹配)。
在你的每个例子中,如果你把它看成“有一些有效的东西,然后是无效的输入”,你会发现它们都是合适的。
这就是为什么 @sepp2k 询问您调用了哪个规则。
很明显您可能调用了 expr
规则而不是 parse
规则(因为 parse
规则确实包含 EOF 标记,它将继续解析直到它看到一个 EOF,并会在此过程中报告错误)。
当您生成 ANTLR 代码时,它会生成 methods/functions 以从您想要的任何规则开始。您必须编写一些代码来创建输入流,然后从该流创建一个 Lexer,然后从您从 Lexer 获得的 TokenStream 创建一个 Parser。最后,一旦您拥有解析器对象,您将选择要调用的解析器规则。
将该规则从 expr()
更改为 parse()
,您应该会开始收到预期的错误。
基本上,解析器规则中的 EOF 表示整个输入必须匹配此规则(即它还必须使用“文件结束”标记)。如果没有该标记,规则可以(并且将会)匹配任何与规则匹配的内容,并在无法再找到有效输入时停止。
只看到一个以 EOF 结尾的“顶级”或“入口”规则是很常见的。这通常是一个线索,表明它是您调用的解析器规则。
几个例外:
- 也许您想要只解析您可以匹配的任何内容而忽略其余部分。然后使用没有终端 EOF 的规则。 (这可能相当罕见)。
- 也许在某些情况下,您知道自己的输入只能是
expr
,但您的顶级规则类似于stmts
或compilationUnit
。在这种情况下,您可以创建一个exprOnly: expr EOF;
规则,然后调用该规则来解析表达式,除非整个输入与expr
的语法匹配,否则该表达式将失败。您不会有任何其他规则引用exprOnly
规则,有效地使其成为顶级或入口规则。没有什么可以阻止您有多个顶级规则可供选择。
任何规则中的 EOF 被另一个规则引用,但期望匹配 EOF,很可能(几乎可以肯定)是一个错误。
注意:毫无疑问,您会发现顶级规则不以 EOF 标记结尾的语法。这被认为是一种不好的做法(正是由于您遇到的原因;它可以在不消耗所有输入的情况下成功解析。