如何在JavaCC中匹配可选的开/闭标签?

4

JavaCC语法如何实现可以解析这些类型的行:

[b]content[/b]
content[/b]
[b]content

尽管JavaCC解析器需要解析所有行,但是它必须区分正确和不正确的标记行为。
正确的标记类似于第一行,它们具有开放和关闭标记。当标记匹配时,将输出加粗格式文本。
不正确的标记类似于第2和第3行,它们没有匹配的开放或关闭标记。当出现这些情况时,它们会按原样写入输出,并且不会被解释为标记。
我尝试了下面的JavaCC代码(LOOKAHEAD = 999999)。问题在于,这个语法将始终将所有内容匹配为invalidTag()而不是bold()。如何确保JavaCC解析器在可能的情况下匹配bold()?
String parse() :
{}
{
    body() <EOF>
    { return buffer; }
}

void body() :
{}
{
    (content())*
}

void content() :
{}
{ 
    (text()|bold()|invalidTag)
}

void bold() :
{}
{
    { buffer += "<b>";  }
    <BOLDSTART>(content())*<BOLDEND>
    { buffer += "</b>"; }
}

void invalidTag() :
{
}
{
    <BOLDSTART> | <BOLDEND>
    { // todo: just output token
    }
}

TOKEN :
{
    <TEXT : (<LETTER>|<DIGIT>|<PUNCT>|<OTHER>)+ >
    |<BOLDSTART : "[b]" >
    |<BOLDEND : "[/b]" >

    |<LETTER : ["a"-"z","A"-"Z"] >
    |<DIGIT : ["0"-"9"] >
    |<PUNCT : [".", ":", ",", ";", "\t", "!", "?", " "] >
    |<OTHER : ["*", "'", "$", "|", "+", "(", ")", "{", "}", "/", "%", "_", "-", "\"", "#", "<", ">", "=", "&", "\\"]     >
}

看到BBCode...呕吐了。 - NullUserException
@NullUserException:对我不起作用,我需要解析人们可能输入的所有可能的BBCode标记。 - Kdeveloper
2个回答

5

你的语法存在歧义。这可能不是你的错,因为很难为你要解决的问题编写一个明确的语法。

对于这个任务,LL(k)解析器可能不是最好的工具。

然而,分词器可能会有用,并且使用堆栈来查找匹配和不匹配的标签可能是一个合适的替代方案。


我得出了相同的结论,但我认为JavaCC对于仅仅进行标记化处理有点过头了。你知道有没有一个100%的Java标记器?(这样我就不需要额外的构建工具了吗?) - Kdeveloper

2

之前我了解到,一些琐碎的问题可以在语义或词汇层面轻松解决,但在句法层面却非常困难甚至不可能。

注意: 我对JavaCC并不是很熟悉,但我以前使用过多个编译器生成器(我最喜欢的是SableCC)。

您可以将“content”定义为以下内容:

(text()|boldstart()|boldend()|invalidTag)
boldstart()只会盲目输出开始标签,而boldend()则是结束标签。
如果您只想过滤掉所有这些,并且只生成正确结束的标签,则建议制作某种有状态的自动机,将其馈送开放和结束标记,并注意是否应该开始、停止或继续(可能包括嵌套深度),并根据此输出开始、停止或无标记。与使用JavaCC中的语法或词法工具相比,这将非常容易实现。

谢谢,你有这方面的示例链接吗?或者知道一个Java分词器工具吗? - Kdeveloper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接