大きな差別された組合の木を読みやすい形に変換するにはどうすればよいですか?
-
26-09-2019 - |
質問
次のタイプは明らかに非常に大きいため、これを読みやすいフォームに変換するためにコードを手動で書き込むことは退屈です。読みやすい形でツリーを表示する最も簡単な方法を知りたいと思います。
type Element =
| Nil
| Token of Token
| Expression of Element * Element
| ExpressionNoIn of Element * Element
| AssignmentExpression of Element * AssignmentOperator * Element
| AssignmentExpressionNoIn of Element * AssignmentOperator * Element
| ConditionalExpression of Element * Element * Element
| ConditionalExpressionNoIn of Element * Element * Element
| LogicalORExpression of Element * Element
| LogicalORExpressionNoIn of Element * Element
| LogicalANDExpression of Element * Element
| LogicalANDExpressionNoIn of Element * Element
| BitwiseORExpression of Element * Element
| BitwiseORExpressionNoIn of Element * Element
| BitwiseXORExpression of Element * Element
| BitwiseXORExpressionNoIn of Element * Element
| BitwiseANDExpression of Element * Element
| BitwiseANDExpressionNoIn of Element * Element
| EqualityExpression of Element * EqualityOperator * Element
| EqualityExpressionNoIn of Element * EqualityOperator * Element
| RelationalExpression of Element * RelationalOperator * Element
| RelationalExpressionNoIn of Element * RelationalOperator * Element
| ShiftExpression of Element * BitwiseShiftOperator * Element
| AdditiveExpression of Element * AdditiveOperator * Element
| MultiplicativeExpression of Element * MultiplicativeOperator * Element
| UnaryExpression of UnaryOperator * Element
| PostfixExpression of Element * PostfixOperator
| MemberExpression of Element * Element
| Arguments of Element * Element
| ArgumentList of Element
| CallExpression of Element * Element
| NewExpression of NewOperator * Element
| LeftHandSideExpression of Element
| PrimaryExpression of Element
| ObjectLiteral of Element
| PropertyNameAndValueList of Element * Element
| PropertyAssignment of Element * Element * Element
| PropertyName of Element
| PropertySetParameterList of Element
| ArrayLiteral of Element * Element
| Elision of Element * Element
| ElementList of Element * Element * Element
| Statement of Element
| Block of Element
| StatementList of Element * Element
| VariableStatement of Element
| VariableDeclarationList of Element * Element
| VariableDeclarationListNoIn of Element * Element
| VariableDeclaration of Element * Element
| VariableDeclarationNoIn of Element * Element
| Initialiser of Element
| InitialiserNoIn of Element
| EmptyStatement
| ExpressionStatement of Element
| IfStatement of Element * Element * Element
| IterationStatement of Element * Element * Element * Element
| ContinueStatement of Element
| BreakStatement of Element
| ReturnStatement of Element
| WithStatement of Element * Element
| SwitchStatement of Element * Element
| CaseBlock of Element * Element * Element
| CaseClauses of Element * Element
| CaseClause of Element * Element
| DefaultClause of Element
| LabelledStatement of Element * Element
| ThrowStatement of Element
| TryStatement of Element * Element * Element
| Catch of Element * Element
| Finally of Element
| DebuggerStatement
| FunctionDeclaration of Element * Element * Element
| FunctionExpression of Element * Element * Element
| FormalParameterList of Element * Element
| FunctionBody of Element
| SourceElement of Element
| SourceElements of Element * Element
| Program of Element
これがどのように表示されるかの例です。 (少し前に作成したので、少し違っています。)
<Expression>
<AssignmentExpression>
<ConditionalExpression>
<LogicalORExpression>
<LogicalORExpression>
<LogicalANDExpression>
<BitwiseORExpression>
<BitwiseXORExpression>
<BitwiseANDExpression>
<EqualityExpression>
<EqualityExpression>
<RelationalExpression>
<ShiftExpression>
<AdditiveExpression>
<MultiplicativeExpression>
<MultiplicativeExpression>
<UnaryExpression>
<PostfixExpression>
<LeftHandSideExpression>
<NewExpression>
<MemberExpression>
<PrimaryExpression>
<TokenNode Value="i" Line="9" Column="13" />
</PrimaryExpression>
</MemberExpression>
</NewExpression>
</LeftHandSideExpression>
</PostfixExpression>
</UnaryExpression>
</MultiplicativeExpression>
<TokenNode Value="%" Line="9" Column="15" />
<UnaryExpression>
<PostfixExpression>
<LeftHandSideExpression>
<NewExpression>
<MemberExpression>
<PrimaryExpression>
<TokenNode Value="3" Line="9" Column="17" />
</PrimaryExpression>
</MemberExpression>
</NewExpression>
</LeftHandSideExpression>
</PostfixExpression>
</UnaryExpression>
</MultiplicativeExpression>
</AdditiveExpression>
</ShiftExpression>
</RelationalExpression>
</EqualityExpression>
<TokenNode Value="===" Line="9" Column="19" />
<RelationalExpression>
<ShiftExpression>
<AdditiveExpression>
<MultiplicativeExpression>
<UnaryExpression>
<PostfixExpression>
<LeftHandSideExpression>
<NewExpression>
<MemberExpression>
<PrimaryExpression>
<TokenNode Value="0" Line="9" Column="23" />
</PrimaryExpression>
</MemberExpression>
</NewExpression>
</LeftHandSideExpression>
</PostfixExpression>
</UnaryExpression>
</MultiplicativeExpression>
</AdditiveExpression>
</ShiftExpression>
</RelationalExpression>
</EqualityExpression>
</BitwiseANDExpression>
</BitwiseXORExpression>
</BitwiseORExpression>
</LogicalANDExpression>
</LogicalORExpression>
<TokenNode Value="||" Line="9" Column="25" />
<LogicalANDExpression>
<BitwiseORExpression>
<BitwiseXORExpression>
<BitwiseANDExpression>
<EqualityExpression>
<EqualityExpression>
<RelationalExpression>
<ShiftExpression>
<AdditiveExpression>
<MultiplicativeExpression>
<MultiplicativeExpression>
<UnaryExpression>
<PostfixExpression>
<LeftHandSideExpression>
<NewExpression>
<MemberExpression>
<PrimaryExpression>
<TokenNode Value="i" Line="9" Column="28" />
</PrimaryExpression>
</MemberExpression>
</NewExpression>
</LeftHandSideExpression>
</PostfixExpression>
</UnaryExpression>
</MultiplicativeExpression>
<TokenNode Value="%" Line="9" Column="30" />
<UnaryExpression>
<PostfixExpression>
<LeftHandSideExpression>
<NewExpression>
<MemberExpression>
<PrimaryExpression>
<TokenNode Value="5" Line="9" Column="32" />
</PrimaryExpression>
</MemberExpression>
</NewExpression>
</LeftHandSideExpression>
</PostfixExpression>
</UnaryExpression>
</MultiplicativeExpression>
</AdditiveExpression>
</ShiftExpression>
</RelationalExpression>
</EqualityExpression>
<TokenNode Value="===" Line="9" Column="34" />
<RelationalExpression>
<ShiftExpression>
<AdditiveExpression>
<MultiplicativeExpression>
<UnaryExpression>
<PostfixExpression>
<LeftHandSideExpression>
<NewExpression>
<MemberExpression>
<PrimaryExpression>
<TokenNode Value="0" Line="9" Column="38" />
</PrimaryExpression>
</MemberExpression>
</NewExpression>
</LeftHandSideExpression>
</PostfixExpression>
</UnaryExpression>
</MultiplicativeExpression>
</AdditiveExpression>
</ShiftExpression>
</RelationalExpression>
</EqualityExpression>
</BitwiseANDExpression>
</BitwiseXORExpression>
</BitwiseORExpression>
</LogicalANDExpression>
</LogicalORExpression>
</ConditionalExpression>
</AssignmentExpression>
</Expression>
解決
すべての組合ケースをリストする必要がない一般的な組合処理コードを作成する場合は、おそらくF#Reflection APIを使用する必要があります。これが簡単な例です。
formatUnion
関数はf#反射を使用します。タイプパラメーターを想定しています 'T
ユニオンタイプと使用です GetUnionFields
現在のケースと議論の名前を含むタプルを取得する。現在のケース名を印刷し、すべての引数を反復します。引数の一部がタイプの値である場合 'T
(それが再帰的な組合であることを意味します)、私たちは価値に関する情報を再帰的に印刷します。
let rec formatUnion indent (value:'T) = //'
// Get name and arguments of the current union case
let info, args = Reflection.FSharpValue.GetUnionFields(value, typeof<'T>) //'
// Print current name (with some indentation)
printfn "%s%s" indent info.Name
for a in args do
match box a with
| :? 'T as v ->
// Recursive use of the same union type..
formatUnion (indent + " ") v
| _ -> ()
次の例では、非常に単純な組合価値で関数を実行します。
type Element = | Nil | And of Element * Element | Or of Element * Element
formatUnion "" (And(Nil, Or(Nil, Nil)))
// Here is the expected output:
// And
// Nil
// Or
// Nil
// Nil
サイドノートとして、私はあなたが訴訟を起こすことによってあなたの差別された組合をほぼ単純化できると思います BinaryOperator
と UnaryOperator
すべての要素タイプを明示的にリストする代わりに(1つの追加パラメーターを使用)。その場合、おそらく機能を直接実装できます。これは非常に簡単だからです。何かのようなもの:
type BinaryOperator = LogicalOr | LogicalAnd | BitwiseOr // ...
type UnaryOperator = Statement | Block | Initializer // ...
type Element =
| BinaryOperator of BinaryOperator * Element * Element
| UnaryOperator of UnaryOperator * Element
所属していません StackOverflow