Давайте напишем одно из определений более традиционным способом:
parseExpr ("+":rs) = let (e1, r1) = parseExpr rs -- recursive call #1
(e2, r2) = parseExpr r1 -- recursive call #2
in (Sum e1 e2, r2)
Учитывая список, который начинается с "+"
, мы сначала рекурсивно анализируем токены, следующие за "+"
;полученному выражению присваивается имя e1
, а неиспользованному суффиксу rs
присваивается имя r1
. Мы повторяем процесс, анализируя r1
, чтобы получить выражение e2
и оставшиеся входные данные r2
. Таким образом, мы можем построить значение Sum
, используя два подвыражения e1
и e2
, и передать обратно r2
, чтобы наш вызывающий мог выполнить синтаксический анализ.
Используя ваш пример,
-- Step 1
parseExpr ["+","4","*","8","-","5"]
= let (e1, r1) = parseExpr ["4","*","8","-","5"]
(e2, r2) = parseExpr r1
in (Sum e1 e2, r2)
Прежде чем мы сможем сделать что-то еще, мы должны оценить первый рекурсивный вызов
-- Step 2
parseExpr ["4","*","8","-","5"] = (Tall 4, ["*","8","-","5"])
Теперь мы можем подключить этот результат обратно к шагу 1
-- Step 3
parseExpr ["+","4","*","8","-","5"]
= let (e1, r1) = (Tall 4, ["*","8","-","5"])
(e2, r2) = parseExpr r1
in (Sum e1 e2, r2)
-- Step 4
parseExpr ["+","4","*","8","-","5"]
= let (e2, r2) = parseExpr ["*","8","-","5"]
in (Sum (Tall 4) e2, r2)
И так далее. ...