私はF#でコンパイラを作成しようとしており、F#powerpackに付属のFslexとFsyaccツールを見ています。私が理解しようとしている外部ビルドツールを処理するサンプルプロジェクトがあります。それはhereをダウンロードすることができます。この例は私のためにコンパイルされて実行されますが、文法には微妙な誤りがあると思います。文法は、式を解析するためのドラゴンブックで見たものと似ていて、私はそれを見つけ出す経験がないので、微妙に言います。正しく入力4 * 5-3 23.Fsyaccの文法のエラー?
に評価
入力 "* 5 4 + 3" は、しかし、解析エラーが発生します。これはFsyaccによって生成されたコードのエラーです。
Fsyaccの情報をよりよく理解し、信頼できるように、問題の原因をより深く理解していただきありがとうございます。私は以下の* .fsyファイルを投稿しました。
// 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) }
そしてここでASTのデータ型の定義が
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
私は、字句解析の定義およびエラーの理解を助けるためにだけでなく、パーサーを駆動するためのコードを掲載しています。
{
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 }
最後に、パーサーを駆動するコード。
// This project type requires the F# PowerPack at http://fsharppowerpack.codeplex.com/releases
// Learn more about F# at http://fsharp.net
// Original project template by Jomo Fisher based on work of Brian McNamara, Don Syme and Matt Valerio
// This posting is provided "AS IS" with no warranties, and confers no rights.
open System
open Microsoft.FSharp.Text.Lexing
open Ast
open Lexer
open Parser
/// Evaluate a factor
let rec evalFactor factor =
match factor with
| Float x -> x
| Integer x -> float x
| ParenEx x -> evalExpr x
/// Evaluate a term
and evalTerm term =
match term with
| Times (term1, term2) -> (evalTerm term1) * (evalTerm term2)
| Divide (term1, term2) -> (evalTerm term1)/(evalTerm term2)
| Factor fact -> evalFactor fact
/// Evaluate an expression
and evalExpr expr =
match expr with
| Plus (expr1, expr2) -> (evalExpr expr1) + (evalExpr expr2)
| Minus (expr1, expr2) -> (evalExpr expr1) - (evalExpr expr2)
| Term term -> evalTerm term
/// Evaluate an equation
and evalEquation eq =
match eq with
| Equation expr -> evalExpr expr
printfn "Calculator"
let rec readAndProcess() =
printf ":"
match Console.ReadLine() with
| "quit" ->()
| expr ->
try
printfn "Lexing [%s]" expr
let lexbuff = LexBuffer<char>.FromString(expr)
printfn "Parsing..."
let equation = Parser.start Lexer.tokenize lexbuff
printfn "Evaluating Equation..."
let result = evalEquation equation
printfn "
Result: %s" (result.ToString())
with ex ->
printfn "Unhandled Exception: %s" ex.Message
readAndProcess()
readAndProcess()
編集:レクサーのオプションのマイナス記号が問題でした。それを取り除いた後、サンプルは期待通りに機能します。
レクサー定義も投稿できますか? – Juliet
バイナリマイナスでも動作するかもしれませんが、単項式では機能しますか? –
@Románコンパイルして実行したとき、レクサーのオプションのマイナス部分を修正した後、単項マイナスとバイナリマイナスの両方が期待どおりに機能しました。 – Samsdram