Параметры LOOKAHEAD - это количество токенов по умолчанию, которое будет использоваться для принятия решения о том, какой путь будет выбран в каждой точке выбора.
Эта конфигурация необходима для разрешения конфликтов выбора, поскольку javacc не поддерживает возврат.
Значение по умолчанию для опции LOOKAHEAD
равно 1. Поэтому важно написать грамматика, которая подходит для LOOKAHEAD = 1, означая, что выбор будет решен, если заглянуть на один токен вперед.
Например:
Поскольку JavaCC является анализатором LL, если левый токен производственного правила повторяется, возникает конфликт выбора:
void PhoneNumber() : {} {
(LocalNumber() | CountryNumber()) <EOF>
}
void LocalNumber() : {} {
AreaCode() "-" <FOUR_DIGITS>
}
void CountryNumber() : {} {
AreaCode() "-" <THREE_DIGIT> "-" <FOUR_DIGITS>
}
void AreaCode() : {} {
<THREE_DIGIT>
}
Обратите внимание, что и CountryNumber
, и LocalNumber
начинаются с терминала <THREE_DIGIT>
, который вызывает конфликт выбора,
Это можно переписать с помощью подхода, называемого "левым факторингом".
void PhoneNumber() : {} {
AreaCode() "-" (LocalNumber() | CountryNumber()) <EOF>
}
void LocalNumber() : {} {
<FOUR_DIGITS>
}
void CountryNumber() : {} {
<THREE_DIGIT> "-" <FOUR_DIGITS>
}
void AreaCode() : {} {
<THREE_DIGIT>
}
Для случая, когда это невозможно, используется спецификация Lookahead
Спецификации Lookahead бывают пяти типов:
- Несколько токенов LOOKAHEAD
- Syntacti c LOOKAHEAD
- Комбинация нескольких токенов и Syntacti c LOOKAHEAD
- Semanti c LOOKAHEAD
- Вложенный Lookahead
Несколько токенов LOOKAHEAD
Это можно использовать с целым числом, переданным в методе LOOKAHEAD (k). Это можно сделать,
Syntacti c LOOKAHEAD
В спецификации просмотра Syntacti c используется конструкция syntacti c в качестве распознавателя выбора.
При указании синтаксического предпросмотра без нескольких токенов на самом деле вы указываете syntacti c предвидение с бесконечным несколькими токенами.
Например: LOOKAHEAD (2147483647, LocalNumber ( ))
void PhoneNumber() : {} {
(
LOOKAHEAD(("A"|"B")+ AreaCode() "-" <FOUR_DIGITS>) LocalNumber()
| CountryNumber()
) <EOF>
}
Комбинация нескольких токенов и Syntacti c LOOKAHEAD
Таким образом, мы могли бы ожидать ограниченное количество токенов до тех пор, пока syntacti c Взгляд будет удовлетворен в рамках указанного выбора.
void PhoneNumber() : {} {
(
LOOKAHEAD(10, ("A"|"B")+ AreaCode() "-" <FOUR_DIGITS>) LocalNumber()
| CountryNumber()
) <EOF>
}
Семанти c СООБЩЕНИЕ
Семанти c упреждающее ожидание включает в себя встраивание логического выражения Java в грамматику в точке выбора.
Если логическое выражение оценивается как true, выбрано текущее расширение.
void PhoneNumber() : {} {
(
LOOKAHEAD({getToken(1).image.equals("123")})
KeysvilleNumber()
| FarmvilleNumber()
) <EOF>
}
Вложенный L ookahead
Вложенный lookahead происходит, когда одна директива lookahead перекрывает другую. В JavaCC вложенный syntacti c lookahead игнорируется, но не вложенный semanti c lookahead .
void Start() : {} {
(
LOOKAHEAD(Fullname()) Fullname()
| Douglas()
) <EOF>
}
void Fullname() : {} {
( LOOKAHEAD(Douglas() Munro())
Douglas()
| Douglas() Albert()
)
Munro()
}
void Douglas() : {} { "Douglas" }
void Albert() : {} { "Albert" }}
void Munro() : {} { "Munro" }}
Все примеры взяты из удивительной книги Создание парсеров с JavaCC Тома Коупленда
Надеюсь, это полезно, спасибо.