3

F# アプリケーションでの文字列解析にFsLexFsYaccを使用しています。抽象構文ツリー (AST) の作成中に、パーサーは AST の作成方法を決定する必要があります (異なるツリーを作成する、例外をスローするなど)。パーサーの動作は、いくつかのパラメーターに依存する必要があります。

ここで、次のような宣言が許可されていることがわかりました。

%type < (context -> context) > toplevel

しかし、この構造を使用する方法を見つけることができず、プロジェクトのコンパイル中に"fsyacc.exe" がコード 1 で終了しました。"エラー

質問は次のとおりです: FsYacc での解析中にコンテキストパラメーターを使用することは可能ですか?

私が試したことの例:

%start startAst

%type < (bool -> MyAst) > startAst

%%   

startAst:
| MyAst EOF { 
                    (fun (x : bool) -> 
                        if x then 
                            MyAst.Type1 $1 
                        else 
                            MyAst.Type2) 
                }
...

そして、私は次のような使用法を期待していました:

let lexbuf = Lexing.LexBuffer<char>.FromString text
lexbuf |> Lexer.tokenize |> Parser.startAst (ctx: bool)

前もって感謝します

次の例外を更新し、fsyacc.exe の実行中にコール スタックが生成されます。

Unhandled Exception: System.Exception: more than one input given
   at FSharp.PowerPack.FsYacc.Driver.clo@67-5.Invoke(String x)
   at <StartupCode$fsyacc>.$Arg.findMatchingArg$cont@104-1(FSharpRef`1 cursor, FSharpFunc`2 other, String usageText, FSharpList`1 argSpecs, String arg, Unit unitVar)
   at <StartupCode$fsyacc>.$Arg.findMatchingArg@64(FSharpRef`1 cursor, String[] argv, FSharpFunc`2 other, String usageText, Int32 nargs, FSharpList`1 argSpecs, String arg, FSharpList`1 args)
   at Internal.Utilities.ArgParser.ParsePartial(FSharpRef`1 cursor, String[] argv, IEnumerable`1 arguments, FSharpOption`1 otherArgs, FSharpOption`1 usageText)
   at Internal.Utilities.ArgParser.Parse(IEnumerable`1 arguments, FSharpOption`1 otherArgs, FSharpOption`1 usageText)
   at <StartupCode$fsyacc>.$FSharp.PowerPack.FsYacc.Driver.main@()
4

1 に答える 1

2

長くなってしまい申し訳ありませんが、ようやくここまでたどり着きました。

FsYacc を書いた人 (F# チーム?) は、あなたがリンクしたページの彼ら自身のコメントでわかるように、関数を見逃していました。いくつかのバリエーションを試しましたが、これが機能する唯一のものです(注:これには、ファイルに伝播するファイル内の 、またはプロジェクト全体のいずれかが#nowarn "62"必要.fsyです.fs--nowarn:62

%{

open Ast

type ('a,'b) Fun = 'a -> 'b

%}

%start startAst

%token <string> MyAst
%token EOF

%type < (bool, MyAst) Fun > startAst

%%

startAst:
| MyAst EOF { (fun (x : bool) ->
                if x then
                    MyAst.Type1 $1
                else
                    MyAst.Type2) }

理由がわかりません (少なくとも今は、FsYacc のソースを確認する時間がありません)。

于 2012-07-06T09:20:55.327 に答える