Самый простой подход - сделать каждое правило (или «производство») функцией. Это называется парсером «рекурсивный спуск».
Напишите две процедуры, которые заглядывают и получат следующий символ.
Это даст вам некоторый код, который выглядит примерно так (в псевдокоде):
// <sequent> ::= <lhs> # <rhs>
sequent()
lhs()
if peekchar() != '#' then error
else poundsign = nextchar()
rhs()
// <lhs> ::= <formulalist>| ε
lhs()
if peekchar() == EOF
return
else
formula()
// <rhs> ::= <formulalist>| ε
rhs()
if peekchar() == EOF
return
else
formulalist()
// <formulalist> ::= <formula>|<formula> , <formulalist>
formulalist()
formula()
if peekchar() is ','
comma = nextchar()
return formulalist()
// <formula> ::= <letter>| - <formula>| (<formula><infixop><formula>)
formula()
next = peekchar()
if next in A..Z
letter
else if next is -
minus_sign = nextchar()
return formula()
else
formula()
infixop()
formula()
// <infixop> ::= & | | | >
infixop()
c = nextchar()
if c not in &,|,> then error
// <letter> ::= A | B | ... | Z
letter()
c = nextchar()
if c not A..Z then error
и так далее, для каждого правила.
Основная идея:
- каждое правило является функцией
- в определенных точках функция заглядывает вперед, чтобы увидеть, что делать. например, formula() проверяет, является ли первый символ знаком минус.
Конвенция SO состоит в том, чтобы добавить тег домашней работы для домашней работы :-) –
Это не строго домашнее задание (он прямо не просит решения упражнения), он просит лучших практик, и он четко заявил что он помогает своему племяннику, поэтому я думаю, что это не требует метки домашней работы ... – Francesco