有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java正则表达式无法匹配开关大小写模式

W e需要解析一条规则,该规则可能包含一条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行之后没有任何变化,为什么


共 (2) 个答案

  1. # 1 楼答案

    很抱歉,我没有对你的问题给出一个直截了当的答案,但我似乎有点不清楚你想要实现什么。在进行一些替换之后,您会评估规则,但您的切换不是合法的groovy(或者java)。切换后需要用花括号。此外,我会尝试利用groovy的DSL特性,而不是制作解析器。如果解析器是您真正需要的(缺少动机和上下文方面的信息),那么我建议使用组合式解析器,比如jparsec:

    https://github.com/jparsec/jparsec

    用jparsec描述语法非常容易,而且非常易于维护。在任何情况下,使用正则表达式似乎是一个问题,因为我们只有一把锤子

  2. # 2 楼答案

    随着我对自己的问题进行更多研究,我测试了其他一些解析器,以评估解析语法的最佳方式。 首先,按照loteq的建议,我在项目中检查了jparsec。但不幸的是,我找不到足够的信息和一个好的参考来使用这个解析器。 所以,我在寻找另一个解析器来处理我的特定语法,我找到了antlr4。然后,我开发语法并将其保存在RuleExpr中。g4文件,由antlr生成lexer和parser文件。语法如下所示:

    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生成的lexer和parser解析我的示例代码

    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");
          }
       }