繁体   English   中英

JavaCC:如何在特定情况下指定期望的令牌?

[英]JavaCC: How can I specify which token(s) are expected in certain context?

我需要使JavaCC知道上下文(当前的父标记),并根据该上下文期望出现不同的标记。

考虑以下伪代码:

TOKEN <abc> { "abc*" } // recognizes "abc", "abcd", "abcde", ...
TOKEN <abcd> { "abcd*" } // recognizes "abcd", "abcde", "abcdef", ...

TOKEN <element1> { "element1" "[" expectOnly(<abc>) "]" }
TOKEN <element2> { "element2" "[" expectOnly(<abcd>) "]" }
...

因此,当生成的解析器在“内部”时,名为"element1" ”的令牌遇到"abcdef"它将识别为<abc> ;但是,当生成的解析器在“内部”时,将命名为"element2"的令牌识别为与<abcd>相同的字符串。 。

element1 [ abcdef ] // aha! it can only be <abc>
element2 [ abcdef ] // aha! it can only be <abcd>

如果我没有记错的话,它的行为类似于XML文件的更复杂的DTD定义。

因此,如何指定在哪个“上下文”中有效/预期的令牌?

注意:这将是不够我的真实案例来定义一个种类的记号“等级制”,让“ABCDEF”总是先对匹配<abcd><abc> 我真的需要上下文感知令牌。

好的,看来您这里需要一种称为前瞻的技术。 这是一个很好的教程: 前瞻教程

那时我的第一次尝试是错误的,但是由于它适用于定义上下文的不同令牌,因此我将其保留在这里(也许对某人有用; 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”。

您需要使用词法分析器状态。 您的示例如下所示:

<DEFAULT>令牌:{<ELEMENT1:“ element1”>:IN_ELEMENT1}
<DEFAULT>令牌:{<ELEMENT2:“ element2”>:IN_ELEMENT2}
<IN_ELEMENT1>令牌:{<ABC:“ abc”(...)*>:默认值}
<IN_ELEMENT2>令牌:{<ABCD:“ abcd”(...)*>:默认}

请注意, (...)*不是正确的JavaCC语法,但是您的示例也不是,因此我只能猜测。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM