【问题标题】:Antlr3 report java.lang.OutOfMemoryError when parse expressionAntlr3 解析表达式时报 java.lang.OutOfMemoryError
【发布时间】:2016-07-13 10:44:47
【问题描述】:

我尝试匹配字符串"match 'match content'",同时提取单引号内的匹配内容。但抛出以下异常:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at org.antlr.runtime.Lexer.emit(Lexer.java:160)
    at org.antlr.runtime.Lexer.nextToken(Lexer.java:91)
    at org.antlr.runtime.BufferedTokenStream.fetch(BufferedTokenStream.java:133)
    at org.antlr.runtime.BufferedTokenStream.sync(BufferedTokenStream.java:127)
    at org.antlr.runtime.CommonTokenStream.consume(CommonTokenStream.java:70)
    at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:106)

我不知道为什么会抛出 OOM 异常,我在 dot g 文件中找不到错误定义。

我的 .g 文件:

grammar Contains;

options {
    language=Java;
    output=AST;
    ASTLabelType=CommonTree;
    backtrack=false;
    k=3;
}

match
    :
    KW_MATCH SINGLE_QUOTE ( ~(SINGLE_QUOTE|'\\') | ('\\' .) )+ SINGLE_QUOTE
    ;

regexp 
    :
    KW_REGEXP SINGLE_QUOTE RegexComponent+ SINGLE_QUOTE
    ;

range 
    :
    KW_RANGE  SINGLE_QUOTE left=(LPAREN | LSQUARE) start=Number COMMA end = Number right=(RPAREN | RSQUARE) SINGLE_QUOTE
    ;


DOT : '.'; // generated as a part of Number rule
COLON : ':' ;
COMMA : ',' ;

LPAREN : '(' ;
RPAREN : ')' ;
LSQUARE : '[' ;
RSQUARE : ']' ;
LCURLY : '{';
RCURLY : '}';

PLUS : '+';
MINUS : '-';
STAR : '*';

BITWISEOR : '|';
BITWISEXOR : '^';
QUESTION : '?';
DOLLAR : '$';

KW_RANGE : 'RANGE';
KW_REGEXP : 'REGEXP';
KW_MATCH : 'MATCH';

DOUBLE_QUOTE : '\"';
SINGLE_QUOTE : '\'';

fragment
Digit
    :
    '0'..'9'
    ;

fragment
Exponent
    :
    ('e' | 'E') ( PLUS|MINUS )? (Digit)+
    ;

fragment
RegexComponent
    : 'a'..'z' | 'A'..'Z' | '0'..'9' | '_'
    | PLUS | STAR | QUESTION | MINUS | DOT
    | LPAREN | RPAREN | LSQUARE | RSQUARE | LCURLY | RCURLY
    | BITWISEXOR | BITWISEOR | DOLLAR | '\u0080'..'\u00FF' | '\u0400'..'\u04FF'
    | '\u0600'..'\u06FF' | '\u0900'..'\u09FF' | '\u4E00'..'\u9FFF' | '\u0A00'..'\u0A7F'
    ;

Number
    :
    (Digit)+ ( DOT (Digit)* (Exponent)? | Exponent)?
    ;

WS  :  (' '|'\r'|'\t'|'\n'|'\u000C')* {$channel=HIDDEN;}
    ;

【问题讨论】:

    标签: java antlr3


    【解决方案1】:

    你可以从改变开始:

    WS  :  (' '|'\r'|'\t'|'\n'|'\u000C')* {$channel=HIDDEN;}
        ;
    

    到:

    WS  :  (' '|'\r'|'\t'|'\n'|'\u000C')+ {$channel=HIDDEN;}
        ;
    

    您的版本匹配一个空字符串,这可能会产生无限数量的令牌(可能会引发 OOME)。

    【讨论】:

    • 我的版本是3.4,我试过用你的方法,还是出现异常!
    • 您是否从编辑的语法文件中重新生成了词法分析器?您能否添加一个重现此异常的小型 Java 应用程序?
    • 是啊,OOM还是这样复制的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    相关资源
    最近更新 更多