Java如何用正则拆分字符串,将运算符与标识符分开用于BNF解释器
我正在为巴科斯范式(Backus Naur Form)文法编写解释器,对应文法规则如下:
<statement> ::= <assignment> | "PRINT" "(" <expression> ")" <assignment> ::= <variable> = <expression> <expression> ::= <term> <expression*> <expression*> ::= "+" <expression> | "-" <expression> | "" <term> ::= <factor> <term*> <term*> ::= "*" <term> | "/" <term> | "" <factor> ::= <number> | <variable> | "(" <expression> ")" <variable> ::= <lowercase> <variable*> <variable*> ::= <variable> | "" <number> ::= <digit> <number*> <number*> ::= <number> | ""
现在需要编写代码判断输入字符串是否为合法表达式,最初的思路是使用split方法拆分字符串,分离所有独立的单词和符号,最初写法为:
String[] words = line.split("\\s+");
这种写法可以把String line = "y = x + 12 * z"这类带空格的字符串正确拆分为["y", "=", "x", "+", "12", "z"],但当输入无空格的表达式比如String line = "x=12+z"时,拆分结果为["x=12+z"],无法正常拆分。
需求是拆分时将+、-、*、/、=、(、)这些符号都单独作为数组的一项。比如输入String line = "x = z+12 * y -(z *var )"时,拆分结果为["x", "=", "z", "+", "12", "*", "y", "-", "(", "z", "*","var", ")"]。
解决方案
使用带环视规则的正则表达式即可实现需求,代码如下:
// 拆分规则:空格、符号前置位置、符号后置位置 String[] words = line.split("\\s+|(?=[+\\-*/=()])|(?<=[+\\-*/=()])"); // 过滤可能出现的空字符串(比如输入开头/结尾是符号的场景) words = Arrays.stream(words).filter(item -> !item.isEmpty()).toArray(String[]::new);
正则规则说明
\\s+:匹配1个或多个空格,作为拆分边界,拆分后自动丢弃空格(?=[+\\-*/=()]):正向零宽断言,匹配运算/分隔符号的前方位置,确保符号被单独拆分出来(?<=[+\\-*/=()]):反向零宽断言,匹配运算/分隔符号的后方位置,确保符号前后的内容和符号本身分离
上述代码测试你给出的示例输入,输出结果完全符合要求。
内容的提问来源于stack exchange,提问作者ParkerHarrelson123
相关产品推荐
相关产品推荐

