Antlr 检查范围内的返回语句 [英] Antlr check return statements in scope
问题描述
我想知道如何在语法分析期间检查所有路径是否在函数中都有返回值.所以说我在词法分析器中有以下内容
I was wondering how to check that all paths have a return in a function during syntax analysis. So say I have the following in the 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 语句,并且后面没有任何内容.所以一个有效的是
My question is that a valid function should have a return statement and nothing after it. So a valid one is
test { return 2+2 }
或
test{ if 2 == 2 then return 2 else return 3 }
无效的将是返回后无法访问的代码.例如.
an invalid one would be where there is unreachable code after the return. For example.
test{return 2; print 3}
我将如何检查 return 语句之后没有任何内容?
How would I go about checking that there is nothing after return statements?
我的主要 java 方法如下所示:
my main java method looks something like this:
MyLexer mylexer = new MyLexer(new ANTLRInputStream(System.in));
CommonTokenStream toks = new CommonTokenStream(mylexer);
MyParser parser = new MyParser(tokens);
ParseTree parseTree = parser.program();
推荐答案
我不是专家,直到今天才使用错误报告,但是如果您只想要错误列表,您可以执行以下操作,灵感来自权威 ANTLR 4 参考的第 9 章.
I'm not an expert and had never use error reporting until today, but if you just want a list of errors, you could do the following, inspired by chapter 9 of 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 }
这篇关于Antlr 检查范围内的返回语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!