好的,看来您需要一种称为前瞻的技术。这是一个非常好的教程:
Lookahead tutorial
那时我的第一次尝试是错误的,但由于它适用于定义上下文的不同标记,我将把它留在这里(也许它对某人有用;o))。
假设我们想要某种标记语言。我们想要“标记”的只是:
- 由字母 (abc...zABC...Z) 和空格组成的表达式 --> 单词
- 由数字 (0-9) 组成的表达式 --> 数字
我们希望将单词包含在标签中,将数字包含在标签中。因此,如果我说对了,这就是您想要做的:如果您在单词上下文中(在单词标签之间),编译器应该期望字母和空格,在数字上下文中它期望数字。
我创建了 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> ...
那是因为解析器没有找到它所期望的。
我希望这会有所帮助。
干杯!
PS:解析器不能在令牌中“存在”,因为令牌是终端符号(如果我错了,请纠正我),不能再被生产规则替换。因此,所有上下文方面都必须放在生产规则(非终端)中,例如我的示例中的“WordContext”。