基于 JavaCC 生成权限校验语法表达式解析器

接上篇 《基于 PEG.js 生成权限校验语法表达式解析器》,前台校验完了,后端也不能省,后端开发依赖 JavaCC,即 Java Compiler Compiler。

JavaCC 简介

Java Compiler Compiler™ (JavaCC™) is the most popular parser generator for use with Java™ applications. A parser generator is a tool that reads a grammar specification and converts it to a Java program that can recognize matches to the grammar. In addition to the parser generator itself, JavaCC provides other standard capabilities related to parser generation such as tree building (via a tool called JJTree included with JavaCC), actions, debugging, etc.

JavaCC 是 Java 语言范围内最受欢迎的语法分析生成器,可以读取特定语法写好的范式并把它转换成可以识别且匹配该语法的 JAVA 程序,除了 javacc 也有配套的 JJTree 生成语法树,JJDoc 生成 BNF 范式文档等。

更多信息参见官网

直接上代码

options
{
  NODE_PACKAGE = "cn.lzxz1234.rbac";
  MULTI = true;
  NODE_USES_PARSER = true;
  STATIC = false;
  VISITOR = true;
}

PARSER_BEGIN(ActionExpression)

package cn.lzxz1234.rbac;
import java.io.StringReader;

public class ActionExpression
{
  public ActionExpression(String s)
  {
    this (new StringReader(s));
  }

  public static boolean evaluate(String src) throws ParseException
  {
    return new ActionExpression(src).expr();
  }

  public static boolean hasAction(String action)
  {
    return action.equals("User.Modify");
  }
}

PARSER_END(ActionExpression)

SKIP :
{
  " "
| "\t"
| "\n"
| "\r"
| < "//" (~[ "\n", "\r" ])*
    (
      "\n"
    | "\r"
    | "\r\n"
    ) >
| < "/*" (~[ "*" ])* "*"
    (
      ~[ "/" ] (~[ "*" ])* "*"
    )*
    "/" >
}

TOKEN : /* LITERALS */
{
  < LOGICAL_AND :
    "&&"
  | "and" >
| 
  < LOGICAL_OR :
    "||"
  | "or" >
}

TOKEN : /* IDENTIFIERS */
{
  < IDENTIFIER :
    < LETTER >
    (
      < LETTER >
    | < DIGIT >
    )* >
| 
  < #LETTER : [ "_", "-", "a"-"z", "A"-"Z", "." ] >
| 
  < #DIGIT : [ "0"-"9" ] >
}

boolean expr() :
{
}
{
  {
    return Expression();
  }
}

boolean Expression() :
{
  boolean tmp1 = false;
  boolean tmp2 = false;
}
{
  tmp1 = TermExpression() [< LOGICAL_OR > tmp2 = TermExpression()]
  {
    return tmp1 || tmp2;
  }
}

boolean TermExpression() :
{
  boolean tmp1 = true;
  boolean tmp2 = true;
}
{
  tmp1 = FactorExpression() [< LOGICAL_AND > tmp2 = FactorExpression()]
  {

    return tmp1 && tmp2;
  }
}

boolean FactorExpression() :
{
  boolean exp;
}
{
  "(" exp = Expression() ")"
  {
    return exp;
  }
|
  {
    {
      return Label();
    }
  }
}

boolean Label() :
{
  Token t;
}
{
  t = < IDENTIFIER >
  {
    return ActionExpression.hasAction(t.image);
  }
}

思路跟前篇是一样的,过程不细讲了,按文档研究下很容易。

测试

运行代码

public class ActionExpressionTest {

    public static void main(String[] args) throws ParseException {

        System.out.println(ActionExpression.evaluate("User.Edit or User.Modify or (User.List and Admin)"));
        System.out.println(ActionExpression.evaluate("User.Edit or (User.List and Admin)"));
    }

}

测试了前一篇的两个表达式,发现运行正常至此结束。

All Done!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注