Разрешение неоднозначностей выполняется в два прохода:
- Первый (от листьев к корню) собирает возможные интерпретации и поднимается к конструкции названной в ARM complete context (См [http://www.ada-auth.org/standards/12aarm/html/AA-8-6.html ARM 8.6 (4)]). Там выбирается одна из возможных интерпретаций всего поддерева.
- Второй проход (в обратном направлении от complete context к листьям) распространяет информацию о выбранной интерпретации
Соответственно нужны следующие абстракции:
- Interpretation (Meaning?) - возможная интерпретация
- Interpretation_Set - множество возможных интерпретаций
- Interpretation_Set_Tuple - вектор/кортеж из Interpretation_Set собирает в единое целое несколько независимых множеств интерпретаций, например ассоциация в агрегате
A | B => C
нужно собрать три множества интерпретаций, которые будут трактоваться в зависимости от контекста. - Interpretation_Set_Tuple_List - вектор таких векторов, например для обобщения списка ассоциаций,
A | B => C, D => 1
Сами интерпретации бывают такими (в скобках указаны параметры интерпретации):
- Symbol (идентификатор) - когда известен только идентификатор
- Defining_Name (ссылка на имя)- когда известно имя обозначаемое конструкцией
- Expression (тип выражения) - когда известен тип выражения
- Expression_Category (категория типов)- когда известен лишь категория типа выражения, например строковый тип как результат строчного литерала
"Hello"
- Attr_Function (атрибут) - интерпретация функций обозначаемых атрибутами, например
Integer'Image
- Placeholder () - интерпретация-заменитель, используется там, где должна быть интерпретация по синтаксису, но ее нет, например
1 => <>
для бокса
От спускаемых интерпретациях нужно следующее:
- до identifier, operator_symbol должна дойти интерпретация у которой можно взять Defining_Name
- для конструкций с несколькими потомками нужно спускать список с элементами соответствующими структуре элемента, например для selected_component нужно иметь элементы для prefix и для selector
- для конструкций-списков (возвращающих Tuple, Tuple_List) ожидается списки спускаемых интерпретациях с совпадающим кол-вом элементов
- нужно как-то спускать информацию о типе
Для некоторых конструкций с дочерними элементами, при построении возможных интерпретаций можно выбрать по одной из возможных интерпретаций для каждого дочернего элемента конструкции и составить список соответствующих спускаемые интерпретаций. Если прикрепить этот список к интерпретации, то на обратном проходе достаточно будет выбрать готовые спускаемые интерпретации из списка. К примеру вызов функции F(X)
, перебрав все интерпретации F, можно выбрать все соответствующие профилю F интерпретацию X и сформировать "возможную интерпретацию" Expression, запомнив в ней выбранные интерпретации F и X. На обратном проходе получив данную интерпретацию для F(X), достаточно взять из нее сохраненные интерпретации F и X, чтобы спустить их в дочерние элементы.
Так можно сделать не для всех конструкций. Интерпретации Symbol, Expression_Category подразумевают, что итоговая интерпретация не известна. Соответственно выбирать спускаемую интерпретацию приходится на обратном проходе, получив Expression или Defining_Name сверху. В качестве примера можно рассмотреть агрегат записи (A => B)
. Единственная возможная интерпретация будет Expression_Category с категорией "тип запись". На обратном проходе мы получаем Expression с указанием типа выражения, можем выбрать по символу A имя компонента записи, сформировать Defining_Name и передать его элемент A. Аналогично для B мы создадим интерпретацию Expression с типов компоненты A.