1

在 FSYACC 中,通常会有导致元组的终端。但是,为方便起见,我想改用记录类型。例如,如果我的抽象语法树 (AbstractSyntaxTree.fsl) 中有以下内容:

namespace FS
module AbstractSyntaxTree =

 type B = { x : int; y : int }

 type Either = 
      | Record of B
      | Tuple of int * string

 type A =
     | Int of int
     | String of string
     | IntTuple of Either

我不清楚 FSYACC (parser.fsy) 中的正确语法,因为如果我使用:

%start a
%token <string> STRING
%token <System.Int32> INT
%token ATOMTOKEN TUPLETOKEN EOF
%type < A > a

%%

a:
    | atomS { $1 }
    | atomI { $1 }
    | either { $1 }

atomI:
    | ATOMTOKEN INT   { Int($2) }

atomS:
    | ATOMTOKEN STRING { String($2)  }

either:
    | TUPLETOKEN INT INT { Record {x=$2;y=$3} } // !!!
    | TUPLETOKEN TUPLETOKEN INT STRING { Tuple( $3, $4) } // !!!

我希望推断出类型 B 和元组。但是,FSYACC 对标有“!!!”的两行都给出了错误:

This expression was expected to have type  A but here has type Either

最后两行的“任一”生产的正确语法是什么?

4

1 回答 1

2

你不是说IntTuple($2, $3)反对B($2, $3)吗?我会尝试IntTuple{x=$2; y=$3}

编辑:这有效:

module Ast

type B = { x : int; y : int }
type A =
    | Int of int
    | String of string
    | IntTuple of B

%{

open Ast

%}

%start a
%token <string> STRING
%token <System.Int32> INT
%token ATOMTOKEN TUPLETOKEN 
%type < Ast.A > a


%%

a:
    | atom { $1 }
    | tuple { $1 }

atom:
    | ATOMTOKEN INT   { Int($2) }
    | ATOMTOKEN STRING { String($2) }

tuple:
    | TUPLETOKEN INT INT { IntTuple {x = $2; y = $3} }

编辑 2:请注意,该行%type < Ast.A > a要求您的非终端a类型为Ast.A. 因此,由于您tuple直接使用非终端,因此tuple需要类型为Ast.A. 因此,您必须将记录包装在 中IntTuple,因此语法IntTuple {x = $2; y = $3}与 just 相对{x = $2; y = $3}

于 2015-04-16T14:00:07.607 回答