首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaCC:我如何指定在特定上下文中需要哪个令牌?

JavaCC:我如何指定在特定上下文中需要哪个令牌?
EN

Stack Overflow用户
提问于 2010-04-29 06:40:15
回答 2查看 4.9K关注 0票数 1

我需要让JavaCC知道一个上下文(当前的父令牌),并且根据这个上下文,期望出现不同的令牌。

考虑以下伪代码:

代码语言:javascript
复制
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>相同的字符串。

代码语言:javascript
复制
element1 [ abcdef ] // aha! it can only be <abc>
element2 [ abcdef ] // aha! it can only be <abcd>

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

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

注意:对于我的实际情况,定义一种令牌的“层次结构”是不够的,因此"abcdef“总是首先与<abcd><abc>匹配。我真的需要上下文感知的标记。

EN

回答 2

Stack Overflow用户

发布于 2010-05-05 11:47:55

好的,这里似乎需要一种叫做“前瞻性”的技术。下面是一个非常好的教程:前瞻性教程

我的第一次尝试是错误的,但由于它适用于定义上下文的不同标记,所以我将把它留在这里(也许它对某人有用;o)。

假设我们想拥有某种标记语言。我们想要的“标记”是:

  • 由字母组成的表达式(abc.zABC.Z)和空格->单词
  • 由数字(0-9) -数字组成的表达式

我们要把单词放在标签里,数字放在标签里。所以,如果我说得对,这就是您想要做的:如果您在word上下文中(在word标记之间),编译器应该期望字母和空格,在数字上下文中它需要数字。

我创建了文件WordNumber.jj,它定义了要生成的语法和解析器:

代码语言:javascript
复制
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>"
}

您可以用这样的文件来测试它:

代码语言:javascript
复制
<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> ...

这是因为解析器没有找到它所期望的。

我希望这能帮上忙。

干杯!

P.S.:解析器不能“在”令牌内,因为令牌是一个终端符号(如果我错了,请纠正我),不能再用生产规则代替它了。因此,在我的示例中,所有的上下文方面都必须放在生产规则(非终端)中,比如"WordContext“。

票数 2
EN

Stack Overflow用户

发布于 2011-02-08 17:05:27

您需要使用lexer状态。您的示例类似于:

令牌:{ :IN_ELEMENT1 } 令牌:{:IN_ELEMENT2 } 令牌:{ :默认} 令牌:{ :默认}

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2735238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档