Использование типов записей в FSYACC
В 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
Каков правильный синтаксис для "любого" производства в последних двух строках?
1 ответ
Разве вы не имеете в виду 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}
в отличие от просто {x = $2; y = $3}
,