w ^ 需要解析可能包含switch case指令的规则。
当我们考虑使用Groovy在Java代码中实现这个解析器时,我在Groovy中编写了下面的代码:
1. class RuleParser {
2. String functionRegex = /(frml[0-9]*)((\s*@[a-zA-Z0-9_]*\s*)?(,\s*@[a-zA-Z0-9_]*\s*)*)/
3. String variableRegex = /@[a-zA-Z0-9_]*/
4. String numberRegex = /\s+[0-9]+/
5. String switchRegex = /switch(\s*1\s*)((\s*|\n)case)+((\s*|\n)default)?/
6. String caseRegex = /case\s*1\s*:\s*1/
7. String defaultRegex = /default\s*:\s*1/
8. String conditionRegex = /1(>=|<=|>|<|==|!=)1/
9. testRule(String rule){
10. try {
11. rule.eachMatch(numberRegex){ match->
12. rule=rule.replaceAll(match, ' 1');
13. }
14. rule.eachMatch(functionRegex){ match->
15. rule=rule.replaceAll(match, '1');
16. }
17. rule.eachMatch(variableRegex){ match->
18. rule=rule.replaceAll(match, '1');
19. }
20. rule.eachMatch(defaultRegex){ match->
21. rule=rule.replaceAll(match, 'default');
22. }
23. rule.eachMatch(caseRegex){ match->
24. rule=rule.replaceAll(match, 'case');
25. }
26. rule.eachMatch(switchRegex){ match->
27. rule=rule.replaceAll(match, '1');
28. }
29. Eval.me(rule)
30. println "run successfully"
31. } catch (Exception e) {
32. e.printStackTrace()
33. }
34. }
35. }
首先,我想测试输入规则,根据我们的结构知道它是否正确,例如我考虑下面的规则示例来跟踪代码是否正常工作:
switch(@prm43)
case 12: @msg13
case 14: @msg32
default: @msg100
直到第26行,当它到达第26行时,规则为:
switch(1)
case
case
default
尽管它完全遵循 switchRegex 的模式,但它在第28行之后没有任何变化,为什么?
答案 0 :(得分:2)
我很抱歉没有为你的问题提出一个直截了当的答案,但我似乎有点不清楚你想要达到的目标。您在进行一些替换后评估规则,但是您的切换不合法groovy(或java)。开关需要跟随花括号。此外,我会尝试利用groovy的DSL功能而不是制作解析器。如果解析器确实是你需要的(缺少关于动机和上下文的信息),那么我建议使用像jparsec这样的组合解析器:
https://github.com/jparsec/jparsec
使用jparsec描述语法非常容易,并且它非常易于维护。在任何情况下,使用正则表达式似乎是一个看起来像钉子的问题,因为我们只有一把锤子。
答案 1 :(得分:0)
当我更多地研究我的问题时,我会测试一些其他解析器来评估解析语法的最佳方法。 首先,正如loteq推荐的那样,我在我的项目中检查了jparsec。但遗憾的是,我找不到足够的信息和使用该解析器的良好参考。 所以,我寻找另一个解析器来完成我的特定语法工作,我找到了antlr4。然后,我开发我的语法并将其保存在RuleExpr.g4文件中,以生成antlr的词法分析器和解析器文件。语法如下所示:
grammar RuleExp;
start
: statement+
;
statement
: assignment
| message
| ifElseExp
| switchExp
;
ifElseExp
: 'if' '(' relCnd ')' 'then' '{' start '}'
| 'if' '(' relCnd ')' 'then' '{' start '}' elseExp
;
elseExp
: 'else' ifElseExp
| 'else' '{' start '}'
;
switchExp
: 'switch' '(' relCnd ')' caseExp
;
caseExp
: 'case' terminal ':' '{' start '}' caseExp
| dfltExpr
;
dfltExpr
: 'default' ':' '{' start '}'
;
message
: '@msg'Digit+
;
assignment
: id '=' addStmt
;
relCnd
: relCnd '>' logCnd
| relCnd '<' logCnd
| relCnd '>=' logCnd
| relCnd '<=' logCnd
| relCnd '==' logCnd
| relCnd '!=' logCnd
| logCnd
;
logCnd
: logCnd 'AND' termCnd
| logCnd 'OR' termCnd
| logCnd 'XOR' termCnd
| 'NOT' termCnd
| termCnd
;
addStmt
: addStmt '+' mulStmt
| addStmt '-' mulStmt
| mulStmt
;
mulStmt
: mulStmt '*' terminal
| mulStmt '/' terminal
| mulStmt '^' terminal
| terminal
;
terminal
: '('addStmt')'
| id
| number
;
termCnd
: '('relCnd')'
| id
| number
;
id
: '@prmt'(Digit)+
| '@fild'(Digit)+
| '@infF'(Digit)+
| '@mthd'(Digit)+
| '@cmpnt'(Digit)+
| '@oprt'(Digit)+
| Letter(Letter|Digit)*
;
number
: Digit+ ('.' Digit+)?
;
Letter
: 'a'..'z'
| 'A'..'Z'
| '_'
;
Digit
: '0'..'9'
;
WS : [ \t\r\n]+ -> skip
;
之后,我使用由antlr
生成的词法分析器和解析器解析我的示例代码public void checkSyntax(String rule) {
// TODO Auto-generated method stub
try {
CharStream stream=new ANTLRInputStream(decodeRule(rule));
RuleExpLexer lexer=new RuleExpLexer(stream);
CommonTokenStream tokens=new CommonTokenStream(lexer);
RuleExpParser parser=new RuleExpParser(tokens);
parser.start();
} catch (Exception e) {
// TODO: handle exception
throw new ApplicationExceptions("uacRule is Wrong");
}
}