2016-07-28 20 views
6

Mit diesem Befehl:Simplest von Parsern in go-Tool yacc

go tool yacc -p Verb -o verb.go boilerplate.y 

Der Versuch, diese yacc-Datei zu erstellen:

// boilerplate.y 
%{ 

package main 

import (
    "bufio" 
    "fmt" 
    "os" 
    "unicode" 
) 

%} 

%% 

.|\n ECHO; 

%% 

func main() { 
    fi := bufio.NewReader(os.NewFile(0, "stdin")) 
    s, err := fi.ReadString('\n') 
    if err != nil { 
    fmt.Println('error', err) 
    } 

    VerbParse(&VerbLex{s: s}) 
} 

Fehler: bad syntax on first rule: boilerplate.y:16

Erfolgreich dieses Beispiel an die Arbeit:

https://github.com/golang-samples/yacc/blob/master/simple/calc.y

Versuchen, meine eigenen und arbeiten durch die Lex & yacc Buch. Ressourcen scheinen auf nicht vorhanden zu sein.

Antwort

4

Sie haben eine falsche rule in Ihren Spezifikationen.

A Spezifikationsdatei hat die folgende Deklaration:

declarations 
%% 
rules 
%% 
programs 

Wo ein rule definiert ist als:

A : BODY ; 

Wo A ein Nicht-Terminal-Symbol ist, während BODY gemacht von Tokens (Terminalsymbole), Nicht-Terminals und Literalen. Die : und ; sind erforderliche Komponenten der Syntax der Regeldeklaration.

Daraus ergibt sich die Regel:

.|\n ECHO; 

ist syntaktisch falsch.

Da Sie versuchen einfach, den Eingang, eine sehr einfache Implementierung auf calc.y basierend auf Echo würde folgende (Datei echo.y):

Regeln

%% 

in : /* empty */ 
    | in input '\n' 
    { fmt.Printf("Read character: %s\n", $2) } 
    ; 

input : CHARACTER 
    | input CHARACTER 
     { $$ = $1 + $2 } 
    ; 

Programm

%% 

type InputLex struct { 
    // contains one complete input string (with the trailing \n) 
    s string 
    // used to keep track of parser position along the above imput string 
    pos int 
} 

func (l *InputLex) Lex(lval *InputSymType) int { 
    var c rune = ' ' 

    // skip through all the spaces, both at the ends and in between 
    for c == ' ' { 
     if l.pos == len(l.s) { 
      return 0 
     } 
     c = rune(l.s[l.pos]) 
     l.pos += 1 
    } 

    // only look for input characters that are either digits or lower case 
    // to do more specific parsing, you'll define more tokens and have a 
    // more complex parsing logic here, choosing which token to return 
    // based on parsed input 
    if unicode.IsDigit(c) || unicode.IsLower(c) { 
     lval.val = string(c) 
     return CHARACTER 
    } 

    // do not return any token in case of unrecognized grammer 
    // this results in syntax error 
    return int(c) 
} 

func (l *InputLex) Error(s string) { 
    fmt.Printf("syntax error: %s\n", s) 
} 

func main() { 
    // same as in calc.y 
} 

func readline(fi *bufio.Reader) (string, bool) { 
    // same as in calc.y 
} 

Zum Kompilieren und dieses Programm ausführen, gehen Sie wie folgt auf Eingabeaufforderung:

go tool yacc -o echo.go -p Input echo.y 
go run echo.go 

Wie Sie sehen können, werden Sie Ihre eigenen Parsing-Regeln in der Lex Methode definieren. Die Struktur InputLex enthält die Werte, während Ihre Eingabe analysiert wird. InputSymType wird automatisch generiert und wird durch den %union definiert, der im Teil der Spezifikation angegeben ist.

Soweit ich sagen kann, gibt es keine Möglichkeit, JISON oder eine Regex direkt zu verwenden, um den Abgleich mit go's yacc Werkzeug zu tun. Möglicherweise müssen Sie sich einige andere Bibliotheken ansehen.

Weitere Details finden Sie hier: http://dinosaur.compilertools.net/yacc/

Vollarbeitscode hier: https://play.golang.org/p/u1QxwRKLCl

+0

Ich möchte nur eine einfache Datei Standardeingabe Echo. Ich kenne nur JISON, und darin gibt es Lexregeln und Grammatikregeln. Ich wollte sehen, wie die beiden mit Go in einer .y-Datei ausgebrochen sind, an der ich arbeiten kann, um die einfache calc-Datei wiederherzustellen, dann vielleicht einen json-Parser oder sowas. –

+0

Hier ist JISON mit Lex-Regeln in der gleichen Datei: http://zaa.ch/jison/demos/calc/ Ich weiß nicht wirklich, wie eine Lex-Funktion funktioniert, die du verlinkt hast. Ich sehe das Lex-Stadium mit Hilfe von reg ex in Token brechen. –

+0

Ein einfacher Echo-Parser wurde hinzugefügt. Soweit ich das beurteilen kann, ist JISON möglicherweise nicht mit yacc von go tool verwendbar. – abhink