ometa GenOMetaParser <: Parser { nameFirst = '_' | '$' | letter, nameRest = nameFirst | digit, tsName = firstAndRest(#nameFirst, #nameRest):xs -> joinStr(xs), name = spaces tsName, eChar = '\\' char:c -> charEscape(c) | char, tsString = '\'' (~'\'' eChar)*:xs '\'' -> joinStr(xs), characters = '`' '`' (~('\'' '\'') eChar)*:xs '\'' '\'' -> gen_strSequence(self, xs), sCharacters = '"' (~'"' eChar)*:xs '"' -> gen_strToken(self, xs), string = (('#' | '`') tsName | tsString):xs -> gen_strExactly(self, xs), number = ('-' | empty -> ''):sign digit+:ds -> gen_number(self, sign, ds), keyword :xs = token(xs) ~letterOrDigit -> xs, args = "(" listOf(`hostExpr, ','):xs ")" -> xs | empty -> [], application = name:rule args:rargs -> gen_apply(self, rule, rargs), hostExpr = foreign(BSJSParser, `expr):r foreign(BSJSTranslator, `trans, r), atomicHostExpr = foreign(BSJSParser, `semAction):r foreign(BSJSTranslator, `trans, r), semAction = ("!" | "->") atomicHostExpr:x -> gen_action(self, x), semPred = "?" atomicHostExpr:x -> gen_predicate(self, x), expr = listOf(#expr4, '|'):xs -> gen_groupOr(self, xs), expr4 = expr3*:xs -> gen_groupAnd(self, xs), optIter :x = "*" -> gen_many(self, x) | "+" -> gen_many1(self, x) | empty -> x, expr3 = expr2:x optIter(x):x ( ':' name:n -> gen_define(self, n, x) | empty -> x ) | ":" name:n -> gen_defineAsAny(self, n), expr2 = "~" expr2:x -> gen_not(self, x) | "&" expr1:x -> gen_look(self, x) | expr1, expr1 = "<" hostExpr:he ">" -> gen_hostExprApp(self, he) | application | semAction | semPred | ( keyword('undefined') | keyword('nil') | keyword('true') | keyword('false') ):x -> gen_exactly(self, x) | spaces (characters | sCharacters | string | number) | "[" expr:x "]" -> gen_form(self, x) | "(" expr:x ")" -> x, rule = name:n name+:args "=" expr:e -> gen_ruleFunction(self, n, args, e) | name:n "=" expr:e -> gen_ruleBody(self, n, e), rule = &(name:n) !(newScope(self, n)) rulePart(n):x ("," rulePart(n))*:xs -> gen_rule(self, n, x, xs), rulePart :rn = name:n ?(n == rn) expr4:b1 ( "=" expr:b2 -> gen_rulePartAs(self, n, b1, b2) | empty -> gen_rulePart(self, n, b1) ), grammar = keyword('ometa') name:n ( "<:" name | empty -> 'OMeta' ):sn "{" listOf(#rule, ','):rs "}" -> gen_grammar(self, n, sn, rs) } ///END/// thisFile = readFile("swh_ometa_parser_dispatch") ometaGrammar = thisFile.substring(0, thisFile.indexOf("///END///")) /* Scope declarations... */ newScope = function(self, name) { return self.locals = ['me']; } getScope = function(self) { r = self.locals; if (!r) { r = newScope(self, null); } return r; } define = function(self, name, result) { self.locals.push(name); return result; } /* Utility Functions */ charEscape = function(c) { return unescape("\\"+c); } joinStr = function(xs) { return xs.join ? xs.join("") : xs; } asString = function(xs) { return joinStr(xs).toProgramString(); } evalEscape = function(expr) { if (expr == '""') return "'" + expr + "'"; if (expr == "''") return '"' + expr + '"'; return "'''" + expr + "'''"; } /*********** * Generation functions ***/ gen_exactly = function(self, v) { return ["App", "exactly", v] } gen_apply = function(self, rule, args) { return ["App", rule].concat(args) } gen_strSequence = function(self, xs) { return gen_apply(self, "seq", [asString(xs)]) } gen_strToken = function(self, xs) { return gen_apply(self, "token", [asString(xs)]) } gen_strExactly = function(self, xs) { return gen_exactly(self, asString(xs)) } gen_number = function(self, sign, ds) { return gen_exactly(self, sign+asString(ds)) } gen_action = function(self, x) { return ["Act", evalEscape(x)] } gen_predicate = function(self, x) { return ["Pred", evalEscape(x)] } gen_hostExprApp = function(self, he) { return ["HostExprApp", he]; } gen_groupOr = function(self, xs) { return ["Or"].concat(xs); } gen_groupAnd = function(self, xs) { return ["And"].concat(xs); } gen_many = function(self, x) { return ["Many", x]; } gen_many1 = function(self, x) { return ["Many1", x]; } gen_define = function(self, name, val) { define(self, name); return ["Set", name, val]; } gen_defineAsAny = function(self, name) { return gen_define(self, name, ["App", "anything"]); } gen_not = function(self, x) { return ["Not", x] } gen_look = function(self, x) { return ["Lookahead", x] } gen_form = function(self, x) { return ["Form", x] } gen_ruleFunction = function(self, name, args, body) { Transcript.show(name+' args: '+ args.toString() + ' ruleFn: ' + body.toString()); return ["RuleFunction", name, args, ["RuleBody", body]]; } gen_ruleBody = function(self, name, body) { var result = ["Rule", name, getScope(self), body]; var r2 = gen_rule(self, name, gen_rulePartAs(null, body), []); Transcript.show(name+' ruleBody1: ' + result.toString()); Transcript.show(name+' ruleBody2: ' + r2.toString()); return r2 } gen_rule = function(self, name, x, xs) { return ["Rule", name, getScope(self), ["Or", x].concat(xs)] } gen_rulePart = function(self, name, b1) { Transcript.show(name + " rp: " + b1.toString()) return b1; } gen_rulePartAs = function(self, name, b1, b2) { Transcript.show(name + " rpa: " + ["And", b1, b2].toString()) return ["And", b1, b2]; } gen_grammar = function(self, n, sn, rs) { return ["Grammar", n, sn].concat(rs); } /********** * Testing ***/ r = BSOMetaParser.matchAll(thisFile, "grammar") /* Transcript.show("\nBSOMetaParser = [") for (ri=0;ri ans | anything, optimize = trans:x helped -> x, Or trans*:xs -> [`Or].concat(xs), And trans*:xs -> [`And].concat(xs), Many trans:x -> [`Many, x], Many1 trans:x -> [`Many1, x], Set :n trans:v -> [`Set, n, v], Not trans:x -> [`Not, x], Lookahead trans:x -> [`Lookahead, x], Form trans:x -> [`Form, x], Rule :name :ls trans:body -> [`Rule, name, ls, body] } NullOptimization.initialize = function() { this._didSomething = false } ometa AndOrOptimization <: NullOptimization { And trans:x end setHelped -> x, And transInside(#And):xs -> [`And].concat(xs), Or trans:x end setHelped -> x, Or transInside(#Or):xs -> [`Or].concat(xs), transInside :t = [exactly(t) transInside(t):xs] transInside(t):ys setHelped -> xs.concat(ys) | trans:x transInside(t):xs -> [x].concat(xs) | -> [] } ometa OMetaOptimizer { optimizeGrammar = [`Grammar :n :sn optimizeRule*:rs] -> [`Grammar, n, sn].concat(rs), optimizeRule = :r (foreign(AndOrOptimization, #optimize, r):r)* -> r } r = OMetaOptimizer.match(r, "optimizeGrammar") Transcript.show("\nOptimized TestOMetaParser = [") for (ri=0;ri