gpt4 book ai didi

java - 使用 ANTLR 树语法复制树的节点

转载 作者:行者123 更新时间:2023-12-01 14:36:41 27 4
gpt4 key购买 nike

我需要一些指导来尝试解决我使用树语法遇到的问题。基本上,我希望能够做的是替换/复制树中可能找到的语句。最好通过一个例子来解释。

这是一个示例输入:

int a = 10;
new function A;

function A {
int x;
int y;
new function B;
}

function B {
float b = 20;
}

想要的输出(稍后):

int a = 10;
int x;
int y;
float b = 20;

这是对功能 block 内的语句的简单搜索和替换。我的问题是 ANTLR 是否提供了一种通过树语法来做到这一点的方法?

这是一个应该解析上述输入的语法:

测试.g

grammar Test;
options {
language = Java;
output = AST;
}
tokens {
VARDECL;
FUNDEF;
FUNCALL;
BLOCK;
ASSIGN;

Assign = '=';
EqT = '==';
NEq = '!=';
LT = '<';
LTEq = '<=';
GT = '>';
GTEq = '>=';
NOT = '!';
PLUS = '+';
MINUS = '-';
MULT = '*';
DIV = '/';
}

parse: statements+
;

statements : varDeclare
| funcDefinition
| funcCall
;

funcDefinition : 'function' id '{' funcBlock* '}' -> ^(FUNDEF id ^(BLOCK funcBlock*))
;

funcBlock : varDeclare
| funcCall
;

funcCall : 'new' 'function' id ';' -> ^(FUNCALL id)
;

varDeclare : type id equalExp? ';' -> ^(VARDECL type id equalExp?)
;

equalExp : (Assign^ (expression | '...' ))
;

expression : binaryExpression
;

binaryExpression : addingExpression ((EqT|NEq|LTEq|GTEq|LT|GT)^ addingExpression)*
;

addingExpression : multiplyingExpression ((PLUS|MINUS)^ multiplyingExpression)*
;

multiplyingExpression : unaryExpression
((MULT|DIV)^ unaryExpression)*
;

unaryExpression: ((NOT|MINUS))^ primitiveElement
| primitiveElement
;

primitiveElement : literalExpression
| id
| '(' expression ')' -> expression
;

literalExpression : INT
;

id : IDENTIFIER
;

type : 'int'
| 'float'
;

// L E X I C A L R U L E S

INT : DIGITS ;

IDENTIFIER : LETTER (LETTER | DIGIT)*;

WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;

fragment LETTER : ('a'..'z' | 'A'..'Z' | '_') ;
fragment DIGITS: DIGIT+;
fragment DIGIT : '0'..'9';

测试.java

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RuleReturnScope;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.DOTTreeGenerator;
import org.antlr.stringtemplate.StringTemplate;

public class Test {
public static void main(String[] args) throws Exception {
String src = "int a = 10;\r\n" +
"new function A;\r\n" +
"\r\n" +
"function A {\r\n" +
" int x;\r\n" +
" int y;\r\n" +
" new function B;\r\n" +
"}\r\n" +
"\r\n" +
"function B{\r\n" +
" float b = 20;\r\n" +
"}";
TestLexer lexer = new TestLexer(new ANTLRStringStream(src));
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
TestParser parser = new TestParser(tokenStream);
RuleReturnScope r = parser.parse();
System.out.println("Tree:" + ((CommonTree) r.getTree()).toStringTree() + "\n");


CommonTree t = (CommonTree)r.getTree();
generateGraph(t, "Tree.dot");
}

private static void generateGraph(CommonTree t, String file) throws IOException {
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(t);
String output = file;
PrintWriter out = new PrintWriter(new FileWriter(output));
out.println(st);
out.close();
}
}

树.点 AST graph

如何使用树语法搜索每个 FUNCALL 并替换为内部 BLOCK 的内容?

提前致谢!

最佳答案

在语法中,您将创建一个 FUNDEF BLOCK 的表 blockMap,并以 ID 作为键。

然后在你的树语法中是这样的,尽管它可能需要一些调整。您将为 funcCall 制定规则:

funcCall : ^(FUNCALL id) -> {input.getTreeAdaptor().dupTree(blockMap.get(id)}
;

这就是从 map 上复制 BLOCK 的方法: input.getTreeAdaptor().dupTree(...)

您需要制作一份副本,因为节点会跟踪其父级,因此您只能在树中的一个位置使用它们。

关于java - 使用 ANTLR 树语法复制树的节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16433273/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com