Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将解析树转换为XML_Java_Xml_Parsing_Tree_Antlr4 - Fatal编程技术网

Java 将解析树转换为XML

Java 将解析树转换为XML,java,xml,parsing,tree,antlr4,Java,Xml,Parsing,Tree,Antlr4,我有一个编译过的语法,我想用它将输入序列转换成XML。请注意,在我的例子中,我有一个包含许多规则的非常大的语法,我希望避免重写代码中的每个语法规则 我将用一个例子来避免混淆。让我们来看看下面的语法 grammar expr; prog: stat+ ; stat: expr NEWLINE | ID '=' expr NEWLINE | NEWLINE ; expr: expr ('*'|'/') expr | INT | ID | '(' expr ')' ; ID : [

我有一个编译过的语法,我想用它将输入序列转换成XML。请注意,在我的例子中,我有一个包含许多规则的非常大的语法,我希望避免重写代码中的每个语法规则

我将用一个例子来避免混淆。让我们来看看下面的语法

grammar expr;

prog: stat+ ;

stat: expr NEWLINE
 | ID '=' expr NEWLINE
 | NEWLINE
;

expr:  expr ('*'|'/') expr
 | INT
 | ID
 | '(' expr ')'
;

ID : [a-zA-Z]+ ; // match identifiers
INT : [0-9]+ ; // match integers
NEWLINE:'\r'? '\n' ; // return newlines to parser (is end-statement signal)
WS : [ \t]+ -> skip ; // toss out whitespace
grammar str;

expr:
 STRING expr                                # exprString
 | LR_BRACKET expr RR_BRACKET expr          # exprParenthesis
 | LR_STRING_BRACKET expr RR_BRACKET expr   # exprRule 
 | <EOF>                                    # exprEnd
 | EOF_MARK                                 # exprEOF
 |                                          # exprEpsilon
;

EOF_MARK:            '<EOF>' ;
LR_STRING_BRACKET:  '(' ~[ ()]+;
LR_BRACKET:         '(';
RR_BRACKET:         ')';
STRING:             ~[ ()]+;
SPACE:              [ \t\r\n]+    -> skip; // toss out whitespace
输入顺序

A = 10
B = A * A
预期产出

<prog> 
    <stat> 
        A = 
        <expr> 10
        </expr> 
        \r\n
    </stat>  
    <stat> 
        B = 
        <expr>
            <expr>A</expr> 
            * 
            <expr> A</expr>
        </expr> 
        \r\n
    </stat>
</prog>
我随后将其转换为上面所示的XML(我使用简单的通用代码处理任何语法)。我觉得这种方法很愚蠢。没有
到字符串树
,是否可以解决此问题?我希望避免重写访问者中的每个语法规则。(我有几百个)

编辑


我基本上需要将某种通用的ParseTree序列化为XML格式。主要目标是,我不必为每个规则用Java编写特殊的序列化方法。

您可以利用ANTLR4的访问者功能。根据您使用的工具,您可能需要在生成类的过程中添加

为了更好地工作,我添加了一些:

prog
:stat+EOF
;
斯达
:expr NEWLINE#exprStat
|ID“=”expr换行符#assignStat
|换行符#清空状态
;
expr
:lhs=expr op=(“*”|“/”)rhs=expr#multExpr
|INT#intExpr
|ID#idExpr
|“('expr')”#nestedExpr
;
您的访问者可能是这样的:

公共类XmlVisitor扩展了exprBaseVisitor{
@凌驾
公共字符串visitProg(exprParser.ProgContext ctx){
StringBuilder=新的StringBuilder(“”);
对于(exprParser.StatContext stat:ctx.stat()){
builder.append(super.visit(stat));
}
返回builder.append(“”.toString();
}
@凌驾
公共字符串visitexpstat(exprParser.ExprStatContext ctx){
返回“expr”;
}
@凌驾
公共字符串visitAssignStat(exprParser.AssignStatContext ctx){
返回“+ctx.ID()+”=“+super.visit(ctx.expr())+”\\r\\n”;
}
@凌驾
公共字符串visitertystat(exprParser.EmptyStatContext ctx){
返回“\\r\\n”;
}
@凌驾
公共字符串visitMultExpr(exprParser.MultExprContext ctx){
return“+super.visit(ctx.lhs)+ctx.op.getText()+super.visit(ctx.rhs)+”;
}
@凌驾
公共字符串visitIntExpr(exprParser.IntExprContext ctx){
返回“+ctx.INT().getText()+”;
}
@凌驾
公共字符串visitIdExpr(exprParser.IdExprContext ctx){
返回“+ctx.ID().getText()+”;
}
@凌驾
公共字符串visitnestedxpr(exprParser.NestedExprContext ctx){
返回“+super.visit(ctx.expr())+”;
}
}
要测试此访问者,请运行以下代码:

String source=“A=10\nB=A*A\n”;
exprLexer lexer=新的exprLexer(CharStreams.fromString(source));
exprParser parser=newexprparser(newcommontokenstream(lexer));
ParseTree=parser.prog();
字符串xml=newXMLVisitor().visit(树);
System.out.println(xml);
将打印:

A=10\r\nB=A*A\r\n

我创建了一个ANTLR语法,它读取由
ParseTree.toString树
方法生成的LISP样式树。项目是可访问的。它有以下几个部分

语法

grammar expr;

prog: stat+ ;

stat: expr NEWLINE
 | ID '=' expr NEWLINE
 | NEWLINE
;

expr:  expr ('*'|'/') expr
 | INT
 | ID
 | '(' expr ')'
;

ID : [a-zA-Z]+ ; // match identifiers
INT : [0-9]+ ; // match integers
NEWLINE:'\r'? '\n' ; // return newlines to parser (is end-statement signal)
WS : [ \t]+ -> skip ; // toss out whitespace
grammar str;

expr:
 STRING expr                                # exprString
 | LR_BRACKET expr RR_BRACKET expr          # exprParenthesis
 | LR_STRING_BRACKET expr RR_BRACKET expr   # exprRule 
 | <EOF>                                    # exprEnd
 | EOF_MARK                                 # exprEOF
 |                                          # exprEpsilon
;

EOF_MARK:            '<EOF>' ;
LR_STRING_BRACKET:  '(' ~[ ()]+;
LR_BRACKET:         '(';
RR_BRACKET:         ')';
STRING:             ~[ ()]+;
SPACE:              [ \t\r\n]+    -> skip; // toss out whitespace
语法str;
表达式:
字符串表达式#表达式字符串
|左括号表达式右括号表达式右括号表达式
|LR_字符串_括号表达式RR_括号表达式#表达式
|#exprEnd
|EOF#U标记#清除
|#exprEpsilon
;
EOF_标记:“”;
LR_字符串_括号:'('~[()]+;
左括号:'(';
右括号:‘)’;
字符串:~[()]+;
空格:[\t\r\n]+->skip;//去掉空格
strxmltvisitor.java

public class strXMLVisitor extends strBaseVisitor<String> {

  @Override
  public String visitExprString(strParser.ExprStringContext ctx) 
  {
    return ctx.STRING().getText() + super.visit(ctx.expr());
  }

  @Override
  public String visitExprParenthesis(strParser.ExprParenthesisContext ctx) {
    return "(" + super.visit(ctx.expr(0)) + ")" + super.visit(ctx.expr(1));
  }

  @Override
  public String visitExprRule(strParser.ExprRuleContext ctx) {
    String value = ctx.LR_STRING_BRACKET().getText().substring(1);
    return "<" + value + ">" + super.visit(ctx.expr(0)) + "</" + value + ">" + super.visit(ctx.expr(1));
  }

  @Override
  public String visitExprEnd(strParser.ExprEndContext ctx) {
    return "";
  }

  @Override
  public String visitExprEOF(strParser.ExprEOFContext ctx) {
    return "";
  }

  @Override
  public String visitExprEpsilon(strParser.ExprEpsilonContext ctx) {
    return "";
  }  
}
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

public class main {
    public static void main(String[] args) throws Exception {
       // create a CharStream that reads from standard input
       ANTLRInputStream input = new ANTLRInputStream(System.in);
       // create a lexer that feeds off of input CharStream
       strLexer lexer = new strLexer(input);
       // create a buffer of tokens pulled from the lexer
       CommonTokenStream tokens = new CommonTokenStream(lexer);
       // create a parser that feeds off the tokens buffer
       strParser parser = new strParser(tokens);
       ParseTree tree = parser.expr(); // begin parsing at init rule

       String xml = "<?xml version=\"1.0\"?>" + new strXMLVisitor().visit(tree);
       System.out.println(xml);      
    }
}
公共类strXMLVisitor扩展strBaseVisitor{
@凌驾
公共字符串visitexpstring(strParser.ExprStringContext ctx)
{
返回ctx.STRING().getText()+super.visit(ctx.expr());
}
@凌驾
公共字符串visitexpr括号(strParser.ExprParenthesisContext ctx){
返回“(“+super.visit(ctx.expr(0))+”)”+super.visit(ctx.expr(1));
}
@凌驾
公共字符串visitexprule(strParser.ExprRuleContext ctx){
字符串值=ctx.LR_字符串_括号().getText().substring(1);
返回“+super.visit(ctx.expr(0))+”+super.visit(ctx.expr(1));
}
@凌驾
公共字符串visitExprEnd(strParser.ExprEndContext ctx){
返回“”;
}
@凌驾
公共字符串visitexprof(strParser.ExprEOFContext ctx){
返回“”;
}
@凌驾
公共字符串visitexpresilon(strParser.ExprEpsilonContext ctx){
返回“”;
}  
}
main.java

public class strXMLVisitor extends strBaseVisitor<String> {

  @Override
  public String visitExprString(strParser.ExprStringContext ctx) 
  {
    return ctx.STRING().getText() + super.visit(ctx.expr());
  }

  @Override
  public String visitExprParenthesis(strParser.ExprParenthesisContext ctx) {
    return "(" + super.visit(ctx.expr(0)) + ")" + super.visit(ctx.expr(1));
  }

  @Override
  public String visitExprRule(strParser.ExprRuleContext ctx) {
    String value = ctx.LR_STRING_BRACKET().getText().substring(1);
    return "<" + value + ">" + super.visit(ctx.expr(0)) + "</" + value + ">" + super.visit(ctx.expr(1));
  }

  @Override
  public String visitExprEnd(strParser.ExprEndContext ctx) {
    return "";
  }

  @Override
  public String visitExprEOF(strParser.ExprEOFContext ctx) {
    return "";
  }

  @Override
  public String visitExprEpsilon(strParser.ExprEpsilonContext ctx) {
    return "";
  }  
}
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

public class main {
    public static void main(String[] args) throws Exception {
       // create a CharStream that reads from standard input
       ANTLRInputStream input = new ANTLRInputStream(System.in);
       // create a lexer that feeds off of input CharStream
       strLexer lexer = new strLexer(input);
       // create a buffer of tokens pulled from the lexer
       CommonTokenStream tokens = new CommonTokenStream(lexer);
       // create a parser that feeds off the tokens buffer
       strParser parser = new strParser(tokens);
       ParseTree tree = parser.expr(); // begin parsing at init rule

       String xml = "<?xml version=\"1.0\"?>" + new strXMLVisitor().visit(tree);
       System.out.println(xml);      
    }
}
import org.antlr.v4.runtime.*;
导入org.antlr.v4.runtime.tree.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
//创建从标准输入读取的字符流
AntlInputStream输入=新的AntlInputStream(System.in);
//创建一个lexer,该lexer从输入字符流中获取信息
strLexer lexer=新strLexer(输入);
//创建从lexer提取的令牌缓冲区
CommonTokenStream令牌=新的CommonTokenStream(lexer);
//创建一个以令牌缓冲区为源的解析器
strParser parser=新的strParser(令牌);
ParseTree=parser.expr();//从init规则开始解析
字符串xml=”“+新strXMLVisitor().visit(树);
System.out.println(xml);
}
}
一旦准备好antlr4(以及类路径中的引用),就可以使用以下命令来运行它:

 antlr4 -visitor str.g4
 javac *.java
 java main < file
antlr4-visitor str.g4
javac*.java
java主文件
文件必须包含LISP树格式的输入,结果是标准输出上的XML