OMeta ist ein Objekt-Orientiertes Parser Framework für PEG’s. Die Implementierung ist in diversen dynamischen Programmiersprachen verfügbar (Javascript, Python, Common Lisp, C#, Scheme, Ruby). Diese muss aber als Interpretation des Modells angesehen werden.OMeta hat dabei die Ansprüche (welche auch durchaus durchgehalten werden), dass die Implementierung minimal sein sollte. Das äußert sich vor allem darin, dass Code stets wiederverwendbar sein soll und dabei minimalistisch und einfach zu verstehen sein soll.
Die Grundlage hierfür ist das Projekt ‘STEPS Toward the Reinvention of Programming’ vom Viewpoint Research Institut in Glendale, Kalifornien. OMeta dient diesem Projekt quasi als Instrument zur Entwicklung von Domänenspezifischen Programmiersprachen. Dabei ist der Funktionsumfang weitaus größer als der eines gewöhnlichen Parsers. Ähnlich wie DCGs in Prolog kann mithilfe dieses Frameworks problemlos eine Intermediäre Respräsentation der Sprache, z.B.: ein abstrakter Syntaxbaum erstellt werden. Darüber hinaus lassen sich beliebige Methoden ausführen. Beispielsweise kann über den Parser das komplette Bootstrapping einer Sprache gesteuert werden (z.B.: Parsen, Kompilieren in Bytecode, Interpretieren des Bytecodes).
Das Beispiel zeigt einen Parser, der gleichzeitig auch Interpreter für die Turing-vollständige Sprache Brainfuck ist. Die Grammatikregeln befinden sich in der Variabel bfgrammar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | """ Simple Interpreter for the Brainfuck language. Implemented with the Parser framework PyMeta2. - http://de.wikipedia.org/wiki/Brainfuck - http://www.allbuttonspressed.com/projects/pymeta """ __author__ = "Rene Bartelmus <rene.bartelmus@uni-duesseldorf.de>" __date__ = "13 September 2012" __version__ = 1, 0 import sys from pymeta.grammar import OMeta bfgrammar = """ skip = '[' ('.'|','|'<'|'>'|'+'|'-' | skip)* ']' rule = '.' -> sys.stdout.write(chr(self.band[self.current])) | ',' -> self.read() | '<' -> self.left() | '>' -> self.right() | '+' -> self.plus() | '-' -> self.minus() | ~~('[') ?(self.test_true()) '[' -> self.loop_begin() | ~~('[') ?(self.test_false()) skip | ']' -> self.loop_end() grammar = rule+ end """ class Tape(dict): def __getitem__(self, key): if key not in self: super(Tape, self).__setitem__(key, 0) return super(Tape, self).__getitem__(key) class Parser(OMeta.makeGrammar(bfgrammar, globals(), "MTGrammar")): band = Tape() current = 0 loop = [] def set_input(self, input): input = [ord(i) for i in input] input.reverse() self.in_stream = input def read(self): self.band[self.current] = self.in_stream.pop() def test_true(self): return not not self.band[self.current] def test_false(self): return not self.band[self.current] def plus(self): self.band[self.current] += 1 def minus(self): self.band[self.current] -= 1 def left(self): self.current += 1 def right(self): self.current -= 1 def loop_begin(self): self.loop.append(self.input.position-1) def loop_end(self): self.input.position = self.loop.pop() if __name__ == "__main__": if len(sys.argv) == 3: p = Parser(sys.argv[1]) p.set_input(sys.argv[2]+"\x00") try: p.apply("grammar") except Exception as e: print e.formatError(sys.argv[1]) sys.exit(1) else: print 'Call example: python brainfuck.py PROGRAM INPUT' |
Ein Beispielaufruf könnte sein:
mit der Ausgabe:
Weiterführende Links:
- OMeta Webseite http://tinlizzie.org/ometa/
- VPRI http://www.vpri.org/index.html
- Proposal von STEPS (PDF 1,1 MB) http://www.vpri.org/pdf/rn2006002_nsfprop.pdf
- OMeta Artikel (PDF 330 KB) http://www.vpri.org/pdf/tr2007003_ometa.pdf