LOOKAHED - количество токенов, необходимое для принятия решения о пути, который необходимо выбрать для проверки синтаксиса в дереве синтаксиса, сгенерированном анализаторами Javacc.
Эта конфигурация необходима для разрешения конфликтов выбора, поскольку javacc не поддерживает возврат.
, поэтому важно написать грамматику, которая подходит для LOOKAHED = 1, то есть, глядя на один токен, определяется поток в дереве синтаксиса. это способ написания грамматики.
Например:
Поскольку JavaCC является синтаксическим анализатором LR, левый токен производственного правила повторяется, поэтому в дереве синтаксиса это будет разветвленным. Конфликт выбора возникает, на какой ветви выбрать, как показано ниже,
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
- Синтаксический LOOKAHEAD
- Сочетание нескольких токенов и синтаксического LOOKAHEAD
- Семантический LOOKAHEAD
- Вложенный Lookahead
Несколько токенов LOOKAHEAD
Это можно использовать с целым числом, переданным в методе LOOKAHEAD (k). Это можно сделать с помощью
Синтаксический LOOKAHEAD
Спецификация Syntactic lookahead использует синтаксическую конструкцию в качестве решателя выбора.
При указании синтаксического просмотра без использования нескольких токенов на самом деле вы указываете синтаксический просмотр с бесконечным множеством токенов.
Например: LOOKAHEAD (2147483647, LocalNumber ())
void PhoneNumber() : {} {
(
LOOKAHEAD(("A"|"B")+ AreaCode() "-" <FOUR_DIGITS>) LocalNumber()
| CountryNumber()
) <EOF>
}
Сочетание нескольких токенов и синтаксического LOOKAHEAD
Таким образом, мы можем смотреть ограниченное количество токенов, если будет сделан синтаксический просмотр, удовлетворяющий заданному выбору.
void PhoneNumber() : {} {
(
LOOKAHEAD(10, ("A"|"B")+ AreaCode() "-" <FOUR_DIGITS>) LocalNumber()
| CountryNumber()
) <EOF>
}
1072 *
Семантический LOOKAHEAD
Семантическое рассмотрение предполагает встраивание кода Java в грамматику в точке выбора.
Если код Java возвращает true, выбрано текущее расширение.
void PhoneNumber() : {} {
(
LOOKAHEAD({getToken(1).image.equals("123")})
KeysvilleNumber()
| FarmvilleNumber()
) <EOF>
}
1083 *
Вложенный Lookahead
Вложенный lookahead возникает, когда одна директива lookahead перекрывает другую.
В JavaCC вложенный упреждения игнорируется, но не вложенный семантический просмотр.
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 Тома Коупленда
Надеюсь, это полезно, спасибо.