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.
scala combinator parser
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