我在设计脚本语言时遇到了问题。
我们有表达式:
1 + 2
x
a := b + c
... etc
函数调用可以包含表达式:
myfunc(1 + 2 + 3, b)
表达式可以包含函数调用:
a := myfunc(1, 2) * x
并且函数调用可以包含函数调用(作为参数):
myfunc(f(x), g(x))
它们可以全部组合在一起:
a := calc(f(x) + g(x), 1) + y
我的问题是如何使用java.util.regex.Pattern
表示这些关系。如果我首先声明Pattern EXPRESSION
,那么它会在尚未声明时使用Pattern FUNC_CALL
。首先声明 FUNC_CALL 时也会发生同样的情况,因为它也使用 EXPRESSION。
代码片段:
/**
* Expression is any positive number of either (number, spaces, operator, function call, or identifier).
*/
public static final Pattern EXPRESSION = Pattern.compile("(\\s*(\\s+|" + NUMBER.pattern()
+ "|" + OPERATOR.pattern() + "|" + FUNC_CALL.pattern() + "|" // Error : FUNC_CALL is not initialized
+ IDENTIFIER.pattern() + ")+)");
/**
* Function call is an identifier, followed by "(",
* followed by arguments which are any non-negative number of
* either (identifier, comma, or spaces), followed by ")"
*/
public static final Pattern FUNC_CALL = Pattern.compile(IDENTIFIER.pattern()
+ "\\s*\\(" + "(" + EXPRESSION.pattern() + "|\\s+|\\,)*\\)");
最佳答案
您对正则表达式的要求太多了。你想要的东西是不可能的。通常,在解析表达式时,正则表达式的使用量要小得多,例如识别合法的函数名称、运算符和值。为了解析完整的表达式,您可能需要尝试 recursive descent parser因为这是最简单的技术。
如果您必须包含中缀运算符,那么这将大大增加解析器的复杂性。您将想了解operator-precedence parsers 。一旦了解了解析器的工作原理,编写一个漂亮的解析器并不难。您甚至可以用几行代码编写一个运算符优先级解析器,但弄清楚算法可能很棘手。如果您打算自己动手,最好的方法是在网络上查找可以帮助您的资源,例如:Parsing expressions by precedence climbing ,和Parsing Expressions by Recursive Descent 。我无法比这些教程做得更好。
您自己做的自然替代方案是使用解析器生成器来为您完成所有操作。以下是许多选项的列表:Comparison of parser generators .
关于java - 正则表达式循环依赖性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20028063/