我有这样的语法规则:
fctDecl
: id AS FUNCTION O_PAR (argDecl (COMMA argDecl)*)? C_PAR COLON (scalar|VOID)
(DECLARE LOCAL (varDecl SEMICOLON)+)?
DO (instruction)+ (RETURN id)? DONE;
当我在visitFctDecl
时,我必须访问FctDecl
的所有孩子。由于孩子可以是不同类型的规则,我怎么知道哪个是当前孩子的类型?
@Override
public FunctionNode visitFctDecl(B314Parser.FctDeclContext ctx) {
for (int i = 0; i < ctx.children.size() ;i++)
{
//what kind of rule is ?
ctx.children.get(i);
}
return null;
}
我根本不确定如何使用访客。
答案 0 :(得分:0)
首先要删除那个大的解析器规则。也许是这样的事情:
fctDecl
: id AS FUNCTION fctParams COLON ( scalar | VOID ) localDecl doStat
;
fctParams
: O_PAR ( argDecl ( COMMA argDecl )* )? C_PAR
;
localDecl
: ( DECLARE LOCAL ( varDecl SEMICOLON )+ )?
;
doStat
: DO instruction+ ( RETURN id )? DONE
;
然后在您的访问者中,您只需返回这样的自定义类(我返回地图和列表,但这可能是您自己的域对象):
public class DemoVisitor extends B314BaseVisitor<Object> {
// fctDecl
// : id AS FUNCTION fctParams COLON ( scalar | VOID ) localDecl doStat
// ;
@Override
public Object visitFctDecl(B314Parser.FctDeclContext ctx) {
Map<String, Object> result = new LinkedHashMap<String, Object>();
result.put("id", ctx.id().getText());
result.put("fctParams", visit(ctx.fctParams()));
result.put("type", ctx.scalar() != null ? ctx.scalar().getText() : ctx.VOID().getText());
result.put("localDecl", visit(ctx.localDecl()));
result.put("doStat", visit(ctx.doStat()));
return result;
}
// fctParams
// : O_PAR ( argDecl ( COMMA argDecl )* )? C_PAR
// ;
//
// argDecl
// : varDecl
// ;
//
// varDecl
// : ID AS type
// ;
@Override
public Object visitFctParams(B314Parser.FctParamsContext ctx) {
List<Map<String, String>> declarations = new ArrayList<Map<String, String>>();
if (ctx.argDecl() != null) {
for (B314Parser.ArgDeclContext argDecl : ctx.argDecl()) {
Map<String, String> declaration = new LinkedHashMap<String, String>();
declaration.put(argDecl.varDecl().ID().getText(), argDecl.varDecl().type().getText());
declarations.add(declaration);
}
}
return declarations;
}
// localDecl
// : ( DECLARE LOCAL ( varDecl SEMICOLON )+ )?
// ;
@Override
public Object visitLocalDecl(B314Parser.LocalDeclContext ctx) {
// See `visitFctParams(...)` how to traverse `( varDecl SEMICOLON )+`
return "TODO";
}
// doStat
// : DO instruction+ ( RETURN id )? DONE
// ;
@Override
public Object visitDoStat(B314Parser.DoStatContext ctx) {
// See `visitFctParams(...)` how to traverse `instruction+`
return "TODO";
}
}
如果您现在运行以下使用上述访问者的类:
public class Main {
public static void main(String[] args) {
String source =
"mu as function(i as integer, b as boolean): integer\n" +
"declare local x as square; y as square;\n" +
"do\n" +
" skip\n" +
"done";
B314Lexer lexer = new B314Lexer(CharStreams.fromString(source));
B314Parser parser = new B314Parser(new CommonTokenStream(lexer));
ParseTree fctDeclTree = parser.fctDecl();
Object result = new DemoVisitor().visit(fctDeclTree);
System.out.printf("source:\n\n%s\n\nresult:\n\n%s\n", source, result);
}
}
以下内容将打印在您的控制台上:
source:
mu as function(i as integer, b as boolean): integer
declare local x as square; y as square;
do
skip
done
result:
{id=mu, fctParams=[{i=integer}, {b=boolean}], type=integer, localDecl=TODO, doStat=TODO}