Как разобрать список выражений с помощью менгира?

Вот мой текущий лексер и парсер для языка тигра Эндрю Аппеля (ocaml).

В настоящее время я пытаюсь поддерживать взаимные рекурсивные функции, но следующий код парсера не работает:

decs :
    | l = list(dec) { l }

dec :
    | t = nonempty_list(loc(tydec)) { S.TypeDec t }
    | v = loc(vardec) { S.VarDec v }
    | f = nonempty_list(loc(fundec)) { S.FunDec f }

%inline fundec :
    | Function fun_name = symbol LPar params = tyfields RPar
        Eq body = loc(exp) {
        S.{ fun_name; args = params; return_type = None; body }
    }
    | Function fun_name = symbol LPar params = tyfields RPar
        Colon result_type = symbol Eq body = loc(exp) {
        S.{ fun_name; args = params; return_type = Some result_type; body }
    }

Для маленького примера:

let
    function f1(x : int) : int =
        f2(x)

    function f2(x : int) : int =
        f1(x)

in
    f1 (0)
end

Я получаю два токена FunDec со списком из одного элемента вместо одного токена FunDec со списком, состоящим из двух элементов.

Как я могу использовать менгир для анализа списка fundec?

PS: я знаю, что могу объединить этот список во втором проходе, но я бы хотел, чтобы синтаксический анализатор сделал это за меня, если это возможно.


person Vinz    schedule 21.11.2017    source источник
comment
Не могли бы вы поместить весь соответствующий код в свой вопрос?   -  person PatJ    schedule 21.11.2017
comment
@PatJ Я добавил правило синтаксического анализа fundec, но я не уверен, что еще вы хотите. Я связал два соответствующих файла + код примера. Помещение всего файла парсера затмит вопрос, не так ли?   -  person Vinz    schedule 21.11.2017
comment
Просто политика сайта гласит, что любой пост должен быть автономным на случай, если ссылка не работает. Хотя github, вероятно, не исчезнет в ближайшее время, ваш репозиторий может исчезнуть.   -  person PatJ    schedule 21.11.2017
comment
Мой плохой, ты прав. Я думаю, что текущего содержания достаточно для вопроса, но я добавлю больше деталей, если кому-то потребуется какая-то конкретная часть.   -  person Vinz    schedule 21.11.2017


Ответы (1)


Поскольку для группы функций нет маркера, вам нужно объявить свой список самостоятельно с помощью нескольких конструкторов:

decs :
    | hd=nonempty_list(fundec) tl=decs_no_function { (S.Fundecs hd)::tl }
    | l=decs_no_function { l }

decs_no_functions :
    | hd=dec tl=decs { hd::tl } (* dec same as yours, without functions *)
    | { [] }

Здесь decs_no_functions соответствует «любому списку объявлений, который не начинается с функции». Обратите внимание, что одно объявление функции будет находиться внутри одного списка элементов.

person PatJ    schedule 21.11.2017
comment
Он хорошо работает для функций. Теперь я пытаюсь сделать то же самое, чтобы одинаково управлять типами функций и. Я подтвержу, когда у меня все получится ;) Спасибо за совет - person Vinz; 21.11.2017