【问题标题】:ANTLR error:no viable alternative at input '<EOF>'. How to fix it?ANTLR 错误:输入 '<EOF>' 没有可行的替代方案。如何解决?
【发布时间】:2017-12-02 01:30:22
【问题描述】:

我是 ANTLR 的新手。并且在使用 ANTLR 编译 2 个 JAVA 文件时遇到了同样的错误。树看起来很好,没有缺陷的叶子。我找不到有关此错误根本原因的任何线索。 我使用的 ANTLR 版本是“ANTLR 4”。 有人知道如何解决吗?提前致谢!

1) ANTLR 文件为 test.g4 如下,

grammar test;

// Syntax Specification ==> Context-free Grammar 
pa1: 
     mainClass aClass*;

mainClass: 
    classDeclaration '{' mainDeclaration ('{'body'}'|'{''{'body'}''}') '}';

mainDeclaration:
    'public' 'static' 'void' 'main' '(' 'String''['']' ID ')';

aClass:
    classDeclaration '{' body '}';

classDeclaration:
    'class' ID;

aMethod:
    methodDeclaration'{'body'}';

methodDeclaration:
    type ID'('parameterList')';

body:
    (varDeclaration|statement|expression|aMethod)*;

varDeclaration:
    type ID ';' ;

statement: 
    (ID|arrayElement) '=' (NUM|ID|string|aChar|('new' type)? arrayElement|'new' (type|ID) '('')'|aCall|mathExpression)';';  //(ID|arrayElement) '=' (NUM|ID|string|aChar|arrayElement|aCall|mathExpression|booleanExpression)';';

string:
    '"' .*? '"';

aChar:
    '\''(.?|'+'|'-')'\'';

expression: 
    ID';'|whileExpression|ifExpression|sysPrintExpression|returnExpression;

ifExpression:
    'if''('booleanExpression')' ((varDeclaration|statement|expression)*|'{'(varDeclaration|statement|expression)*'}')
    ('else''if''('booleanExpression')' ((varDeclaration|statement|expression)*|'{'(varDeclaration|statement|expression)*'}'))?  
    ('else'((varDeclaration|statement|expression)*|'{'(varDeclaration|statement|expression)*'}'))?;

whileExpression: 
    'while''('booleanExpression')' '{'(varDeclaration|statement|expression)*'}';

sysPrintExpression: 
    'System''.''out''.''println''('(NUM|arrayElement|aCall)')'';';

returnExpression: 
    'return'(NUM|ID)';';

compExpression: 
    (ID|NUM|mathExpression) COMPOPERATOR (ID|NUM|'('mathExpression')'|'('ID')');

mathExpression: 
    (ID|NUM) (PLUS|MINUS|MULT|DIV)(ID|NUM|('('ID'.'ID'('parameterList')'')'));  

singleBooleanExpression: 
    '!'?('('compExpression')'|compExpression|aCall|ID);//(LOGICALOPERATOR('!'?(compExpression|aCall|ID|string|aChar)))?;    

doubleBooleanExpression: 
    '(''!'?('('compExpression')'|compExpression|aCall|ID)')'LOGICALOPERATOR('(''!'?(compExpression|aCall|ID|string|aChar)')');

booleanExpression:
    singleBooleanExpression|doubleBooleanExpression;    

aCall: 
    (ID|'new'? ID '('')')calling|'('(ID|ID'('')')calling')'calling;

calling:
    '.'(ID('('parameterList')')?);  

parameterList: 
    (NUM|type? ID|aChar|string|mathExpression|aCall)?(','(NUM|type? ID|aChar|mathExpression))*;

arrayElement: 
    ID?'['(ID|NUM)']';

type: 
    'int''['']'|'boolean'|'int'|'char'|ID;  

// Lexer Specification ==> Regular Expressions  
NUM: ('0' | [1-9][0-9]*);
ID: [a-zA-Z_][0-9a-zA-Z_]*;
PLUS : '+' ;
MINUS : '-' ;
MULT : '*' ;
DIV : '/';
COMPOPERATOR: '<'|'>'; 
LOGICALOPERATOR: '=='|'||'|'&&';
WHITESPACE: [ \t\r\n]+  -> skip; 
COMMENT: ('/*'.*?'*/'|'//'~[\r\n|\r|\n]*) -> skip; 

2) JAVA file1 是 MyChar.java 如下,

class MyChar{
    public static void main(String[] a){
        {
            System.out.println(new CharEditor().whichIsSmaller('a', 'c'));
            System.out.println(new CharEditor().whichIsSmaller('a', 'A'));
            System.out.println(new CharEditor().whichIsSmaller('1', 'd'));
            System.out.println(new CharEditor().whichIsSmaller('-', '+'));
            // System.out.println("There are total " + new MyChar().countFromCharToChar('a', 'z', true) + " characters in between a and z");
            System.out.println(new CharEditor().countChars("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 'c'));
        }
    }
}

class CharEditor {

    char whichIsSmaller(char firstChar, char secondChar){
        char returnChar;

        if(secondChar < firstChar) //the comparison is based on the character's ASCII code
        returnChar = firstChar;
        else
        returnChar = secondChar;
        return returnChar;
    }

    int countChars(String str, char c){
        int n;
        int sz;
        char c1;
        int counter;

        counter = 0;

        sz = str.length();
        n = 0;
        while ( n < sz ) {
            c1 = str.charAt(n);
            if ( c1 == c) {
                counter = counter + 1;
            }
            n = n + 1;
        }
        return counter;
    }
}

3)JAVA file2 为 MyString.java 如下,

class MyString{
    public static void main(String[] a){
        {
            System.out.println(new StringEditor().removeSpace("Hello World And Happy Coding"));
            System.out.println(new StringEditor().containsChar("Hello World And Happy Coding", 'd'));
            System.out.println(new StringEditor().containsChar("Hello World And Happy Coding", 'b'));
        }
    }
}

class StringEditor {
    String removeSpace(String str) {
        String toReturn;
        int n;
        int sz;
        char c;

        toReturn = "";
        sz = str.length();
        n = 0;
        while ( n < sz ) {
            c = str.charAt(n);
            if ( c == ' ') {

            } else {
                toReturn = toReturn + c;
            }
            n = n+1;
        }

        return toReturn;
    }

    boolean containsChar(String str, char c) {
        int n;
        int sz;
        char c1;

        boolean toReturn;

        toReturn = false;

        sz = str.length();
        n = 0;
        while ( n < sz ) {
            c1 = str.charAt(n);
            if ( c1 == c) {
                toReturn = true;
                break;
            }
            n = n+1;
        }

        return toReturn;
    }
}

【问题讨论】:

  • 关于文件 1,语法无法解析第 26 行 int countChars(String str, char c){,因为规则 type 中缺少 String。同时将==LOGICALOPERATOR移动到COMPOPERATOR
  • 谢谢伯纳德!它适用于文件 1。在你的启发下,我也为文件 2 解决了它。

标签: antlr


【解决方案1】:

尽管您已经解决了文件 2 的问题,但我仍然发布了我正在处理的答案。

如果出现问题,首先要做的是显示标记以查看词法分析器如何解释输入。这往往不是我们所相信的。使用文件 2:

$ grun Question question -tokens -diagnostics input2.text 
...
[@131,652:653='if',<'if'>,23:12]
[@132,655:655='(',<'('>,23:15]
[@133,657:657='c',<ID>,23:17]
[@134,659:660='==',<COMP_OPERATOR>,23:19]
[@135,662:662=''',<'''>,23:22]
[@136,664:664=''',<'''>,23:24]
[@137,665:665=')',<')'>,23:25]
[@138,667:667='{',<'{'>,23:27]
[@139,682:682='}',<'}'>,25:12]

表明在语句 23 中

    if ( c == ' ') {

单个空格字符被解释为两个单独的',而不是按照规则

aChar:
    '\'' ( .? | '+' | '-' ) '\'';

因为在这个解析器规则aChar中,撇号被隐式定义为一个记号,所以空格被扔掉了

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

并且没有词法分析器规则强制词法分析器将' ' 视为一个整体。这就是为什么我将解析器规则aChar 更改为词法分析器规则

A_CHAR : '\'' ( '+' | '-' | .? ) '\'' ;

现在标记是正确的:

[@127,652:653='if',<'if'>,23:12]
[@128,655:655='(',<'('>,23:15]
[@129,657:657='c',<ID>,23:17]
[@130,659:660='==',<COMP_OPERATOR>,23:19]
[@131,662:664='' '',<A_CHAR>,23:22]
[@132,665:665=')',<')'>,23:25]

另请注意,使用string 解析器规则,"Lorem ipsum dolor sit met ..." 的每个单词都被解释为ID,而使用词法分析器规则STRING,整个句子被捕获在一个标记中。

另一个改进是应用 DRY 原则(不要重复自己)。例如在ifExpression 中,表达式(varDeclaration|statement|expression) 重复了6 次。这可以使用子规则来减少。

因此语法可以是:

grammar Question;

question
@init {System.out.println("Question last update 1803");}

// Syntax Specification ==> Context-free Grammar 
    :   mainClass aClass*;

mainClass
    :   classDeclaration '{' mainDeclaration declaration_block '}';

mainDeclaration:
    'public' 'static' 'void' 'main' '(' 'String' '[' ']' ID ')';

aClass:
    classDeclaration declaration_block ;

classDeclaration:
    'class' ID;

aMethod:
    methodDeclaration declaration_block ;

methodDeclaration:
    type ID parameterList ;

declaration_block
    :   '{' declarattion_body* '}'
    |   '{' declaration_block '}'
    ;

declarattion_body
    :   statement
    |   aMethod
    ;

statement_block
    :   '{' statement* '}'
    ;

statement
    :   varDeclaration
    |   assignment
    |   statement_expression
    ;

varDeclaration:
    type ID ';' ;

assignment: 
    (ID|arrayElement) '=' (NUM|ID|STRING|A_CHAR|('new' type)? arrayElement|'new' (type|ID) '('')'|aCall|mathExpression)';';  //(ID|arrayElement) '=' (NUM|ID|STRING|A_CHAR|arrayElement|aCall|mathExpression|booleanExpression)';';

statement_expression
    :   ID ';'
    |   whileExpression
    |   ifExpression
    |   sysPrintExpression
    |   returnExpression
    ;

ifExpression
    :   'if' '(' booleanExpression ')' statement_if
        ( 'else' 'if' '(' booleanExpression ')' statement_if )?  
        ( 'else' statement_if )?
    ;

statement_if
    :   statement*
    |   statement_block
    ;

whileExpression
    :   'while' '(' booleanExpression ')' statement_block
    ;

sysPrintExpression: 
    'System''.''out''.''println''('(NUM|arrayElement|aCall)')'';';

returnExpression: 
    'return'(NUM|ID)';';

compExpression
    :   ( ID | NUM | mathExpression ) COMP_OPERATOR ( ID | NUM | A_CHAR | '(' mathExpression ')' | '(' ID ')' ) ;

mathExpression: 
    (ID|NUM) (PLUS|MINUS|MULT|DIV) ( ID | NUM | ( '(' ID '.' ID parameterList ')' ));  

singleBooleanExpression
    :   '!'? ( '(' compExpression ')' | compExpression | aCall | ID ) ; //(LOGICAL_OPERATOR('!'?(compExpression|aCall|ID|STRING|A_CHAR)))?;    

doubleBooleanExpression: 
    '(''!'?('('compExpression')'|compExpression|aCall|ID)')'LOGICAL_OPERATOR('(''!'?(compExpression|aCall|ID|STRING|A_CHAR)')');

booleanExpression
    :   singleBooleanExpression
    |   doubleBooleanExpression
    ;

aCall: 
    (ID|'new'? ID '('')')calling|'('(ID|ID'('')')calling')'calling;

calling:
    '.' ( ID ( parameterList )? ) ;  

parameterList
    :   '('  
        ( NUM | type? ID | A_CHAR | STRING | mathExpression | aCall )? 
        ( ',' ( NUM | type? ID | A_CHAR | mathExpression ) )*
        ')'
    ;

arrayElement: 
    ID? '[' ( ID | NUM ) ']' ;

type
    :   'int' '[' ']'
    |   'boolean'
    |   'int'
    |   'char'
    |   'String' // <----- added
    |   ID;  

// Lexer Specification ==> Regular Expressions  
NUM   : '0' | [1-9][0-9]* ;
ID    : [a-zA-Z_][0-9a-zA-Z_]* ;
PLUS  : '+' ;
MINUS : '-' ;
MULT  : '*' ;
DIV   : '/' ;
COMP_OPERATOR    : '<' | '>' | '==' ;  // <----- changed
LOGICAL_OPERATOR : '||' | '&&' ; // <----- changed
STRING : '"' .*? '"' ;
A_CHAR : '\'' ( '+' | '-' | .? ) '\'' ;
WHITESPACE: [ \t\r\n]+  -> skip; 
//COMMENT: ('/*'.*?'*/'|'//'~[\r\n|\r|\n]*) -> skip; 
/*
warning(180): Question.g4:103:27: chars "" used multiple times in set [\r\n|\r|\n]
warning(180): Question.g4:103:27: chars "|" used multiple times in set [\r\n|\r|\n]
warning(180): Question.g4:103:27: chars "
" used multiple times in set [\r\n|\r|\n]
*/
COMMENT      : '/*' .*? '*/' -> skip ;
LINE_COMMENT : '//' ~[\r\n]* -> skip; 

但它只适用于两个发布的文件。有了这个:

class MyString{
    public static void main(String[] a){
        {
        }
    }
}

public class test {
    public static class UnderlineListener extends BaseErrorListener {
    }
}

它不起作用:

$ grun Question question input3.text 
Question last update 1803
line 8:0 extraneous input 'public' expecting {<EOF>, 'class'}
line 9:1 no viable alternative at input '{public'
line 9:39 mismatched input 'extends' expecting '{'

为现有语言编写语法令人兴奋,但也很困难。有准备去 Java 语法from the Antlr site -> 下载

-> 源代码库

github 一切顺利

-> 附加语法

This repository

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-26
    • 2021-06-06
    • 2016-01-14
    • 1970-01-01
    • 2022-11-04
    相关资源
    最近更新 更多