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 : ["*", "'", "$", "|", "+", "(", ")", "{", "}", "/", "%", "_", "-", "\"", "#", "<", ">", "=", "&", "\\"] >
}
答案 0 :(得分:5)
你的语法含糊不清。这可能不是你的错,因为对于你想要解决的问题,可能很难产生明确的语法。
LL(k)解析器可能不是这项工作的最佳工具。
然而,令牌化器可能很有用,并且使用堆栈来查找匹配和不匹配的标签对可能是合适的替代方案。
答案 1 :(得分:2)
前段时间我已经了解到,在语义或词汇层面上可以很容易地解决一些微不足道的问题,而在语法层面证明是非常困难或不可能的。
注意:我对JavaCC不太熟悉,但过去我曾经使用过多个编译器生成器(我最喜欢的是sablecc)。
您可能只需将“内容”定义为:
(text()|boldstart()|boldend()|invalidTag)
其中boldstart()只是盲目地输出开始标记和boldend() - 结束标记。
如果你想要过滤所有这些并且只生成正确结束的标签,那么我建议为此制作某种有状态的自动机,将它打开并结束标签,注意是否(如)粗体应该开始,停止或继续(可能包括嵌套深度)并根据输出启动,停止或无标记。与使用JavaCC中的语法或词汇工具相比,这将非常容易实现。