有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

作用域中的java Antlr check返回语句

我想知道如何在语法分析期间检查函数中的所有路径是否都有返回。假设我在Lexer中有以下内容

RETURN: 'return';
PRINT: 'print';
IF:'if';
ELSE: 'else';
THEN:'then';
PLUS: '+';
MINUS:'-';
EQUALS: '==';
DIGIT: '0'..'9';
OPEN:'{';
CLOSE:'}';
STRING: [a..zA..Z]+;
SEMICOLON: ';';

和解析器

function: STRING OPEN statement CLOSE
statement: RETURN expr | PRINT expr | IF expr THEN statement ELSE statement | statement SEMICOLON statement;
expr: DIGIT| expr PLUS expr | expr MINUS expr | expr EQUALS expr;

我的问题是一个有效的函数应该有一个return语句,后面什么都没有。 所以一个有效的是

test { return 2+2 }

或者

test{ if 2 == 2 then return 2 else return 3 }

如果返回后有无法访问的代码,则返回无效代码。例如

test{return 2; print 3}

我该如何检查返回语句后是否没有任何内容

我的主要java方法如下所示:

MyLexer mylexer = new MyLexer(new ANTLRInputStream(System.in));
CommonTokenStream toks = new CommonTokenStream(mylexer);
MyParser parser = new MyParser(tokens);
ParseTree parseTree = parser.program();

共 (1) 个答案

  1. # 1 楼答案

    我不是专家,直到今天才使用过错误报告,但是如果你只是想要一个错误列表,你可以根据The Definitive ANTLR 4 Reference第9章的启发做以下事情

    文件Question.g4

    grammar Question;
    
    /* Detecting invalid input after a return statement. */
    
    question
    @init {System.out.println("Question last update 1302");}
        :   function+ EOF
        ;
    
    function
        :   STRING OPEN statement_block CLOSE
        ;
    
    statement_block
        :   statement* if_last? return_statement
        ;
    
    statement
        :   PRINT expr
        |   IF expr THEN statement ELSE statement
        |   statement SEMICOLON statement
        ;
    
    if_last
        :   IF expr THEN statement_block ELSE statement*
        ;
    
    return_statement
        :   RETURN expr
        ;
    
    expr
        :   DIGIT
        |   expr PLUS expr
        |   expr MINUS expr
        |   expr EQUALS expr
        ;
    
    CLOSE  : '}' ;
    ELSE   : 'else' ;
    EQUALS : '==' ;
    IF     : 'if' ;
    MINUS  : '-' ;
    OPEN   : '{' ;
    PLUS   : '+' ;
    PRINT  : 'print' ;
    RETURN : 'return' ;
    THEN   : 'then' ;
    
    DIGIT     : [0-9] ;
    STRING    : [a-zA-Z]+ ;
    SEMICOLON : ';' ;
    
    WS  : [ \r\n\t] -> channel(HIDDEN) ;
    

    文件MyListener.java

    public class MyListener extends QuestionBaseListener {
        QuestionParser parser;
        public MyListener(QuestionParser parser) { this.parser = parser; }
    
        public void exitFunction(QuestionParser.FunctionContext ctx) {
            System.out.println(">>> in MyListener for function");
            System.out.println(parser.getTokenStream().getText(ctx));
        }
    }
    

    文件test.java

    import org.antlr.v4.runtime.*;
    
    import org.antlr.v4.runtime.tree.*;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.IOException;
    import java.util.*;
    
    public class test {
        public static class UnderlineListener extends BaseErrorListener {
            public void syntaxError(Recognizer<?, ?> recognizer,
                                    Object offendingSymbol,
                                    int line, int charPositionInLine,
                                    String msg,
                                    RecognitionException e)
            {
                System.err.println("line " + line + ":" + charPositionInLine + " " + msg);
                underlineError(recognizer,(Token)offendingSymbol,
                    line, charPositionInLine);
            }
    
            protected void underlineError(Recognizer recognizer,
                                          Token offendingToken, int line,
                                          int charPositionInLine) {
                CommonTokenStream tokens =
                    (CommonTokenStream)recognizer.getInputStream();
                String input = tokens.getTokenSource().getInputStream().toString();
                String[] lines = input.split("\n");
                String errorLine = lines[line - 1];
                System.err.println(errorLine);
                for (int i=0; i<charPositionInLine; i++) System.err.print(" ");
                int start = offendingToken.getStartIndex();
                int stop = offendingToken.getStopIndex();
                if ( start>=0 && stop>=0 ) {
                    for (int i=start; i<=stop; i++) System.err.print("^");
                }
                System.err.println();
            }
        }
    
        public static void main(String[] args) throws IOException {
            ANTLRInputStream input = new ANTLRFileStream(args[0]);
            QuestionLexer lexer = new QuestionLexer(input);
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            QuestionParser parser = new QuestionParser(tokens);
            parser.removeErrorListeners(); // remove ConsoleErrorListener
            parser.addErrorListener(new UnderlineListener()); // add ours
            ParseTree tree = parser.question();
            System.out.println(" -parsing ended");
            ParseTreeWalker walker = new ParseTreeWalker();
            MyListener my_listener = new MyListener(parser);
            System.out.println(">>>> about to walk");
            walker.walk(my_listener, tree);
        }
    }
    

    文件t.text

    test { return 2+2 }
    test { if 2 == 2 then return 2 else return 3 }
    test { if 2 == 2 then print 2 else print 3 return 4 }
    test {return 2; print 3}
    test { if 2 == 2 then return 2; abc else return 3; def }
    test { if 2 == 2 then if 6 then print 6 else print 3 else if 5 then
    print 1; print 2 else print 3 return 4 }
    

    执行:

    $ java test t.text 
    Question last update 1302
    line 4:14 mismatched input ';' expecting {'}', '==', '-', '+'}
    test {return 2; print 3}
                  ^
    line 5:30 mismatched input ';' expecting {'else', '==', '-', '+'}
    test { if 2 == 2 then return 2; abc else return 3; def }
                                  ^
    line 5:49 mismatched input ';' expecting {'}', '==', '-', '+'}
    test { if 2 == 2 then return 2; abc else return 3; def }
                                                     ^
     -parsing ended
    >>>> about to walk
    >>> in MyListener for function
    test { return 2+2 }
    >>> in MyListener for function
    test { if 2 == 2 then return 2 else return 3 }
    >>> in MyListener for function
    test { if 2 == 2 then print 2 else print 3 return 4 }
    >>> in MyListener for function
    test {return 2; print 3}
    >>> in MyListener for function
    test { if 2 == 2 then return 2; abc else return 3; def }
    >>> in MyListener for function
    test { if 2 == 2 then if 6 then print 6 else print 3 else if 5 then print 1; print 2 else print 3 return 4 }