如何在 yacc 或 bison 中实现 python 样式的缩进?
How to implement python style indentation in yacc or bison?
我一直在尝试在我的 bison 语法中实现 python 风格的缩进,一些关于该实现的见解或想法会很好。
最好的方法通常是让词法分析器跟踪缩进级别并将 INDENT/UNINDENT 标记适当地插入到标记流中。这是我必须执行的一些弹性代码:
%x LINESTART
%s NORMAL
%{
static std::stack<int> indent;
static int indent_depth(const char *);
%}
%%
<INITIAL>.*|\n { yyless(0); BEGIN(LINESTART); indent.push(0); }
<LINESTART>[ \t]* { int depth = indent_depth(yytext);
if (depth < indent.top()) {
indent.pop();
yyless(0);
return UNINDENT; }
BEGIN(NORMAL);
if (depth > indent.top()) {
indent.push(depth);
return INDENT; } }
<LINESTART>. { yyless(0);
if (indent.top() > 0) {
indent.pop();
return UNINDENT; }
BEGIN(NORMAL); }
<LINESTART><<EOF>> { if (indent.top() > 0) {
indent.pop();
return UNINDENT; }
BEGIN(NORMAL); }
<LINESTART>[ \t]*\n { lineno++; }
<LINESTART>[ \t]*#.*\n { lineno++; }
[[({] { parens++; return *yytext; }
[])}] { if (--parens < 0) parens = 0;
return *yytext; }
\n { lineno++;
if (parens == 0) BEGIN(LINESTART); }
这段代码在特殊情况下有些棘手——例如,您需要忽略空行和只有注释的行,并且您可能还想忽略不平衡括号内的缩进(上面的代码就是这样做的)。
我一直在尝试在我的 bison 语法中实现 python 风格的缩进,一些关于该实现的见解或想法会很好。
最好的方法通常是让词法分析器跟踪缩进级别并将 INDENT/UNINDENT 标记适当地插入到标记流中。这是我必须执行的一些弹性代码:
%x LINESTART
%s NORMAL
%{
static std::stack<int> indent;
static int indent_depth(const char *);
%}
%%
<INITIAL>.*|\n { yyless(0); BEGIN(LINESTART); indent.push(0); }
<LINESTART>[ \t]* { int depth = indent_depth(yytext);
if (depth < indent.top()) {
indent.pop();
yyless(0);
return UNINDENT; }
BEGIN(NORMAL);
if (depth > indent.top()) {
indent.push(depth);
return INDENT; } }
<LINESTART>. { yyless(0);
if (indent.top() > 0) {
indent.pop();
return UNINDENT; }
BEGIN(NORMAL); }
<LINESTART><<EOF>> { if (indent.top() > 0) {
indent.pop();
return UNINDENT; }
BEGIN(NORMAL); }
<LINESTART>[ \t]*\n { lineno++; }
<LINESTART>[ \t]*#.*\n { lineno++; }
[[({] { parens++; return *yytext; }
[])}] { if (--parens < 0) parens = 0;
return *yytext; }
\n { lineno++;
if (parens == 0) BEGIN(LINESTART); }
这段代码在特殊情况下有些棘手——例如,您需要忽略空行和只有注释的行,并且您可能还想忽略不平衡括号内的缩进(上面的代码就是这样做的)。