На самом деле, это немного упрощенно, чтобы иметь смысл как синтаксический анализатор. Все это можно записать в виде простого регулярного выражения: «[ab]? C». Если вы действительно настаиваете на написании парсера, код может выглядеть примерно так:
Boolean parseA() {
// an A is a B followed by a `c`:
return parseB() && (get_token() == Token.c);
}
Boolean parseB {
// Get a token.
// If it's an `a` or a `b`, consume it.
// Otherwise, throw it back (match null string by consuming nothing).
// Either way, return true (successful match).
//
token current_token = get_token();
if (token != Token.a && token != Token.b)
push_back(current_token);
return true;
}
Изменить (в ответ на комментарий к другому ответу): Нет, когда вы соответствуете B, вы должны , а не искать Token.c. Что касается B, есть три варианта: сопоставить «a», сопоставить «b» или вообще ничего не сопоставить. Затем часть, которая анализирует A, проверяет наличие B, а затем Token.c.
Например, если вам нужно изменить грамматику на что-то вроде:
A :: = B C
B :: = a | б | ε
C :: = c | д
Поскольку «B» по-прежнему имеет то же определение, вы должны не изменять его только потому, что некоторые другие определения изменены. Аналогично, вы можете добавить к грамматике, чтобы разрешить (например) произвольную строку B, за которой следует C.