# -*- test-case-name: pymeta.test.test_pymeta -*- """ Public interface to OMeta, as well as the grammars used to compile grammar definitions. """ import string from .builder import TreeBuilder, moduleFromGrammar from .boot import BootOMetaGrammar from .runtime import OMetaBase, ParseError, EOFError class OMeta(OMetaBase): """ Base class for grammar definitions. """ metagrammarClass = BootOMetaGrammar def makeGrammar(cls, grammar, globals, name="Grammar"): """ Define a new subclass with the rules in the given grammar. @param grammar: A string containing a PyMeta grammar. @param globals: A dict of names that should be accessible by this grammar. @param name: The name of the class to be generated. """ g = cls.metagrammarClass(grammar) tree = g.parseGrammar(name, TreeBuilder) return moduleFromGrammar(tree, name, cls, globals) makeGrammar = classmethod(makeGrammar) ometaGrammar = r""" number ::= ('-' :x => -x |:x => x) barenumber ::= ('0' (('x'|'X') *:hs => int(''.join(hs), 16) |*:ds => int('0'+''.join(ds), 8)) |+:ds => int(''.join(ds))) octaldigit ::= :x ?(x in string.octdigits) => x hexdigit ::= :x ?(x in string.hexdigits) => x escapedChar ::= '\\' ('n' => "\n" |'r' => "\r" |'t' => "\t" |'b' => "\b" |'f' => "\f" |'"' => '"' |'\'' => "'" |'\\' => '\\') character ::= ( | ):c => c bareString ::= ( | ~('"') )*:c => ''.join(c) string ::= :s => self.builder.exactly(s) name ::= :x *:xs !(xs.insert(0, x)) => ''.join(xs) application ::= ( :name (' ' !(self.applicationArgs(finalChar='>')):args => self.builder.apply(name, self.name, *args) |'> => self.builder.apply(name, self.name))) expr1 ::= ( | | | |( | ):lit => self.builder.exactly(lit) | | :e => e | :e => self.builder.listpattern(e)) expr2 ::= ( ( :e => self.builder.lookahead(e) |:e => self.builder._not(e)) |) expr3 ::= ((:e ('*' => self.builder.many(e) |'+' => self.builder.many1(e) |'?' => self.builder.optional(e) | => e)):r (':' :n => self.builder.bind(r, n) | => r) | :n => self.builder.bind(self.builder.apply("anything", self.name), n)) expr4 ::= *:es => self.builder.sequence(es) expr ::= :e ( )*:es !(es.insert(0, e)) => self.builder._or(es) ruleValue ::= "> => self.ruleValueExpr(False) semanticPredicate ::= => self.semanticPredicateExpr() semanticAction ::= => self.semanticActionExpr() rulePart :requiredName ::= ( :n ?(n == requiredName) !(setattr(self, "name", n)) :args ( | '\r' | '\n') emptyline ::= * indentation ::= * + noindentation ::= * ~~~ number ::= ('-' :x => self.builder.exactly(-x) |:x => self.builder.exactly(x)) barenumber ::= '0' (('x'|'X') *:hs => int(''.join(hs), 16) |*:ds => int('0'+''.join(ds), 8)) |+:ds => int(''.join(ds)) octaldigit ::= :x ?(x in string.octdigits) => x hexdigit ::= :x ?(x in string.hexdigits) => x escapedChar ::= '\\' ('n' => "\n" |'r' => "\r" |'t' => "\t" |'b' => "\b" |'f' => "\f" |'"' => '"' |'\'' => "'" |'\\' => "\\") character ::= ( | ):c => self.builder.exactly(c) string ::= ( | ~('"') )*:c => self.builder.exactly(''.join(c)) name ::= :x *:xs !(xs.insert(0, x)) => ''.join(xs) application ::= ? :name ('(' !(self.applicationArgs(finalChar=')')):args => self.builder.apply(name, self.name, *args) | => self.builder.apply(name, self.name)) expr1 ::= | | | | | | | :e => e | :e => self.builder.listpattern(e) expr2 ::= ( :e => self.builder.lookahead(e) |:e => self.builder._not(e)) | expr3 ::= (:e ('*' => self.builder.many(e) |'+' => self.builder.many1(e) |'?' => self.builder.optional(e) | => e)):r (':' :n => self.builder.bind(r, n) | => r) | :n => self.builder.bind(self.builder.apply("anything", self.name), n) expr4 ::= *:es => self.builder.sequence(es) expr ::= :e ( )*:es !(es.insert(0, e)) => self.builder._or(es) ruleValue ::= "> => self.ruleValueExpr(True) semanticPredicate ::= => self.semanticPredicateExpr() semanticAction ::= => self.semanticActionExpr() rulePart :requiredName ::= :n ?(n == requiredName) !(setattr(self, "name", n)) :args (*:exprs]] => self.builder.apply(ruleName, codeName, *exprs) | ["Exactly" :expr] => self.builder.exactly(expr) | ["Many" :expr] => self.builder.many(expr) | ["Many1" :expr] => self.builder.many1(expr) | ["Optional" :expr] => self.builder.optional(expr) | ["Or" [*:exprs]] => self.builder._or(exprs) | ["And" [*:exprs]] => self.builder.sequence(exprs) | ["Not" :expr] => self.builder._not(expr) | ["Lookahead" :expr] => self.builder.lookahead(expr) | ["Bind" :name :expr] => self.builder.bind(expr, name) | ["Predicate" :expr] => self.builder.pred(expr) | ["Action" :code] => self.builder.action(code) | ["Python" :code] => self.builder.expr(code) | ["List" :exprs] => self.builder.listpattern(exprs) ) grammar ::= ["Grammar" :name [*:rs]] => self.builder.makeGrammar(rs) rulePair ::= ["Rule" :name :rule] => self.builder.rule(name, rule) """ NullOptimizer = OMeta.makeGrammar(nullOptimizationGrammar, {}, name="NullOptimizer")