ANTLR4语法性能非常差
根据下面的语法,我发现解析较长字符串时的性能非常差,以秒为单位。在Python和Go实现中都会出现这种情况,这种语法中有什么原因导致这种情况吗 示例输出:ANTLR4语法性能非常差,antlr,antlr4,Antlr,Antlr4,根据下面的语法,我发现解析较长字符串时的性能非常差,以秒为单位。在Python和Go实现中都会出现这种情况,这种语法中有什么原因导致这种情况吗 示例输出: 0.000061s LEXING "hello world" 0.014349s PARSING "hello world" 0.000052s LEXING 5 + 10 0.015384s PARSING 5 + 10 0.000061s LEXING FIRST_WORD(WORD_SLICE(contact.blerg, 2, 4))
0.000061s LEXING "hello world"
0.014349s PARSING "hello world"
0.000052s LEXING 5 + 10
0.015384s PARSING 5 + 10
0.000061s LEXING FIRST_WORD(WORD_SLICE(contact.blerg, 2, 4))
0.634113s PARSING FIRST_WORD(WORD_SLICE(contact.blerg, 2, 4))
0.000095s LEXING (DATEDIF(DATEVALUE("01-01-1970"), date.now, "D") * 24 * 60 * 60) + ((((HOUR(date.now)+7) * 60) + MINUTE(date.now)) * 60))
1.552758s PARSING (DATEDIF(DATEVALUE("01-01-1970"), date.now, "D") * 24 * 60 * 60) + ((((HOUR(date.now)+7) * 60) + MINUTE(date.now)) * 60))
这是关于Python的。。虽然我不期望有出色的性能,但我希望任何输入都能达到亚秒级。我做错了什么
grammar Excellent;
parse
: expr EOF
;
expr
: atom # expAtom
| concatenationExpr # expConcatenation
| equalityExpr # expEquality
| comparisonExpr # expComparison
| additionExpr # expAddition
| multiplicationExpr # expMultiplication
| exponentExpr # expExponent
| unaryExpr # expUnary
;
path
: NAME (step)*
;
step
: LBRAC expr RBRAC
| PATHSEP NAME
| PATHSEP NUMBER
;
parameters
: expr (COMMA expr)* # functionParameters
;
concatenationExpr
: atom (AMP concatenationExpr)? # concatenation
;
equalityExpr
: comparisonExpr op=(EQ|NE) comparisonExpr # equality
;
comparisonExpr
: additionExpr (op=(LT|GT|LTE|GTE) additionExpr)? # comparison
;
additionExpr
: multiplicationExpr (op=(ADD|SUB) multiplicationExpr)* # addition
;
multiplicationExpr
: exponentExpr (op=(MUL|DIV) exponentExpr)* # multiplication
;
exponentExpr
: unaryExpr (EXP exponentExpr)? # exponent
;
unaryExpr
: SUB? atom # negation
;
funcCall
: function=NAME LPAR parameters? RPAR # functionCall
;
funcPath
: function=funcCall (step)* # functionPath
;
atom
: path # contextReference
| funcCall # atomFuncCall
| funcPath # atomFuncPath
| LITERAL # stringLiteral
| NUMBER # decimalLiteral
| LPAR expr RPAR # parentheses
| TRUE # true
| FALSE # false
;
NUMBER
: DIGITS ('.' DIGITS?)?
;
fragment
DIGITS
: ('0'..'9')+
;
TRUE
: [Tt][Rr][Uu][Ee]
;
FALSE
: [Ff][Aa][Ll][Ss][Ee]
;
PATHSEP
:'.';
LPAR
:'(';
RPAR
:')';
LBRAC
:'[';
RBRAC
:']';
SUB
:'-';
ADD
:'+';
MUL
:'*';
DIV
:'/';
COMMA
:',';
LT
:'<';
GT
:'>';
EQ
:'=';
NE
:'!=';
LTE
:'<=';
GTE
:'>=';
QUOT
:'"';
EXP
: '^';
AMP
: '&';
LITERAL
: '"' ~'"'* '"'
;
Whitespace
: (' '|'\t'|'\n'|'\r')+ ->skip
;
NAME
: NAME_START_CHARS NAME_CHARS*
;
fragment
NAME_START_CHARS
: 'A'..'Z'
| '_'
| 'a'..'z'
| '\u00C0'..'\u00D6'
| '\u00D8'..'\u00F6'
| '\u00F8'..'\u02FF'
| '\u0370'..'\u037D'
| '\u037F'..'\u1FFF'
| '\u200C'..'\u200D'
| '\u2070'..'\u218F'
| '\u2C00'..'\u2FEF'
| '\u3001'..'\uD7FF'
| '\uF900'..'\uFDCF'
| '\uFDF0'..'\uFFFD'
;
fragment
NAME_CHARS
: NAME_START_CHARS
| '0'..'9'
| '\u00B7' | '\u0300'..'\u036F'
| '\u203F'..'\u2040'
;
ERRROR_CHAR
: .
;
您始终可以首先尝试使用SLL*进行解析,只有当解析失败时,您才需要使用默认的LL*进行解析 请参阅ANTLR的GitHub上的ticket以获得进一步的解释,这是一个使用此策略的实现
当解析语法正确的输入时,此方法将为您节省大量时间。您始终可以尝试首先使用SLL*进行解析,并且只有当解析失败时,您才需要使用默认的LL*进行解析 请参阅ANTLR的GitHub上的ticket以获得进一步的解释,这是一个使用此策略的实现
当解析语法正确的输入时,此方法将为您节省大量时间。这种性能似乎是由于加法/乘法等运算符中使用了左递归。相反,将这些规则重写为二进制规则会产生即时的性能。见下文
grammar Excellent;
COMMA : ',';
LPAREN : '(';
RPAREN : ')';
LBRACK : '[';
RBRACK : ']';
DOT : '.';
PLUS : '+';
MINUS : '-';
TIMES : '*';
DIVIDE : '/';
EXPONENT : '^';
EQ : '=';
NEQ : '!=';
LTE : '<=';
LT : '<';
GTE : '>=';
GT : '>';
AMPERSAND : '&';
DECIMAL : [0-9]+('.'[0-9]+)?;
STRING : '"' (~["] | '""')* '"';
TRUE : [Tt][Rr][Uu][Ee];
FALSE : [Ff][Aa][Ll][Ss][Ee];
NAME : [a-zA-Z][a-zA-Z0-9_.]*; // variable names, e.g. contact.name or function names, e.g. SUM
WS : [ \t\n\r]+ -> skip; // ignore whitespace
ERROR : . ;
parse : expression EOF;
atom : fnname LPAREN parameters? RPAREN # functionCall
| atom DOT atom # dotLookup
| atom LBRACK expression RBRACK # arrayLookup
| NAME # contextReference
| STRING # stringLiteral
| DECIMAL # decimalLiteral
| TRUE # true
| FALSE # false
;
expression : atom # atomReference
| MINUS expression # negation
| expression EXPONENT expression # exponentExpression
| expression (TIMES | DIVIDE) expression # multiplicationOrDivisionExpression
| expression (PLUS | MINUS) expression # additionOrSubtractionExpression
| expression (LTE | LT | GTE | GT) expression # comparisonExpression
| expression (EQ | NEQ) expression # equalityExpression
| expression AMPERSAND expression # concatenation
| LPAREN expression RPAREN # parentheses
;
fnname : NAME
| TRUE
| FALSE
;
parameters : expression (COMMA expression)* # functionParameters
;
这种性能似乎是由于加法/乘法等运算符中使用了左递归。相反,将这些规则重写为二进制规则会产生即时的性能。见下文
grammar Excellent;
COMMA : ',';
LPAREN : '(';
RPAREN : ')';
LBRACK : '[';
RBRACK : ']';
DOT : '.';
PLUS : '+';
MINUS : '-';
TIMES : '*';
DIVIDE : '/';
EXPONENT : '^';
EQ : '=';
NEQ : '!=';
LTE : '<=';
LT : '<';
GTE : '>=';
GT : '>';
AMPERSAND : '&';
DECIMAL : [0-9]+('.'[0-9]+)?;
STRING : '"' (~["] | '""')* '"';
TRUE : [Tt][Rr][Uu][Ee];
FALSE : [Ff][Aa][Ll][Ss][Ee];
NAME : [a-zA-Z][a-zA-Z0-9_.]*; // variable names, e.g. contact.name or function names, e.g. SUM
WS : [ \t\n\r]+ -> skip; // ignore whitespace
ERROR : . ;
parse : expression EOF;
atom : fnname LPAREN parameters? RPAREN # functionCall
| atom DOT atom # dotLookup
| atom LBRACK expression RBRACK # arrayLookup
| NAME # contextReference
| STRING # stringLiteral
| DECIMAL # decimalLiteral
| TRUE # true
| FALSE # false
;
expression : atom # atomReference
| MINUS expression # negation
| expression EXPONENT expression # exponentExpression
| expression (TIMES | DIVIDE) expression # multiplicationOrDivisionExpression
| expression (PLUS | MINUS) expression # additionOrSubtractionExpression
| expression (LTE | LT | GTE | GT) expression # comparisonExpression
| expression (EQ | NEQ) expression # equalityExpression
| expression AMPERSAND expression # concatenation
| LPAREN expression RPAREN # parentheses
;
fnname : NAME
| TRUE
| FALSE
;
parameters : expression (COMMA expression)* # functionParameters
;
您的联系人是什么。blerg?您使用的是哪一版本的ANTLR4?我使用的是Antlr 4.7您的联系人是什么。blerg?您使用的是哪一版本的ANTLR4?我使用的是Antlr 4.7。在实际情况下,SLL*和LL*之间是否存在显著的性能差异?LL*在进行自上而下的解析时可能会有更多的歧义,这种歧义会如何影响性能?是的,有。。。我用LL*解析文件需要约20秒,用SLL*解析文件需要约600毫秒。我从来没有遇到过SLL*在语法正确的输入方面失败的情况。如果这样做了,解析器将切换回LL*,因此在这种情况下,以前完成的SLL*解析所用的时间将被浪费。但正如我所说,对于有效输入,在实际情况下,SLL*和LL*之间是否存在显著的性能差异?LL*在进行自上而下的解析时可能会有更多的歧义,这种歧义会如何影响性能?是的,有。。。我用LL*解析文件需要约20秒,用SLL*解析文件需要约600毫秒。我从来没有遇到过SLL*在语法正确的输入方面失败的情况。如果这样做了,解析器将切换回LL*,因此在这种情况下,以前完成的SLL*解析所用的时间将被浪费。但正如我所说的,我从未体验过有效输入的这种情况,难道你把语法搞混了吗?这个答案中的语法使用左递归,而你问题中的语法不使用左递归。这与您的答案文本相矛盾,您说左递归移除会导致更好的性能。完全可能我的命名不正确,将把示例和语法作为示例,以便其他人能够理解。您是否会在这里混淆语法?这个答案中的语法使用左递归,而你问题中的语法不使用左递归。这与你的答案文本相矛盾,你说左递归移除会导致更好的性能。完全可能我的命名不正确,我会将示例和语法作为示例,以便其他人能够理解。