Skip to content

Instantly share code, notes, and snippets.

Created May 10, 2013 11:05
Show Gist options
  • Save anonymous/5553760 to your computer and use it in GitHub Desktop.
Save anonymous/5553760 to your computer and use it in GitHub Desktop.

Revisions

  1. @invalid-email-address Anonymous created this gist May 10, 2013.
    150 changes: 150 additions & 0 deletions parser.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,150 @@
    package com.baidu.cms.thirtpart
    import util.parsing.combinator.JavaTokenParsers
    import java.io.FileReader
    import java.util.regex.Pattern
    import com.baidu.cms.thirtpart.TransferRuleContext._
    import com.baidu.cms.thirtpart.TransferRuleContext.ActivityRef
    import com.baidu.cms.thirtpart.TransferRuleContext.FieldValueFilter
    import com.baidu.cms.thirtpart.TransferRuleContext.Rule
    import com.baidu.cms.thirtpart.TransferRuleContext.OperatorFetchStrategy
    import scala.collection.JavaConversions._
    /**
    *
    * User: sunflower
    * Date: 12-9-14
    * Time: 下午8:54
    *
    */
    class TransferParser extends JavaTokenParsers {
    def value: Parser[TransContext] = rep(statement) ^^ {
    case state =>
    val context: TransContext = new TransContext()
    state foreach context.interpret
    context
    }

    def statement: Parser[AST] = varDefinition ^^ {
    case v => v
    } | rulesDefinition ^^ {
    case r => RulesDefinition(r)
    }

    def varDefinition: Parser[Var] = (ident <~ ":=") ~ (complexValue <~ ",") ^^ {
    case name ~ value =>
    Var(name, value)
    }

    def complexValue: Parser[VarValue] = "class:" ~ """[a-zA-Z][a-zA-Z0-9.]*""".r ^^ {
    case "class:" ~ classpath => LocalClass(classpath)
    } | "spring:" ~ """[a-zA-Z][a-zA-Z0-9.]*""".r ^^ {
    case "spring:" ~ beanId => SpringManagedBean(beanId)
    } | varValue ^^ {
    case value => SimpleValue(value)
    }

    def varValue = """[^,][0-9a-zA-Z"_\p{InCJKUnifiedIdeographs}:+*/\\.-]*""".r

    def rulesDefinition: Parser[Set[Rule]] = ("transformRules" <~ ":=") ~ ("{" ~> repsep(ruleDef, ",") <~ "}") ^^ {
    case "transformRules" ~ rules => Set() ++ rules
    }

    def ruleDef: Parser[Rule] = from ~ to ~ opt(props) ^^ {
    case from ~ to ~ props => {
    if (props.isEmpty)
    Rule(from, to, collection.mutable.Map.empty[String, OperatorProp])
    else
    Rule(from, to, props.get)
    }
    }

    def from = "from" ~> activityRef

    def to = "to" ~> activityRef

    def activityRef: Parser[ActivityRef] = ("(" ~> ident <~ ":") ~ (varValue <~ ")") ^^ {
    case id ~ name => ActivityRef(id, name)
    }

    def props: Parser[collection.mutable.Map[String, OperatorProp]] = "{" ~> repsep(prop, ",") <~ "}" ^^ {
    case props =>
    val map = collection.mutable.Map.empty[String, OperatorProp]
    for (p <- props) {
    map.update(p.name, p)
    }
    map
    }

    def prop: Parser[OperatorProp] =
    "operator" ~ ("{" ~> executorArithmetic <~ "}") ^^ {
    case "operator" ~ expr => OperatorProp("operator", expr)
    } | "countersign-users" ~ ("{" ~> executorArithmetic <~ "}") ^^ {
    case "countersign-users" ~ expr => OperatorProp("countersign-users", expr)
    }

    def executorArithmetic: Parser[OperatorFetchExpr] = fetchStrategy ~ rep("+" ~ fetchStrategy | "-" ~ fetchStrategy) ^^ {
    case fs ~ ms =>
    if (ms.isEmpty) {
    OperatorFactor(fs)
    } else {
    processOperatorArithmetic(ms, OperatorFactor(fs))
    }
    }

    def fetchStrategy: Parser[OperatorFetchStrategy] = ident ~ repsep(filter,",") ^^ {
    case strategyName ~ filter =>
    if (filter.isEmpty) OperatorFetchStrategy(strategyName)
    else {
    val map = collection.mutable.Map.empty[String, FieldValueFilter]
    for (f <- filter){
    map.update(f.fieldName,f)
    }
    OperatorFetchStrategy(strategyName, map)
    }
    }

    def filter: Parser[FieldValueFilter] = ("[" ~> ident) ~ ("=" ~> restriction <~ "]") ^^ {
    case propName ~ pattern => FieldValueFilter(propName, pattern)
    }

    def restriction: Parser[Pattern] = ("Regex" <~ "@@") ~ ("""[^@][^@][a-zA-Z0-9(){}.$*/@+\\_-]+""".r <~ "@@") ^^ {
    case "Regex" ~ regex => Pattern.compile(regex)
    }

    def processOperatorArithmetic(tail: List[~[String, OperatorFetchStrategy]],
    expr: OperatorFetchExpr): OperatorFetchExpr = tail match {
    case head :: xs => head match {
    case "+" ~ strategy => processOperatorArithmetic(xs, OperatorAdd(expr, OperatorFactor(strategy)))
    case "-" ~ strategy => processOperatorArithmetic(xs, OperatorMinus(expr, OperatorFactor(strategy)))
    }
    case Nil => expr
    }

    }

    object ScriptParser extends TransferParser {
    def doParse(script: String): TransContext = {
    val reader: FileReader = new FileReader(script)
    try {
    parseAll(value, reader) match {
    case Success(r, next) => {
    r.checkMandatoryVars()
    r.init()
    r
    }
    case e@NoSuccess(msg, next) => throw new RuntimeException(e.toString)
    }
    } finally {
    reader.close()
    }
    }
    // test run
    def main(args: Array[String]) {
    val context: TransContext = doParse("普通流程-迁移.transfer")
    val rule: Rule = context.findRule("act64")
    println(rule)
    val instance: ActivityInstance = new ActivityInstance("123", "123", rule.from.id, context.processDef.id)
    val result: java.util.List[ActivityOperator] =
    OperatorExprEvaluator.evaluate(rule.props.get("countersign-users").fetch, rule,instance, context)
    println(result)
    }
    }