本格的に 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