Also versuche ich einen Compiler in F # zu schreiben und habe mir die Fslex- und Fsyacc-Tools angesehen, die mit dem F # Powerpack geliefert werden. Es gibt ein Beispielprojekt, das sich um die externen Build-Tools kümmert, die ich zu verstehen versucht habe. Es kann heruntergeladen werden here. Das Beispiel kompiliert und läuft für mich, aber ich denke, es gibt einen subtilen Fehler in der Grammatik. Ich sage subtil, weil die Grammatik dem ähnelt, was ich im Dragon-Buch zum Parsen von Ausdrücken gesehen habe, und ich habe nicht die Erfahrung, es zu erkennen.Fehler in Beispielgrammatik für Fsyacc?
Der Eingang "4 * 5 + 3" richtig bis 23 bewertet
der Eingang 4 * 5-3 erzeugt jedoch einen Analysefehler. Das ist ein Fehler in dem von Fsyacc generierten Code.
Ich würde Ihre Hilfe schätzen, um besser zu verstehen, was das Problem ist, damit ich besser informiert werden kann und mehr Vertrauen in Fsyacc habe. Ich habe die * .fsy Datei unten gepostet.
// This is the type of the data produced by a successful reduction of the 'start'
// symbol:
%type <Ast.Equation> start
%%
// These are the rules of the grammar along with the F# code of the
// actions executed as rules are reduced. In this case the actions
// produce data using F# data construction terms.
start: Prog { Equation($1) }
Prog:
| Expr EOF { $1 }
Expr:
| Expr PLUS Term { Plus($1, $3) }
| Expr MINUS Term { Minus($1, $3) }
| Term { Term($1) }
Term:
| Term ASTER Factor { Times($1, $3) }
| Term SLASH Factor { Divide($1, $3) }
| Factor { Factor($1) }
Factor:
| FLOAT { Float($1) }
| INT32 { Integer($1) }
| LPAREN Expr RPAREN { ParenEx($2) }
Und hier ist die Definition für AST-Datentyp
namespace Ast
open System
type Factor =
| Float of Double
| Integer of Int32
| ParenEx of Expr
and Term =
| Times of Term * Factor
| Divide of Term * Factor
| Factor of Factor
and Expr =
| Plus of Expr * Term
| Minus of Expr * Term
| Term of Term
and Equation =
| Equation of Expr
EDIT
ich die Lexer Definition und den Code geschrieben haben, als auch den Parser fahren mit dem Verständnis, den Fehler zu helfen.
{
module Lexer
open System
open Parser
open Microsoft.FSharp.Text.Lexing
let lexeme lexbuf =
LexBuffer<char>.LexemeString lexbuf
}
// These are some regular expression definitions
let digit = ['0'-'9']
let whitespace = [' ' '\t' ]
let
newline = ('\n' | '\r' '\n')
rule tokenize = parse
| whitespace { tokenize lexbuf }
| newline { tokenize lexbuf }
// Operators
| "+" { PLUS }
| "-" { MINUS }
| "*" { ASTER }
| "/" { SLASH }
// Misc
| "(" { LPAREN }
| ")" { RPAREN }
// Numberic constants
| ['-']?digit+ { INT32 (Int32.Parse(lexeme lexbuf)) }
| ['-']?digit+('.'digit+)?(['e''E']digit+)? { FLOAT (Double.Parse(lexeme lexbuf)) }
// EOF
| eof { EOF }
Schließlich der Code, um den Parser zu fahren.
EDIT: Das optionale Minuszeichen im Lexer war das Problem. Nach dem Entfernen funktioniert das Beispiel wie erwartet.
Können Sie die Lexer-Definition auch posten? – Juliet
Es könnte funktionieren für binäre minus, aber funktioniert es für die unären? –
@ Román Als ich es kompilierte und ausführte, funktionierte nach dem Fixieren des optionalen Minus-Teils des Lexers sowohl das unäre als auch das binäre Minus wie erwartet. – Samsdram