对于所有编译器专家,我想编写一个递归下降解析器,我只想用代码来完成。没有从其他语法生成词法分析器和解析器,也不要告诉我阅读龙书,我最终会解决这个问题。
我想深入了解有关为一种合理的简单语言(例如 CSS)实现词法分析器和解析器的细节。我想正确地做到这一点。
这可能最终会成为一系列问题,但现在我从词法分析器开始。可以在此处找到 CSS 的标记化规则。
我发现我自己编写的代码是这样的(希望你可以从这段代码中推断出其余的):
public CssToken ReadNext()
{
int val;
while ((val = _reader.Read()) != -1)
{
var c = (char)val;
switch (_stack.Top)
{
case ParserState.Init:
if (c == ' ')
{
continue; // ignore
}
else if (c == '.')
{
_stack.Transition(ParserState.SubIdent, ParserState.Init);
}
break;
case ParserState.SubIdent:
if (c == '-')
{
_token.Append(c);
}
_stack.Transition(ParserState.SubNMBegin);
break;
这个叫什么?我离合理理解的东西还有多远?我正在尝试平衡一些在效率方面公平且易于使用的东西,使用堆栈来实现某种状态机效果很好,但我不确定如何继续这样。
我拥有的是一个输入流,我一次可以从中读取 1 个字符。我现在不做任何头,我只是阅读角色然后根据当前状态尝试对此做些什么。
我真的很想进入编写可重用代码片段的思维模式。这个Transition
方法目前的意思是这样做,它会弹出堆栈的当前状态,然后以相反的顺序推送参数。这样,当我编写Transition(ParserState.SubIdent, ParserState.Init)
它时,它将“调用”一个子例程SubIdent
,该例程完成后将返回到该Init
状态。
解析器将以几乎相同的方式实现,目前,将所有内容都放在一个大方法中,这样我可以在找到一个标记时轻松返回一个标记,但它也迫使我将所有内容保存在一个大方法中。有没有一种很好的方法可以将这些标记化规则拆分为单独的方法?