Допустим, я создаю синтаксический анализатор для предметно-ориентированного языка в F #.
Я определил дискриминационное объединение для представления выражений:
type Expression =
| Equality of Expression*Expression
| NonEquality of Expression*Expression
| Or of Expression*Expression
| And of Expression*Expression
| If of Expression*Expression
| IfElse of Expression*Expression*Expression
| Bool of bool
| Variable of string
| StringLiteral of string
Теперь я создал AST типа Expression
и хочу сгенерировать для него код.
У меня есть одна функция, которая делает вывод типа и проверку типа выражения.
Это определено как
let rec InferType expr =
match expr with
| Equality(e1,e2) -> CheckTypes (InferType e1) (InferType e2)
| Or(e1,e2) -> CheckTypes (InferType e1) (InferType e2)
| And(e1,e2) -> CheckTypes (InferType e1) (InferType e2)
...
И у меня есть еще одна функция для генерации кода, который следует похожему шаблону: взять выражение, написать операторы соответствия шаблону для каждого элемента в объединении.
Мой вопрос: это идиоматический способ сделать это в F #?
Мне кажется, что было бы чище, если бы каждый член союза определил свои собственные InferType
и GenerateCode
локально с ним.
Если бы я использовал C #, я бы определил некоторый абстрактный базовый класс с именем Expression
с виртуальными методами для InferType
и GenerateCode
, а затем переопределил их в каждом подклассе.
Есть ли другой способ сделать это?