ometa TestOMetaParser <: 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 '\'' '\'' -> ["App", "seq", ident(xs)], sCharacters = '"' (~'"' eChar)*:xs '"' -> ["App", "token", ident(xs)], string = (('#' | '`') tsName | tsString):xs -> ["App", "exactly", ident(xs)], number = ('-' | empty -> ''):sign digit+:ds -> ["App", "exactly", sign + joinStr(ds)], keyword :xs = token(xs) ~letterOrDigit -> xs, hostExpr = foreign(BSJSParser, `expr):r foreign(BSJSTranslator, `trans, r), atomicHostExpr = foreign(BSJSParser, `semAction):r foreign(BSJSTranslator, `trans, r), args = "(" listOf(`hostExpr, ','):xs ")" -> xs | empty -> [], application = name:rule args:as -> joinList(["App", rule], as), semAction = ("!" | "->") atomicHostExpr:x -> ["Act", x], semPred = "?" atomicHostExpr:x -> ["Pred", x], expr = listOf(#expr4, '|'):xs -> joinList(["Or"], xs), expr4 = expr3*:xs -> joinList(["And"], xs), optIter :x = "*" -> ["Many", x] | "+" -> ["Many1", x] | empty -> x, expr3 = expr2:x optIter(x):x ( ':' name:n -> define(self, n, ["Set", n, x]) | empty -> x ) | ":" name:n -> define(self, n, ["Set", n, ["App", "anything"]]), expr2 = "~" expr2:x -> ["Not", x] | "&" expr1:x -> ["Lookahead", x] | expr1, expr1 = application | semAction | semPred | ( keyword('undefined') | keyword('nil') | keyword('true') | keyword('false') ):x -> ["App", "exactly", x] | spaces (characters | sCharacters | string | number) | "[" expr:x "]" -> ["Form", x] | "(" expr:x ")" -> x, ruleName = name | spaces tsString, rule = &(ruleName:n) !(newScope(self, n)) rulePart(n):x ("," rulePart(n))*:xs -> ["Rule", n, getScope(self), joinList(["Or", x], xs)], rulePart :rn = ruleName:n ?(n == rn) expr4:b1 ( "=" expr:b2 -> ["And", b1, b2] | empty -> b1 ), grammar = keyword('ometa') name:n ( "<:" name | empty -> 'OMeta' ):sn "{" listOf(#rule, ','):rs "}" -> joinList(["Grammar", n, sn], rs) } ///END/// newScope = function(self, name) { return self.locals = ['$elf=this']; } getScope = function(self) { return self.locals; } define = function(self, name, result) { self.locals.push(name); return result; } charEscape = function(c) { return unescape("\\"+c); } joinStr = function(xs) { return xs.join ? xs.join("") : xs; } joinList = function(l0, l1) { return l0.concat(l1); } ident = function(xs) { return joinStr(xs).toProgramString(); } evalItem = function(s) { return eval(s); } thisFile = readFile("swh_ometa_parser") ometaGrammar = thisFile.substring(0, thisFile.indexOf("///END///")) 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