gpt4 book ai didi

java - 在antlr访问者模式中如何从一种方法导航到另一种方法

转载 作者:太空宇宙 更新时间:2023-11-04 09:18:16 27 4
gpt4 key购买 nike

我是 Antlr 的新手,我想知道如何从一个解析导航到输入每个方法,并且我希望使用 Antlr4 完成以下实现。我有下面写的功能。

下面是项目的github链接。 https://github.com/VIKRAMAS/AntlrNestedFunctionParser/tree/master

1. FUNCTION.add(Integer a,Integer b)
2. FUNCTION.concat(String a,String b)
3. FUNCTION.mul(Integer a,Integer b)

我正在像这样存储函数元数据。

Map<String,String> map=new HashMap<>();
map.put("FUNCTION.add","Integer:Integer,Integer");
map.put("FUNCTION.concat","String:String,String");
map.put("FUNCTION.mul","Integer:Integer,Integer");

其中,Integer:Integer,Integer表示Integer是返回类型,函数将接受的输入参数是Integer,Integer

如果输入是这样的

FUNCTION.concat(Function.substring(String,Integer,Integer),String)
or
FUNCTION.concat(Function.substring("test",1,1),String)

使用访问者实现,我想检查输入是否针对映射中存储的函数元数据有效。

下面是我正在使用的词法分析器和解析器:

Lexer MyFunctionsLexer.g4:

lexer grammar MyFunctionsLexer;

FUNCTION: 'FUNCTION';

NAME: [A-Za-z0-9]+;

DOT: '.';

COMMA: ',';

L_BRACKET: '(';

R_BRACKET: ')';

解析器MyFunctionsParser.g4:

parser grammar MyFunctionsParser;

options {
tokenVocab=MyFunctionsLexer;
}

function : FUNCTION '.' NAME '('(function | argument (',' argument)*)')';

argument: (NAME | function);

WS : [ \t\r\n]+ -> skip;

我正在使用 Antlr4。

下面是我根据建议的答案使用的实现。

访客实现: 公共(public)类 FunctionValidateVisitorImpl 扩展 MyFunctionsParserBaseVisitor {

    Map<String, String> map = new HashMap<String, String>();

public FunctionValidateVisitorImpl()
{
map.put("FUNCTION.add", "Integer:Integer,Integer");
map.put("FUNCTION.concat", "String:String,String");
map.put("FUNCTION.mul", "Integer:Integer,Integer");
map.put("FUNCTION.substring", "String:String,Integer,Integer");
}

@Override
public String visitFunctions(@NotNull MyFunctionsParser.FunctionsContext ctx) {
System.out.println("entered the visitFunctions::");
for (int i = 0; i < ctx.getChildCount(); ++i)
{
ParseTree c = ctx.getChild(i);
if (c.getText() == "<EOF>")
continue;
String top_level_result = visit(ctx.getChild(i));
System.out.println(top_level_result);
if (top_level_result == null)
{
System.out.println("Failed semantic analysis: "+ ctx.getChild(i).getText());
}
}
return null;
}

@Override
public String visitFunction( MyFunctionsParser.FunctionContext ctx) {
// Get function name and expected type information.
String name = ctx.getChild(2).getText();
String type=map.get("FUNCTION." + name);
if (type == null)
{
return null; // not declared in function table.
}
String result_type = type.split(":")[0];
String args_types = type.split(":")[1];
String[] expected_arg_type = args_types.split(",");
int j = 4;
ParseTree a = ctx.getChild(j);
if (a instanceof MyFunctionsParser.FunctionContext)
{
String v = visit(a);
if (v != result_type)
{
return null; // Handle type mismatch.
}
} else {
for (int i = j; i < ctx.getChildCount(); i += 2)
{
ParseTree parameter = ctx.getChild(i);
String v = visit(parameter);
if (v != expected_arg_type[(i - j)/2])
{
return null; // Handle type mismatch.
}
}
}
return result_type;
}


@Override
public String visitArgument(ArgumentContext ctx){
ParseTree c = ctx.getChild(0);
if (c instanceof TerminalNodeImpl)
{
// Unclear if what this is supposed to parse:
// Mutate "1" to "Integer"?
// Mutate "Integer" to "String"?
// Or what?
return c.getText();
}
else
return visit(c);
}


}

测试类:

public class FunctionValidate {


public static void main(String[] args) {
String input = "FUNCTION.concat(FUNCTION.substring(String,Integer,Integer),String)";
ANTLRInputStream str = new ANTLRInputStream(input);
MyFunctionsLexer lexer = new MyFunctionsLexer(str);
CommonTokenStream tokens = new CommonTokenStream(lexer);
MyFunctionsParser parser = new MyFunctionsParser(tokens);
parser.removeErrorListeners(); // remove ConsoleErrorListener
parser.addErrorListener(new VerboseListener()); // add ours
FunctionsContext tree = parser.functions();
FunctionValidateVisitorImpl visitor = new FunctionValidateVisitorImpl();
visitor.visit(tree);
}


}

词法分析器:

lexer grammar MyFunctionsLexer;
FUNCTION: 'FUNCTION';
NAME: [A-Za-z0-9]+;
DOT: '.';
COMMA: ',';
L_BRACKET: '(';
R_BRACKET: ')';
WS : [ \t\r\n]+ -> skip;

解析器:

parser grammar MyFunctionsParser;
options { tokenVocab=MyFunctionsLexer; }
functions : function* EOF;
function : FUNCTION '.' NAME '(' (function | argument (',' argument)*) ')';
argument: (NAME | function);

详细监听器:

public class VerboseListener  extends BaseErrorListener  {

@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
List<String> stack = ((Parser)recognizer).getRuleInvocationStack();
Collections.reverse(stack);
throw new FunctionInvalidException("line "+line+":"+charPositionInLine+" at "+ offendingSymbol+": "+msg);

}
}

输出:它没有进入访问者实现,因为它没有打印 System.out.println("entered the VisitFunctions::"); 语句。我无法使用访问方法遍历子节点。

最佳答案

生成的解析器和运行时之间存在版本偏差。此外,您生成的 .java 文件存在版本偏差,就好像您下载并运行了两个 Antlr 工具版本(4.4 和 4.7.2),其中一次没有 -visitor选项,然后再次使用它。 MyFunctionsParser.java 的源代码位于 AntlrNestedFunctionParser\FunctionValidator\target\generated-sources\antlr4\com\functionvalidate\validate 。在文件的顶部,它说

// Generated from MyFunctionsParser.g4 by ANTLR 4.4

MyFunctionsParserVisitor.java 的来源是

// Generated from com\functionvalidate\validate\MyFunctionsParser.g4 by ANTLR 4.7.2

运行时是 4.7.2,您在 pom.xml 中声明。在AntlrNestedFunctionParser\FunctionValidator 。有MyFunctionsLexer.tokens至少在两个位置定义,谁知道你选择哪一个。我不熟悉与 pom.xml 相关的 Antlr 构建规则,但是生成的内容一团糟(这就是为什么我为 C# 的 Antlr 编写了自己的构建规则和编辑器)。确保完全清理目标目录,生成干净的最新 .java 文件,并且使用正确的 Antlr 运行时 4.7.2。

关于java - 在antlr访问者模式中如何从一种方法导航到另一种方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58684563/

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