2017-10-28 6 views
0

구문 분석 중에 함수에 모든 경로가 반환되는지 확인하는 방법을 궁금합니다. 그래서 내 질문은 유효한 함수가 후 return 문 아무것도를해야한다는 것입니다Antlr 범위 내에서 return 문을 확인하십시오.

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

파서에서 다음을했다고 밝혔습니다. 그래서 유효한 하나

test { return 2+2 } 

또는

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

반환 후 도달 할 수없는 코드가 어디에 잘못된 일이 될 것입니다. 예를 들어.

test{return 2; print 3} 

return 문 다음에 아무것도 없는지 확인하려면 어떻게해야합니까? 제가 전문가가 아니에요 오늘까지 오류보고를 사용하지 않을했지만, 그냥 오류 목록을 원하는 경우, 다음을 수행 할 수

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

문법을 통해이를 강제 할 방법은 없습니다. 의미 론적 동작에서 확인할 수는 있지만 일반적으로 구문 분석기에서는이를 확인하지 않지만 의미 분석 단계에서는 확인합니다. – sepp2k

+0

고맙습니다. –

+0

@ sepp2k : 왜 문법을 적용 할 수 없습니까? 그것은 간단한 통사론적인 특징입니다. – rici

답변

0

:

내 주요 자바 방법은 다음과 같이 보입니다 , 제 9 장인 The Definitive ANTLR 4 Reference에서 영감을 얻었다.

파일 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 } 
+0

'if'문이 함수의 마지막 문이 아니더라도 모든 if 블록에 return 문이 끝에 있어야합니다. 또한 if 문에 return 문이 있고'if 문 뒤에 문이있는 경우에도 오류가 발생하지 않습니다. 이 문제를 문법에서 실제로 해결하려면 함수의 끝에 나타나는 if와 그렇지 않은 if에 대해 다른 규칙이 필요합니다. 또한 끝이 아닌 'if'가 사례 중 하나에서 수익을 얻을 수 있지만 두 가지 모두에서 수익을 올릴 수 있다는 점을 고려해야합니다 (적어도 그것이 합리적인 규칙이며 다른 언어로 작동하는 방식 임). – sepp2k

+0

@ sepp2k 오른쪽, 한 사례 만 업데이트했습니다. 그가이 솔루션에 관심이 있다면 OP가 모든 사례를 제공합니다.그러나 당신이 당신의 첫 번째 논평에서 제안한 바와 같이, 의미 해석 단계에서 그것을 더 나을 것입니다. – BernardK