简体   繁体   English

正则表达式无法匹配开关案例模式

[英]Regex can't match switch case pattern

W e need to parse a rule which may be include a switch case instruction. 我们需要解析一个可能包含切换案例指令的规则。

As we considered to use Groovy to implement this parser within Java code, I wrote the code below in Groovy: 当我们考虑使用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. }

In first I just Wanna test the input rule to know if it is correct based on our structure, for example I considered the rule sample below to trace the code if it works properly: 首先,我只是想根据我们的结构测试输入规则,以了解它是否正确,例如,我认为下面的规则示例可以跟踪代码是否正常运行:

switch(@prm43) 
case 12: @msg13
case 14: @msg32
default: @msg100

and it works until line 26, when it reach line 26 the rule is: 它一直工作到第26行,到达26行时,规则是:

switch(1) 
case
case
default

Despite of the fact that it completely follow the pattern of switchRegex , but it doesn't have any change after line 28, why? 尽管它完全遵循switchRegex的模式,但是在第28行之后却没有任何变化,为什么?

I'm sorry for not coming up with a straight answer for your question, but it seems a little unclear to me what you are trying to achieve. 很抱歉没有为您的问题提供一个直接的答案,但是对我来说,您要达到的目标似乎有点不清楚。 You eval the rule after you do some replacements, but your switch is not legal groovy (or java for that matter). 在进行一些替换后,您可以评估该规则,但是您的选择不是合法的习惯(或Java)。 switch needs to be followed by curly braces. 开关后需要大括号。 Moreover, I would try to take advantage of groovy's DSL features instead of making a parser. 此外,我将尝试利用Groovy的DSL功能,而不是使用解析器。 If a parser is really what you need (missing information on motivation and context), then I would suggest using a combinator parser like jparsec: 如果解析器确实是您所需要的(缺少关于动机和上下文的信息),那么我建议使用像jparsec这样的组合器解析器:

https://github.com/jparsec/jparsec https://github.com/jparsec/jparsec

It is extremely easy to describe grammars with jparsec, and it is very maintainable. 用jparsec描述语法非常容易,并且非常易于维护。 In any case, using regexes for this seems like a problem looking like a nail because we have only a hammer. 无论如何,使用正则表达式看起来像是一个钉子一样的问题,因为我们只有锤子。

As I research more about my problem, I test some other parser to evaluate the best way to parse my grammar. 当我对问题进行更多研究时,我测试了其他解析器,以评估解析语法的最佳方法。 In first, as loteq recommended I went after examine jparsec in my project. 首先,按照loteq的建议,我在项目中检查了jparsec。 But unfortunately I couldn't find enough information and a good reference to use that parser. 但不幸的是,我找不到足够的信息和使用该解析器的良好参考。 So, I look for another parser to do my job on my specific grammar and I found antlr4. 因此,我寻找另一个解析器来完成我的特定语法工作,结果发现了antlr4。 Then, I develop my grammar and save it in RuleExpr.g4 file to generate the lexer and parser file by antlr. 然后,我开发语法并将其保存在RuleExpr.g4文件中,以通过antlr生成词法分析器和解析器文件。 the grammar is shown below: 语法如下所示:

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 
    ;

After that I parse my sample code using the lexer and parser which generated by antlr 之后,我使用由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");
      }
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM