2016-05-23 2 views
0

Ich habe diese Grammatik Abschnitt in einem glücklichen Parser, auf der offiziellen Website Happy gegeben, aber ich brauche eine tiefere Erklärung der Bedeutung der Regeln in Klammern. Hier ist die Token-DefinitionSyntax happy Parser Bedeutung

%token 
     let    { TokenLet } 
     in    { TokenIn } 
     int    { TokenInt $$ } 
     var    { TokenVar $$ } 
     '='    { TokenEq } 
     '+'    { TokenPlus } 
     '-'    { TokenMinus } 
     '*'    { TokenTimes } 
     '/'    { TokenDiv } 
     '('    { TokenOB } 
     ')'    { TokenCB } 

und hier die Grammatik

Exp : let var '=' Exp in Exp { Let $2 $4 $6 } 
      | Exp1     { Exp1 $1 } 

Exp1 : Exp1 '+' Term   { Plus $1 $3 } 
     | Exp1 '-' Term   { Minus $1 $3 } 
     | Term     { Term $1 } 

Term : Term '*' Factor   { Times $1 $3 } 
     | Term '/' Factor   { Div $1 $3 } 
     | Factor     { Factor $1 } 

Factor    
     : int      { Int $1 } 
     | var      { Var $1 } 
     | '(' Exp ')'    { Brack $2 } 

Was ich verstehe, ist, dass die Lexer, wie unten definiert in der Datei erzeugen sollten Token nur von der Art definined und dann bauen die den Baum unter Verwendung der Grammatik analysieren. Aber was genau bedeutet "{$ 2 $ 4 $ 6}"? Ich weiß, dass $ 2 sich auf das zweite Regelargument bezieht und so weiter, aber wenn mir jemand eine "menschliche Leseversion" der Regeln geben könnte, wäre ich wirklich glücklich. Hoffe, ich war klar.

Vielen Dank im Voraus.

Antwort

1

Im Abschnitt %token sind die linken Spalte die Token-Namen, die an anderer Stelle in der Grammatik verwendet werden, und das rechte ist ein Muster, das in einer case-Anweisung verwendet werden kann. Wo Sie $$ Happy sehen, wird eine eigene Variable ersetzen. Wenn also der resultierende Parser zu einem bestimmten Zeitpunkt eine Ganzzahl erwartet, wird Happy eine case-Anweisung mit einem Muster einschließlich TokenInt v1234 haben, wobei das Bit v1234 ein von Happy erstellter Variablenname ist.

Das "Let" ist der Konstruktor für den Grammatikausdruck, der erkannt wird. Wenn Sie ein wenig weiter unten in der Beispielseite sehen Sie,

data Exp 
    = Let String Exp Exp 
    | Exp1 Exp1 
    deriving Show 

So ist der Let Konstruktor einen String und zwei Unterausdrücke nimmt (vom Typ ‚Exp‘). Wenn Sie sich die Grammatik ansehen, können Sie sehen, dass es sechs Elemente in der let Regel gibt. Der erste ist nur die konstante Zeichenfolge "Let". Dies wird vom generierten Parser verwendet, um herauszufinden, dass er eine "let" -Klausel betrachtet, aber der resultierende Parse-Baum braucht ihn nicht. So erscheint $1 nicht. Stattdessen muss das erste Argument für den Konstruktor Let der Name der zu bindenden Variablen sein, die das zweite Element der Grammatikregel ist. Daher ist dies $2. Die anderen Dinge sind die zwei Unterausdrücke, die $4 und $6 durch die gleiche Logik sind.Beides können beliebig komplexe Ausdrücke sein: Happy gibt an, wo sie beginnen und enden und analysiert sie, indem sie die anderen Regeln für das, was Ausdrücke ausmacht, befolgt.

+0

Hallo danke an alle für die Antwort. Zum Beispiel war in der Aktion "Plus $ 1 $ 3" ​​nicht genug, um $$ = $ 1 + $ 3 zu schreiben? – davideb93

+0

Der "Plus" ist der Konstruktor, den Sie in Haskell verwenden, während das "+" in der Syntax des geparsten Dokuments zu finden ist. Ihr "$$ = $ 1 + $ 3" ​​hat nichts, das "+" in dem Dokument mit dem "Plus" in dem Syntaxbaum zu verknüpfen. –

1

Diese Linie ist eine Regel zum Erzeugen (Parsing), um die Produktion Exp:

Exp : let var '=' Exp in Exp { Let $2 $4 $6 } 

Sie entspricht die Regel:

if you see "let"  ($1) 
followed by a variable name ($2) 
followed by "="   ($3) 
followed by an Exp  ($4) 
followed by "in"  ($5) 
followed by another Exp ($6) 

dann wieder den Wert Let $2 $4 $6. Die $n Parameter werden durch die Werte jeder Unterproduktion ersetzt. Also, wenn diese Regel übereinstimmt, die Let Funktion (die wahrscheinlich einige Daten Konstruktor ist) wird mit aufgerufen werden:

  • der Wert des var Token als ersten Parameter,
  • die erste Exp analysiert ($ 4) als zweiter Parameter
  • und der zweite geparste Exp ($ 6) als dritter Parameter.

Ich glaube hier ist der Wert des var Tokens der Variablenname.