LALR
Реализация: LALR-by-SLR.
- LR(0) item sets & translation table
- Extended grammar
- FIRST sets
- FOLLOW sets
- Action & goto table
- initialize
- gotos
- shifts
- reductions
Item set collection
Item
Item (элемент) — это правило грамматики с позицией.
Позиция как правило обозначается точкой.
- означает " вот-вот встретится"
- означает " только что встретился"
Алгоритм CLOSURE
Если — множество элементов грамматики , тогда (замыкание) — это множество элементов, построенное из по следующим шагам:
- Множество инициализируется всеми элементами из .
- Если элемент находится во множестве (т.е. непосредственно за точкой следует нетерминал) и — правило грамматики, то во множество добавляется элемент , если его ещё нет.
- Предыдущий шаг повторяется до тех пор, пока добавляются новые элементы.
Множество элементов, которые были добавлены на этапе инициализации, называется ядром.
Пример
Грамматика:
Начальный набор:
Алгоритм GOTO
Если — множество элементов, а — символ грамматики, то определяется как замыкание таких элементов , что элемент принадлежит .
Этот алгоритм используется для определения переходов между состояниями LR(0) автомата. Набор состояний конечного автомата соответствует множествам элементов, а GOTO определяет переход из при вводе .
Расширенная грамматика
Обозначения:
- — переход от к через подачу на вход
- — переход от к через подачу на вход
- — переход от к через подачу на вход
Общий шаблон:
Для пустого правила конечная точка это первая цифра:
FIRST и FOLLOW
Множество FIRST для символа в КС-грамматике — это множество терминальных символов, которые могут появиться в начале строк, выводимых из символа.
Множество FOLLOW для символа в КС-грамматике — это множество терминальных символов, которые могут следовать непосредственно за данным символов в выводе (развёртывании).
Алгоритм построения FIRST
# T - terminals
# NT - non-terminals
# P - rules in grammar
for a in [*T, EOF, EPS]:
FIRST(a) = a
for A in NT:
FIRST(A) = set()
while FIRST changes:
for A -> b[1..k] in P:
rhs = FIRST(b[1]) - { EPS }
i = 1
# adding first for eps-gen symbols
while EPS in FIRST(b[i]) and i <= k - 1:
rhs |= FIRST(b[i + 1]) - { EPS }
i += 1
if i == k and EPS in FIRST(b[k]):
rhs |= { EPS }
FIRST(A) |= rhs
Алгоритм построения FOLLOW
# NT - non-terminals
# P - rules in grammar
for A in NT:
FOLLOW(A) = set()
FOLLOW(S) = { EOF }
while FOLLOW changes:
for A -> b[1..k] in P:
trailer = FOLLOW(A)
for i in range(k, 0, -1):
if b[i] in NT:
FOLLOW(b[i]) |= trailer
if EPS in FIRST(b[i]):
trailer |= FIRST(b[i]) - { EPS }
else:
trailer = FIRST(b[i])
else:
trailer = FIRST(b[i])
Генерация таблицы
Разрешение конфликтов:
- shift/reduce shift
- reduce/reduce reduce по более длинному правилу
Проблемные правила
Для правила ниже возникает неоднозначность, которую нельзя разрешить имея lookahead в один токен.
params : '(' (param (',' param)* ','?)? ')' ;
Решением как правило является преобразование грамматики.
params : '(' param (',' param)* ')' | '(' (param ',')* ')' ;
Очень подробное описание на примере простой грамматики:
https://web.cs.dal.ca/~sjackson/lalr1.html