Здравствуйте, palm mute, Вы писали:
PM>2. Парсер: из списка токенов строим AST. Тебе надо определить тип данных, представляющий синтаксическую структуру выражения:
PM>PM>type Exp = Const of float | Plus of (Exp * Exp) | ...
PM>
Только наверное, чтобы не городить варианты,
type Operator = Plus|Minus|Mult|Div|...| Custom of string
type Expr = Literal of float | Identifier of string | Unary of (Operator*Expr) | Binary of (Operator*Expr*Expr)
PM>3. Собственно, интерпретатор. Это будет функция типа Exp -> float. Эскиз:
unop : Operator -> (float -> float)
binop : Operator -> (float -> float -> float)
unop o = match o with
| Plus -> (+.) 0
| Minus -> (-.) 0
| _ -> error "Unexpected unary operator"
binop o = match o with
| Plus -> (+.)
| Minus -> (-.)
| Mult -> (*.)
| Div -> (/.)
| _ -> error "Unexpected binary operator"
eval expr = match expr with
| Literal c -> c
| Identifier n -> lookupValueSomewhereElse n
| Unary (o,x) -> unop o (eval x)
| Binary (o,x,y) -> binop o (eval x) (eval y)
Кстати говоря, можно не интерпретатор сделать, а генератор функции.
ast2fun : Expr -> (Set of string) -> (Set of string)*(Map of string*float -> float)
(* на входе выражение и множество уже найденных переменных *)
(* на выходе - множество входящих в него переменных *)
(* и функция, принимающая таблицу значений *)
(* типы Set и Map - вымышленные. смотрите их аналоги в документации *)
ast2funS e s = match e with
| Literal c -> (s, const c)
| Identifier n ->
let sn = append s n in
let f m = lookup m n in
(sn, fn)
| Unary (o,ex) ->
let fo = unop o in
let (sx,fx) = ast2funS ex s in
let f m = fo (fx m) in
(sx, f)
| Binary (o,ex,ey) ->
let fo = binop o in
let (sx,fx) = ast2funS ex s in
let (sy,fy) = ast2funS ey sx in
let f m = fo (fx m) (fy m) in
(sy, f)
ast2fun e =
let (_,f) = ast2funS e emptySet
in f
Хаскелльщики без труда разглядят здесь монаду State (и даже Writer) в генераторе и привет от монады Reader в его выходной функции.
ЗЫ. Если налажал в синтаксисе, извиняйте. Давно не камлал с этим бубном.
... << RSDN@Home 1.2.0 alpha rev. 655>>