解析没有花括号的代码块的技巧
Techniques for parsing code blocks without curly braces
我正在用 C# 从头开始编写一个简单的 parser/interpreter(没有第三方库)。它编译为字节码,然后我有 class 运行字节码。我快要结束了。我刚刚实现了 while
和 for
循环,并且正在处理 if
|else if
|else
块。
就目前而言,我的解析器要求所有这些结构都使用大括号。我想让它更像 C,并且当块只包含一个语句时花括号是可选的。这给我带来了麻烦。
if (condition)
{
// Make curly braces optional when there is just one statement here
}
问题是跟踪状态。解析器如何知道没有花括号的块何时结束。一种方法是检查在每条语句之后是否有一个没有生效的大括号块。然而,有很多不同的场景可以构成一个声明,因此这些检查需要在很多地方进行。这对我来说有点脆弱。
我只是想知道是否有人这样做过并且知道在没有花括号的情况下跟踪代码块何时结束的巧妙技巧。
您需要调查 recursive descent parser。它使创建解析器变得容易得多。假设您的语法如下所示:
statement
: 'if' paren_expr ['{'] statement ['}']
paren_expr
: '(' expr ')'
然后使用递归下降你可以做这样的事情:
public void Statement()
{
if(curToken == Token.If)
{
Eat(Token.If); // Eat is convenience method that moves token pointer on
if(curToken == Token.LParen)
{
Eat(Token.LParen)
ParenExpr();
Eat(Token.RParen);
}
if(curToken == Token.LBrace) // this will signify a block of statements
{
Eat(Token.LBrace);
while(curToken != Token.RBrace)
Statement();
Eat(Token.RBrace);
}
else
Statement();
}
}
public void ParenExpr()
{
// do other token checks
}
对所有非终端执行此操作,您可以轻松构建 AST,然后从中生成字节码。
我正在用 C# 从头开始编写一个简单的 parser/interpreter(没有第三方库)。它编译为字节码,然后我有 class 运行字节码。我快要结束了。我刚刚实现了 while
和 for
循环,并且正在处理 if
|else if
|else
块。
就目前而言,我的解析器要求所有这些结构都使用大括号。我想让它更像 C,并且当块只包含一个语句时花括号是可选的。这给我带来了麻烦。
if (condition)
{
// Make curly braces optional when there is just one statement here
}
问题是跟踪状态。解析器如何知道没有花括号的块何时结束。一种方法是检查在每条语句之后是否有一个没有生效的大括号块。然而,有很多不同的场景可以构成一个声明,因此这些检查需要在很多地方进行。这对我来说有点脆弱。
我只是想知道是否有人这样做过并且知道在没有花括号的情况下跟踪代码块何时结束的巧妙技巧。
您需要调查 recursive descent parser。它使创建解析器变得容易得多。假设您的语法如下所示:
statement
: 'if' paren_expr ['{'] statement ['}']
paren_expr
: '(' expr ')'
然后使用递归下降你可以做这样的事情:
public void Statement()
{
if(curToken == Token.If)
{
Eat(Token.If); // Eat is convenience method that moves token pointer on
if(curToken == Token.LParen)
{
Eat(Token.LParen)
ParenExpr();
Eat(Token.RParen);
}
if(curToken == Token.LBrace) // this will signify a block of statements
{
Eat(Token.LBrace);
while(curToken != Token.RBrace)
Statement();
Eat(Token.RBrace);
}
else
Statement();
}
}
public void ParenExpr()
{
// do other token checks
}
对所有非终端执行此操作,您可以轻松构建 AST,然后从中生成字节码。