1

我正在尝试使用 java 表达式语句创建用于创建 HTML 模板的自定义域特定语言。

例如,它应该解析结合 java 语句的标签:

<div>
    if (someValue == true) {

        <span>"someValue was true"</span>

    }
</div>

现在我知道如何编写这样的解析器了。但是,如果我可以只对表达式使用标准 Java Parser,那将非常简单,这样我就不必重新实现 Java Parser 的一部分。我想要实现的可能看起来像:

IfStatementNode parseIfStatement() {

    scanner.expect("if");

    scanner.expect("(");

    JavaExpression expression = scanner.parseJavaExpression(); // <--- how to implement this?

    scanner.expect(")");

    return new IfStatementNode(expression);
}

如何做到这一点以便scanner.parseJavaExpression解析任何 Java 表达式?

4

2 回答 2

2

一种选择是添加一些生成代码以将表达式转换为 Function 对象的有效 java 代码。然后,您可以使用在运行时可用的常规 java 编译器解析生成的函数(包含返回值的表达式)。

这仍然需要您能够找到表达式的结尾。StreamTokenizer 可能就足够/方便了。

另一个问题是在/如果您添加对变量的支持时跟踪变量。

另一种方法可能是扩展模板中不是 Java 的部分(例如<span>变成output.append("<span>")),将您的模板变成有效的 Java 代码,可以将其作为一个整体进行编译。

于 2017-03-05T11:15:41.910 回答
1

你是对的:你可以重用 JavaParser,我建议你这样做,因为解析 Java 表达式一点也不简单。JavaParser 维护良好,它正在努力构建对 Java 9 的支持,如果您使用 JavaParser,您将免费获得。

在这种情况下使用 JavaParser 非常简单,以至于我几乎羞于编写这段代码:

Expression expression = JavaParser.parseExpression(code);

你完成了。

现在,如果代码中有错误,我们会抛出异常。如果您想获得一个很好的问题列表以向您的用户报告它们,您可以这样做:

  ParseResult<Expression> result = new JavaParser().parse(ParseStart.EXPRESSION, new StringProvider(code));
  for (Problem p : result.getProblems()) {
      System.err.println("Problem at " + p.getLocation().get() + 
              ": " + p.getMessage());
  }

如果您想随后处理代码以计算类型或解析对外部类的引用,您可能需要查看构建在 JavaParser 之上的 JavaSymbolSolver。

来源:我是 JavaParser 贡献者

于 2017-03-05T11:23:30.163 回答