ОК, похоже, вам нужна техническая техника, называемая lookahead. Вот очень хороший учебник: Lookahead tutorial
Моя первая попытка была не так, то, но, как это работает для различных маркеров, которые определяют контекст, я оставлю это здесь (Может быть, это полезно для кого-то; о)).
Предположим, мы хотим иметь какой-либо язык разметки. Все, что мы хотим "разметки" являются:
- Выражения, состоящие из букв (ABC ... ZABC ... Z) и непечатаемых -> Слова
- выражения, состоящие из цифр (0-9) - > numbers
Мы хотим заключить слова в теги и цифры в тегах. Поэтому, если я правильно понял, что вы хотите сделать: если вы находитесь в контексте слова (между тегами слов), компилятор должен ожидать буквы и пробелы, в числовом контексте он ожидает числа.
Я создал файл WordNumber.jj, который определяет грамматику и парсер генерироваться:
options
{
LOOKAHEAD= 1;
CHOICE_AMBIGUITY_CHECK = 2;
OTHER_AMBIGUITY_CHECK = 1;
STATIC = true;
DEBUG_PARSER = false;
DEBUG_LOOKAHEAD = false;
DEBUG_TOKEN_MANAGER = false;
ERROR_REPORTING = true;
JAVA_UNICODE_ESCAPE = false;
UNICODE_INPUT = false;
IGNORE_CASE = false;
USER_TOKEN_MANAGER = false;
USER_CHAR_STREAM = false;
BUILD_PARSER = true;
BUILD_TOKEN_MANAGER = true;
SANITY_CHECK = true;
FORCE_LA_CHECK = false;
}
PARSER_BEGIN(WordNumberParser)
/** Model-tree Parser */
public class WordNumberParser
{
/** Main entry point. */
public static void main(String args []) throws ParseException
{
WordNumberParser parser = new WordNumberParser(System.in);
parser.Input();
}
}
PARSER_END(WordNumberParser)
SKIP :
{
" "
| "\n"
| "\r"
| "\r\n"
| "\t"
}
TOKEN :
{
< WORD_TOKEN : (["a"-"z"] | ["A"-"Z"] | " " | "." | ",")+ > |
< NUMBER_TOKEN : (["0"-"9"])+ >
}
/** Root production. */
void Input() :
{}
{
(WordContext() | NumberContext())* <EOF>
}
/** WordContext production. */
void WordContext() :
{}
{
"<WORDS>" (<WORD_TOKEN>)+ "</WORDS>"
}
/** NumberContext production. */
void NumberContext() :
{}
{
"<NUMBER>" (<NUMBER_TOKEN>)+ "</NUMBER>"
}
Вы можете протестировать его с файлом, как что:
<WORDS>This is a sentence. As you can see the parser accepts it.</WORDS>
<WORDS>The answer to life, universe and everything is</WORDS><NUMBER>42</NUMBER>
<NUMBER>This sentence will make the parser sad. Do not make the parser sad.</NUMBER>
Последняя строка вызвать парсер, чтобы бросить исключение, как это:
Exception in thread "main" ParseException: Encountered " <WORD_TOKEN> "This sentence will make the parser sad. Do not make the parser sad. "" at line 3, column 9. Was expecting: <NUMBER_TOKEN> ...
Это потому, что парсер не нашел ожидаемого.
Я надеюсь, что это поможет.
Cheers!
P.S .: Парсер не может «быть» внутри токена, поскольку токен является символом терминала (исправьте меня, если я ошибаюсь), который не может быть заменен производственными правилами дальше. Таким образом, все контекстные аспекты должны быть помещены внутри производственного правила (non terminal), такого как «WordContext» в моем примере.
Я узнал, что 'JavaCC' позволяет указать лексические контексты. К сожалению, это делает все очень сложным, когда у вас много * токенов, в которых большинство из них нуждается в собственном * состоянии. Я уже разработал парсер детерминированного состояния-машины и в настоящее время улучшаю его, чтобы принять недетерминированные состояния-машины. Должен признаться, мое дело очень особенное. –