compiler-construction - 如何使用缩进作为带有 bison 和 flex 的 block 分隔符

标签 compiler-construction bison flex-lexer

我想知道如何在 bison + flex 中实现缩进作为块分隔符。就像在python中一样。我正在编写自己的编程语言(主要是为了好玩,但我打算将它与游戏引擎一起使用),我将尝试提出一些特殊的东西,以最大限度地减少样板并最大限度地提高开发速度。

我已经用 C 编写了一个编译器(实际上是一个“langToy”到 Nasm 翻译器),但是失败了。由于某种原因,它只能处理整个源文件中的一个字符串(好吧,我已经醒了 48 多个小时——所以......你知道,大脑崩溃了)。

我不知道大括号和/或开始 -> 结束是否更容易实现(我这样做没有问题),或者只是我的大脑被锁定了。

提前致谢!

更新:好的,我不知道如何使用 flex 来做到这一点。我在将多个 DEDENT 返回给解析器时遇到问题。 Flex/Bison 对我来说相对较新。

更新 2:
这是我目前想出的 flex 文件;它不太明白:

%x t
%option noyywrap

%{
  int lineno = 0, ntab = 0, ltab = 0, dedent = 0;
%}

%%

<*>\n  { ntab = 0; BEGIN(t); }
<t>\t  { ++ntab; }
<t>.   { int i; /* my compiler complains not c99 if i use for( int i=0... */
         if( ntab > ltab )
           printf("> indent >\n");
         else if( ntab < ltab )
           for( i = 0; i < ltab - ntab; i++ )
             printf("< dedent <\n");
         else
           printf("=        =\n");

         ltab = ntab; ntab = 0;
         BEGIN(INITIAL);
         /* move to next rule */
         REJECT;}
.    /* ignore everything else for now */

%%

main()
{
  yyin = fopen( "test", "r" );
  yylex();
}

你可以试着玩弄它,也许你看到了我缺少的东西。在 Haxe 中返回多个 dedents 会很容易( return t_dedent( num ); )。

此代码并不总是正确匹配缩进/凹进。

更新 3:我想我会放弃对 flex 的希望并以我自己的方式去做,如果有人知道如何在 flex 中做到这一点,我会很高兴听到它。

最佳答案

您需要做的是让 flex 计算每行开头的空格数量,并插入适当数量的 INDENT/UNINDENT 标记,供解析器用于对事物进行分组。一个问题是你想对制表符和空格做些什么——你只是想让它们与固定的制表位等效,还是你想要求缩进保持一致(所以如果一行以制表符开头,下一行如果有空格,则表示错误,这可能会更难一些)。

假设您想要固定的 8 列制表位,您可以使用类似

%{
/* globals to track current indentation */
int current_line_indent = 0;   /* indentation of the current line */
int indent_level = 0;          /* indentation level passed to the parser */
%}

%x indent /* start state for parsing the indentation */
%s normal /* normal start state for everything else */

%%
<indent>" "      { current_line_indent++; }
<indent>"\t"     { current_line_indent = (current_line_indent + 8) & ~7; }
<indent>"\n"     { current_line_indent = 0; /*ignoring blank line */ }
<indent>.        {
                   unput(*yytext);
                   if (current_line_indent > indent_level) {
                       indent_level++;
                       return INDENT;
                   } else if (current_line_indent < indent_level) {
                       indent_level--;
                       return UNINDENT;
                   } else {
                       BEGIN normal;
                   }
                 }

<normal>"\n"     { current_line_indent = 0; BEGIN indent; }
... other flex rules ...

您必须确保以缩进模式开始解析(以获得第一行的缩进)。

关于compiler-construction - 如何使用缩进作为带有 bison 和 flex 的 block 分隔符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1413204/

相关文章:

parsing - Gnu Bison 移位/减少描述分层表达式的基于缩进的语法中的冲突

c++ - 在 C++ 中,严格的自底向上分析如何暗示返回类型不用于重载决策?

c - 如何为特定部分构建大量全局数据?

parsing - Bison Flex 无法访问 bison 规则部分中的第一个 token

parsing - 如何设置 flex/bison 规则来解析逗号分隔的参数列表

c - 从 yylex 返回 "non-ints"

c# - C# visual studio 编译器如何处理 struct/NULL 比较?

objective-c - 使用 Clang (Ubuntu) 编译 Objective C 时的问题

Bison 错误处理

c - 如何让 Bison/YACC 在解析整个字符串之前不识别命令?