moonmile solutions 分室

ソフトウェア開発者の情報収集をリアルタイムで垂れ流し...という具合に行きます。

本格的に F# の二項演算子(中置記法)を導入してみる(2)

D:\git\fsharp\src\utils\prim-parsing.fs の 115行目あたりに

 

#if DEBUG

module Flags = 

    let mutable debug = true

#endif

 

があるので debug = true にしておくと、pars.fs の解析途中が見られる。

 

 0 value(state), state 4:op x y ;;

keyword:"op"

keyword:"x"

reduce popping 0 values/states, lookahead IDENT "op" goto state 33

1 value(state), state 4-33:reduce popping 0 values/states, lookahead IDENT "op" goto state 34

2 value(state), state 4-33-34:shift/consume input IDENT "op", shift to state 1642

3 value(state), state 4-33-34-1642:reduce popping 1 values/states, lookahead [TBC] IDENT "op" goto state 1691

3 value(state), state 4-33-34-1691:reduce popping 1 values/states, lookahead [TBC] IDENT "op" goto state 1698

3 value(state), state 4-33-34-1698:reduce popping 1 values/states, lookahead [TBC] IDENT "op" goto state 1236

3 value(state), state 4-33-34-1236:reduce popping 1 values/states, lookahead [TBC] IDENT "op" goto state 1211

3 value(state), state 4-33-34-1211:keyword:"y"

reduce popping 1 values/states, lookahead IDENT "x" goto state 1208

3 value(state), state 4-33-34-1208:shift/consume input IDENT "x", shift to state 1642

4 value(state), state 4-33-34-1208-1642:reduce popping 1 values/states, lookahead [TBC] IDENT "x" goto state 1691

4 value(state), state 4-33-34-1208-1691:reduce popping 1 values/states, lookahead [TBC] IDENT "x" goto state 1698

4 value(state), state 4-33-34-1208-1698:reduce popping 1 values/states, lookahead [TBC] IDENT "x" goto state 1236

4 value(state), state 4-33-34-1208-1236:reduce popping 1 values/states, lookahead [TBC] IDENT "x" goto state 1214

4 value(state), state 4-33-34-1208-1214:reduce popping 1 values/states, lookahead IDENT "y" goto state 1210

4 value(state), state 4-33-34-1208-1210:reduce popping 2 values/states, lookahead IDENT "y" goto state 1208

3 value(state), state 4-33-34-1208:shift/consume input IDENT "y", shift to state 1642

4 value(state), state 4-33-34-1208-1642:reduce popping 1 values/states, lookahead [TBC] IDENT "y" goto state 1691

4 value(state), state 4-33-34-1208-1691:reduce popping 1 values/states, lookahead [TBC] IDENT "y" goto state 1698

4 value(state), state 4-33-34-1208-1698:reduce popping 1 values/states, lookahead [TBC] IDENT "y" goto state 1236

4 value(state), state 4-33-34-1208-1236:reduce popping 1 values/states, lookahead [TBC] IDENT "y" goto state 1214

4 value(state), state 4-33-34-1208-1214:reduce popping 1 values/states, lookahead SEMICOLON_SEMICOLON goto state 1210

4 value(state), state 4-33-34-1208-1210:reduce popping 2 values/states, lookahead SEMICOLON_SEMICOLON goto state 1208

3 value(state), state 4-33-34-1208:reduce popping 1 values/states, lookahead SEMICOLON_SEMICOLON goto state 1085

3 value(state), state 4-33-34-1085:reduce popping 1 values/states, lookahead SEMICOLON_SEMICOLON goto state 35

3 value(state), state 4-33-34-35:reduce popping 3 values/states, lookahead SEMICOLON_SEMICOLON goto state 21

1 value(state), state 4-21:shift/consume input SEMICOLON_SEMICOLON, shift to state 16

2 value(state), state 4-21-16:reduce popping 1 values/states, lookahead [TBC] SEMICOLON_SEMICOLON goto state 22

2 value(state), state 4-21-22:reduce popping 2 values/states, lookahead [TBC] SEMICOLON_SEMICOLON goto state 6

1 value(state), state 4-6:reduce popping 1 values/states, lookahead [TBC] SEMICOLON_SEMICOLON goto state 5

1 value(state), state 4-5:val it : int = 30

>

Parser: interpret tables

0 value(state), state 4:

 ここの state 4-33-34-1208 が yacc の解析スタックなのだが、この番号は  fyacc が生成する _fsyacc_reductions に対応している。コンパイル時に番号が決まるので、元の pars.fsy に書かれている構文解析と対応がこのままではできない。

localBindings: 

  | attr_localBinding moreLocalBindings 

      { let (moreBindings, moreBindingRanges) = List.unzip $2

        let moreLocalBindingsLastRange = if moreBindingRanges.IsEmpty then None else Some (List.last moreBindingRanges)

        match $1 with 

        | Some (localBindingRange,attrLocalBindingBuilder) -> 

           let lastRange = 

               match moreLocalBindingsLastRange with 

               | None -> localBindingRange 

               | Some m -> m

           Some lastRange, (fun attrs vis mLetKwd -> attrLocalBindingBuilder attrs vis mLetKwd true ::  moreBindings)

        | None -> 

           moreLocalBindingsLastRange, (fun _attrs _vis _letm -> moreBindings) }

 

 これを変換した後に、以下のようなラムダ式になることは分かったので、state no(配列の番号)と "localBindings" の文字列を突き合わせる手段があれば、解析が進む。

        (fun (parseState : Internal.Utilities.Text.Parsing.IParseState) ->

            let _1 = (let data = parseState.GetInput(1) in (Microsoft.FSharp.Core.Operators.unbox data : 'attr_localBinding)) in

            let _2 = (let data = parseState.GetInput(2) in (Microsoft.FSharp.Core.Operators.unbox data : 'moreLocalBindings)) in

            Microsoft.FSharp.Core.Operators.box

                (

                   (

# 2189 "..\pars.fsy"

                             let (moreBindings, moreBindingRanges) = List.unzip _2

                             let moreLocalBindingsLastRange = if moreBindingRanges.IsEmpty then None else Some (List.last moreBindingRanges)

                             match _1 with 

                             | Some (localBindingRange,attrLocalBindingBuilder) -> 

                                let lastRange = 

                                    match moreLocalBindingsLastRange with 

                                    | None -> localBindingRange 

                                    | Some m -> m

                                Some lastRange, (fun attrs vis mLetKwd -> attrLocalBindingBuilder attrs vis mLetKwd true ::  moreBindings)

                             | None -> 

                                moreLocalBindingsLastRange, (fun _attrs _vis _letm -> moreBindings) 

                   )

# 2189 "..\pars.fsy"

                 : 'localBindings));

 

 _fsyacc_reductions の実体は、tables.reductions になる。ここの actionValue action が int 型を返して、reductions 配列から拾ってくる。

                ) elif kind = reduceFlag then

                    let prod = actionValue action                                     

                    let reduction = reductions.[prod]                                                             

                    let n = int tables.reductionSymbolCounts.[prod]

                       // pop the symbols, populate the values and populate the locations                              

#if DEBUG

                    if Flags.debug then Console.Write("reduce popping {0} values/states, lookahead {1}", n, report haveLookahead lookaheadToken);

#endif