2012-11-30 7 views
6

Ich verwende OCaml, um einen rekursiven Descent-Parser für eine Teilmenge von Scheme zu erstellen. Hier ist die Grammatik:Erstellen von AST in OCaml

S -> a|b|c|(T) 
    T -> ST | Epsilon 

Also sage ich:

type expr = 
     Num of int | String of string | Tuple of expr * expr 

Pseudocode

Diese Funktionen haben ausdr Typ zurückzukehren, um die AST

parseS lr = 
    if head matches '(' then 
    parseL lr 
    else 
    match tokens a, b, or c 

unter Verwendung eines ersten zu bauen Satz von S, die Token sind und '(':

Meine Frage ist "Wie kann ich für den Epsilon Teil zurückkehren, da ich einfach nicht zurück()?". Eine OCaml-Funktion benötigt den gleichen Rückgabetyp und selbst wenn ich für den Epsilon-Teil leer lasse, nimmt OCaml immer noch den Einheitentyp an.

Antwort

6

Soweit ich sehen kann, entspricht Ihr AST nicht Ihrer Grammatik.

Sie können das Problem lösen, indem Sie einen speziellen leeren Knoten in Ihrem AST-Typ haben, um das Epsilon in Ihrer Grammatik darzustellen.

Oder Sie können Ihre Grammatik ändern, um das Epsilon herauszufiltern.

Hier ist eine äquivalente Grammatik ohne Epsilon:

S -> a|b|c|()|(T) 
T -> S | S T 
+0

so zu meinem Verständnis, entweder muss ich einen Platzhalter für Epsilon einschließen oder die gegebene Grammatik anpassen, wie Sie erwähnten. Das scheint das Epsilon-Problem zu beseitigen. Bedeutet das, dass ich, wenn ich Epsilon sehe, die Grammatik umgeschrieben habe? – lovetostrike

+0

Ich würde ja sagen, im Konzept. In der Praxis bedeutet es nur, dass Sie in Ihrem Parser nach vorne schauen. Wenn Sie den Parser mit der Hand schreiben, können Sie wahrscheinlich damit arbeiten, ohne viel Zeit mit dem Umschreiben der Grammatik zu verschwenden. –

+0

Wenn S a, b, c vom Typ expr zurückgibt, was soll ich für() Teil in S zurückgeben? – lovetostrike

4

Vielleicht ist es besser, anstatt Parser-Funktionen manuell zu erstellen, existierende Ansätze zu verwenden: zum Beispiel LALR (1) ocamlyacc oder camlp4 basierend LL (k) parsers?

+1

oder [Menhir] (http://gallium.inria.fr/~fpottier/menhir/). – Thomash

+2

Danke Jungs :). Aber ich kann vorhandene Dienstprogramme nicht verwenden, da dies eine Übung ist. – lovetostrike