我正在尝试为我的语法创建访问者,遵循不同的帮助和建议。然而,即使我似乎做了每个人都告诉我的事情,我的访客似乎也不会被访问?这是我的ANTLR语法:
grammar Minecraft;
/* LEXER RULES */
SINGLE_COMMENT : '//' ~('\r' | '\n')* -> skip ;
MULTILINE_COMMENT : '/*' .*? '*/' -> skip ;
WS : [ \t\n\r]+ -> skip ;
fragment LETTER : ('a' .. 'z') | ('A' .. 'Z') ;
IDENTIFIER : LETTER+ ;
fragment NUMBER : ('0' .. '9') ;
BOOL : 'true' | 'false' ;
NUM : NUMBER+ | NUMBER+ '.' NUMBER+ ;
STR : '"' (LETTER | NUMBER)* '"' | '\'' (LETTER | NUMBER)* '\'' ;
COORDS : NUM ',' NUM ',' NUM ;
ITEM_ID : NUMBER+ | NUMBER+ ':' NUMBER+ ;
MULDIVMODOP : '*' | '/' | '%' ;
ADDSUBOP : '+' | '-' ;
NEGOP : '!' ;
EQOP : '==' | '!=' | '<' | '<=' | '>' | '>=' ;
LOGOP : '&&' | '||' ;
/* PROGRAM GRAMMAR */
prog : 'begin' 'bot' body 'end' 'bot' ;
body : glob_var* initiate main function* ;
initiate : 'initiate' stmt* 'end' 'initiate' ;
main : 'loop' stmt* 'end' 'loop' ;
type : 'num' | 'bool' | 'string' | 'block' | 'item' | 'coords' ;
function
: 'function' IDENTIFIER '(' args ')' stmt* 'end' 'function' #function_func
| 'activity' IDENTIFIER '(' args ')' stmt* 'end' 'activity' #activity_func
;
arg
: (type | type '[' ']') IDENTIFIER #type_arg
| dcl #dcl_arg
;
args : arg ',' args | arg ;
i_args : IDENTIFIER ',' i_args | /* epsilon */ ;
cond
: '(' cond ')' #paren_cond
| left=cond MULDIVMODOP right=cond #multdiv_cond
| left=cond ADDSUBOP right=cond #addsub_cond
| NEGOP cond #neg_cond
| left=cond EQOP right=cond #eq_cond
| left=cond LOGOP right=cond #log_cond
| tpe=(NUM | STR | BOOL | ITEM_ID | COORDS | IDENTIFIER) #var_cond
;
stnd_stmt
: dcl #dcl_stmt
| 'for' IDENTIFIER '=' init=NUM way=('to' | 'downto') target=NUM 'do' stmt* 'end' 'for' #for_stmt
| rpt=('while' | 'until') cond 'repeat' stmt* 'end' 'repeat' #repeat_stmt
| IDENTIFIER '(' i_args ')' #func_call_stmt
| IDENTIFIER '=' cond #assign_stmt
| 'return' (IDENTIFIER | cond) #return_stmt
| 'break' #break_stmt
;
stmt : stnd_stmt | if_stmt ;
else_stmt : stnd_stmt | ifelse_stmt ;
if_stmt
: 'if' cond 'then' stmt* 'end' 'if'
| 'if' cond 'then' stmt* 'else' else_stmt* 'end' 'if'
;
ifelse_stmt
: 'if' cond 'then' else_stmt*
| 'if' cond 'then' else_stmt* 'else' else_stmt*
;
glob_var : 'global' dcl ;
str_arr_items : val=(STR | IDENTIFIER) ',' str_arr_items | val=(STR | IDENTIFIER) ;
num_arr_items : val=(NUM | IDENTIFIER) ',' num_arr_items | val=(NUM | IDENTIFIER) ;
bool_arr_items : val=(BOOL | IDENTIFIER) ',' bool_arr_items | val=(BOOL | IDENTIFIER) ;
blck_arr_items : val=(ITEM_ID | IDENTIFIER) ',' blck_arr_items | val=(ITEM_ID | IDENTIFIER) ;
dcl
: 'num' id=IDENTIFIER '=' (val=(NUM | IDENTIFIER) | accessing | cond) #num_dcl
| 'bool' id=IDENTIFIER '=' (val=(BOOL | IDENTIFIER) | accessing | cond) #bool_dcl
| 'string' id=IDENTIFIER '=' (val=(STR | IDENTIFIER) | accessing) #str_dcl
| 'block' id=IDENTIFIER '=' (val=(ITEM_ID | IDENTIFIER) | accessing) #block_dcl
| 'item' id=IDENTIFIER '=' (val=(ITEM_ID | IDENTIFIER) | accessing) #item_dcl
| 'coords' id=IDENTIFIER '=' (val=(COORDS | IDENTIFIER) | accessing) #coords_dcl
| 'string' '[' ']' id=IDENTIFIER '=' ('{' str_arr_items '}' | vid=IDENTIFIER) #str_arr_dcl
| 'num' '[' ']' id=IDENTIFIER '=' ('{' num_arr_items '}' | vid=IDENTIFIER) #num_arr_dcl
| 'bool' '[' ']' id=IDENTIFIER '=' ('{' bool_arr_items '}' | vid=IDENTIFIER) #bool_arr_dcl
| tpe=('block' | 'item') '[' ']' id=IDENTIFIER '=' ('{' blck_arr_items '}' | vid=IDENTIFIER)#blck_item_arr_dcl
;
accessing
: IDENTIFIER '[' val=('X' | 'Y' | 'Z') ']' #coords_accessing
| IDENTIFIER '[' val=NUM+ ']' #arr_accessing
;
我的主要人物:
package Minecraft;
import org.antlr.runtime.RuleReturnScope;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.v4.runtime.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.*;
public class Minecraft {
public static void main(String[] args) throws IOException {
File f = new File("input");
FileInputStream fis = new FileInputStream(f);
ANTLRInputStream in = new ANTLRInputStream(fis);
MinecraftLexer lexer = new MinecraftLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
MinecraftParser parser = new MinecraftParser(tokens);
ParseTree tree = parser.prog();
ReadBaseVisitor visitor = new ReadBaseVisitor();
visitor.visit(tree);
}
}
和ReadBaseVisitor
类:
package Minecraft;
public class ReadBaseVisitor extends MinecraftBaseVisitor<Symbol> {
@Override
public Symbol visitProg(MinecraftParser.ProgContext ctx){
Symbol s = new Symbol();
System.out.println("kk");
return s;
}
}
现在,问题是,它从不打印&#34; kk&#34; line,所以它永远不会进入visitProg
方法,即使它来自prog
方法,我首先创建了解析树。有人可以帮我吗?
这是由ANTLR创建的MinecraftBaseVisitor:
package Minecraft;// Generated from E:/Dropbox/Dropbox/P4/ANTLRGrammar\Minecraft.g4 by ANTLR 4.5.1
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
/**
* This class provides an empty implementation of {@link MinecraftVisitor},
* which can be extended to create a visitor which only needs to handle a subset
* of the available methods.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public class MinecraftBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements MinecraftVisitor<T> {
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitProg(MinecraftParser.ProgContext ctx) {
return visitChildren(ctx); }
}
这是我的测试输入(这是正确的,它可以正确解析,当我使用测试装备时,我可以看到解析树就好了):
begin bot
global string Test = "hi"
global num TestA = 21
initiate
end initiate
loop
end loop
end bot