Я предполагаю, что это теоретически, так как это домашняя работа, а не то, что вам действительно нужно кодировать на данный момент.(Ответ Кендрика охватывает подход кода)
Основная идея состоит в том, чтобы начать с вашей стартовой переменной BNF и попытаться выяснить, как ее расширить, применяя правила по одному, чтобы посмотреть, сможете ли вы придуматьВаша входная последовательность.
Для набора правил, подобного следующему:
(1) start: expression
(2) expression: expression '+' term
(3) | expression '-' term
(4) | term
(5) term: 'a'
(6) | 'b'
Учитывая выражение a + b - a
, вы бы пошли примерно так:
a.start
(дано)
b.expression
(1)
c.expression '-' term
(3)
д.expression '-' 'a'
(5)
e.expression '+' term '-' 'a'
(2)
ф.term '+' term '-' 'a'
(4)
г.'a' '+' term '-' 'a'
(5)
ч.'a' '+' 'b' '-' 'a'
(6)
Так вот, как вы делаете это по одному шагу за раз ... Теперь уловка в том, что вам нужно отслеживать все ваши вызовы правил.Итак, ваше настоящее дерево будет выглядеть примерно так:
start
| (b)
expression
/ | \ (c)
expression '-' term
/ | \ (e) | (d)
expression '+' term 'a'
| (f) | (h)
term 'b'
| (g)
'a'
Сначала это немного сложно, но как только вы действительно увидите, как это делается, его не так сложно подобрать.
Примечание: Некоторым людям легче работать задом наперед, начиная с вашего ввода и затем применяя правила в обратном порядке, чтобы попытаться найти ваше начальное выражение.Когда вы пишете парсер, вам неизбежно нужно будет следовать этому маршруту на каком-то уровне.
РЕДАКТИРОВАТЬ: Я перечислил все шаги выражения, используя строчные буквы выше, а затем показал, что каждый наборветви из дерева фактически соответствуют одному из приложений правил.Может или не может помочь.