Вы должны понимать, что синтаксический предикат будет не заставлять синтаксический анализатор давать лексеру какое-то направление относительно того, какой маркер парсер "хотел бы" получить.Синтаксический предикат используется, чтобы заставить анализатор смотреть в существующем потоке токенов для устранения неоднозначностей (акцент на «существующий»: анализатор не имеет никакого контроля над тем, какие токены создаются!).
Лексер работает независимо от анализатора, систематически создавая токены:
- он пытается сопоставить максимально возможное количество символов;
- всякий раз, когда совпадают 2 (или более) правилаПри таком же количестве символов правило, определенное первым, получит приоритет над правилом, определенным позже.
Таким образом, в вашем случае, учитывая ввод "a/b/c/filename"
, лексер будет жадно соответствовать всемуввод в виде одного PATH
токена.
Если вы хотите получить имя файла, либо получите его из PATH
:
rule : PATH
{
String file = $PATH.text.substring($PATH.text.lastIndexOf('/') + 1);
System.out.println("file: " + file + ", path: " + $PATH.text);
}
;
WORD : ('a'..'z')+;
SLASH : '/';
PATH : (WORD SLASH)* WORD;
, либо создайте правило синтаксического анализатора, соответствующее пути:
rule : dir WORD
{
System.out.println("file: " + $WORD.text + ", dir: " + $dir.text);
}
;
dir : (WORD SLASH)+;
WORD : ('a'..'z')+;
SLASH : '/';