Created
May 10, 2013 11:05
-
-
Save anonymous/5553760 to your computer and use it in GitHub Desktop.
scala combinator parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment