如何在ANTLR中获得完整的用户编写语句(包括空格)
我有一个来自Java语言定义的“语句”定义,如下所示如何在ANTLR中获得完整的用户编写语句(包括空格),antlr,Antlr,我有一个来自Java语言定义的“语句”定义,如下所示 statement : block | ASSERT expression (':' expression)? ';' | 'if' parExpression statement ('else' statement)? | 'for' '(' forControl ')' statement | 'while' parExpression statement | 'do' statement 'while' parExp
statement
: block
| ASSERT expression (':' expression)? ';'
| 'if' parExpression statement ('else' statement)?
| 'for' '(' forControl ')' statement
| 'while' parExpression statement
| 'do' statement 'while' parExpression ';'
| 'try' block
( catches 'finally' block
| catches
| 'finally' block
)
| 'switch' parExpression switchBlock
| 'synchronized' parExpression block
| 'return' expression? ';'
| 'throw' expression ';'
| 'break' Identifier? ';'
| 'continue' Identifier? ';'
| ';'
| statementExpression ';'
| Identifier ':' statement
;
在执行解析器时,我还希望打印完整的用户编写语句(包括语句中的空格),例如:
Object o = Ma.addToObj(r1);
if(h.isFull() && !h.contains(true)) h.update(o);
但是当我在“exitStatement”中使用函数“getText()”时,我只能得到删除了所有空格的语句,例如:
Object o = Ma.addToObj(r1);
if(h.isFull() && !h.contains(true)) h.update(o);
Objecto=Ma.addToObj(r1);
if(h.isFull()&&!h.contains(true))h.update(o);
如何以简单的方式获得完整的用户编写的语句(包括语句中的空格)?非常感谢
完整代码如下:
public class PrintStatements {
public static class GetStatements extends sdlParserBaseListener {
StringBuilder statements = new StringBuilder();
public void exitStatement(sdlParserParser.StatementContext ctx){
statements.append(ctx.getText());
statements.append("\n");
}
}
public static void main(String[] args) throws Exception{
String inputFile = null;
if ( args.length>0 ) inputFile = args[0];
InputStream is = System.in;
if ( inputFile!=null ) {
is = new FileInputStream(inputFile);
}
ANTLRInputStream input = new ANTLRInputStream(is);
sdlParserLexer lexer = new sdlParserLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
sdlParserParser parser = new sdlParserParser(tokens);
ParseTree tree = parser.s();
// create a standard ANTLR parse tree walker
ParseTreeWalker walker = new ParseTreeWalker();
// create listener then feed to walker
GetStatements loader = new GetStatements();
walker.walk(loader, tree); // walk parse tree
System.out.println(loader.statements.toString());
}
}
def exitSomeDecl(self, ctx: yourParser.SomeDeclContext):
start_index = ctx.start.tokenIndex
stop_index = ctx.stop.tokenIndex
user_text = self.token_stream.getText(interval=(start_index, stop_index))
我是ANTLR的新手,所以可能我有点不对劲 我不知道简单的方法,但你可以试试这样的方法。 在语法文件中,您可能有如下内容:
WS : (' '|'\r'|'\t'|'\u000C'|'\n')
{
if (!preserveWhitespacesAndComments) {
skip();
} else {
$channel = HIDDEN;
}
}
public void exitE(sdlParserParser.EContext ctx) {
TokenStream tokens = parser.getTokenStream();
String Stmt = null;
Stmt = tokens.getText(ctx.statement());
...
}
这个lexer规则告诉解析器忽略空白。更确切地说,这些令牌是在隐藏通道上发送的(解析器看不到它们)。如果您对这行代码进行注释
WS : (' '|'\r'|'\t'|'\u000C'|'\n')
{
if (!preserveWhitespacesAndComments) {
// skip();
} else {
// $channel = HIDDEN;
}
}
所有的空白都将被发送到解析器,但您需要重写解析器规则,这样他就可以在任何地方看到空白
Object(EXPECT WHITESPACE)o(EXPECT WHITESPACE)=(EXPECT WHITESPACE)Ma.addToObj(r1);
否则解析器将报告错误。您需要两件事之一:
- 能够获取语句解析所接受的第一个和最后一个标记的文件位置数据(词素或树节点都可以),然后转到源文件并提取文本。这将得到原始的空白
- 预打印程序,它将从AST中重新生成文本,并插入适当的空格。请参阅我关于如何构建预打印程序的答案
WS : (' '|'\r'|'\t'|'\u000C'|'\n')
{
if (!preserveWhitespacesAndComments) {
skip();
} else {
$channel = HIDDEN;
}
}
public void exitE(sdlParserParser.EContext ctx) {
TokenStream tokens = parser.getTokenStream();
String Stmt = null;
Stmt = tokens.getText(ctx.statement());
...
}
就Antlr4和Python3而言,其外观如下:
public class PrintStatements {
public static class GetStatements extends sdlParserBaseListener {
StringBuilder statements = new StringBuilder();
public void exitStatement(sdlParserParser.StatementContext ctx){
statements.append(ctx.getText());
statements.append("\n");
}
}
public static void main(String[] args) throws Exception{
String inputFile = null;
if ( args.length>0 ) inputFile = args[0];
InputStream is = System.in;
if ( inputFile!=null ) {
is = new FileInputStream(inputFile);
}
ANTLRInputStream input = new ANTLRInputStream(is);
sdlParserLexer lexer = new sdlParserLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
sdlParserParser parser = new sdlParserParser(tokens);
ParseTree tree = parser.s();
// create a standard ANTLR parse tree walker
ParseTreeWalker walker = new ParseTreeWalker();
// create listener then feed to walker
GetStatements loader = new GetStatements();
walker.walk(loader, tree); // walk parse tree
System.out.println(loader.statements.toString());
}
}
def exitSomeDecl(self, ctx: yourParser.SomeDeclContext):
start_index = ctx.start.tokenIndex
stop_index = ctx.stop.tokenIndex
user_text = self.token_stream.getText(interval=(start_index, stop_index))
这里,self.token\u流:CommonTokenStream
在初始化期间分配:
input_stream = FileStream(file_name)
lexer = sdplLexer(input_stream)
token_stream = CommonTokenStream(lexer)
可能重复的