是否可以通过解析器删除lexer的内部控件,以便在shell中解析heredoc?

时间:2019-02-07 19:36:08

标签: parsing compiler-construction bison interpreter flex-lexer

要在外壳(例如bash)中处理heredoc,语法规则将通过need_here_doc来更改变量push_heredoc()

    |   LESS_LESS WORD
            {
              source.dest = 0;
              redir.filename = $2;
              $$ = make_redirection (source, r_reading_until, redir, 0);
              push_heredoc ($$);
            }

http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y#n539

static void
push_heredoc (r)
     REDIRECT *r;
{
  if (need_here_doc >= HEREDOC_MAX)
    {
      last_command_exit_value = EX_BADUSAGE;
      need_here_doc = 0;
      report_syntax_error (_("maximum here-document count exceeded"));
      reset_parser ();
      exit_shell (last_command_exit_value);
    }
  redir_stack[need_here_doc++] = r;
}

http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y#n2794

need_here_docread_token()中使用的yylex()中使用。这使得yylex()的行为是非自治的。

设计一个可以更改yylex()行为的解析器是否正常?

是因为外壳语言不是LALR(1),所以没有办法避免通过语法动作来改变yylex()的行为吗?

      if (need_here_doc)
    gather_here_documents ();

http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y#n3285

  current_token = read_token (READ);

http://git.savannah.gnu.org/cgit/bash.git/tree/parse.y#n2761

1 个答案:

答案 0 :(得分:0)

  

设计一个可以更改yylex()行为的解析器是否正常?

好的。这可能不是理想的,但是非常普遍。

Posix shell语法与flex / bison解析器的理想候选者相去甚远,关于使用flex和bison的bash实现,您唯一可以说的就是它展示了将这些工具推送到其后可以多么灵活。各自的限制。这里的文档并不是唯一需要“词汇反馈”的地方。

但是,即使使用更纪律的语言,词汇反馈也可能有用。或其替代方案:将部分解析逻辑写入词汇扫描器,以使其知道何时解析将需要一组不同的词汇规则。

可能最著名(或评论最频繁)的词法反馈是C样式强制转换表达式的解析,这要求词法分析器知道foo中的(foo)是否是类型名称或不。 (这通常是通过解析器和词法分析器之间共享的符号表来实现的,但是确切的实现细节很棘手。)

还有其他一些示例,尽管它们肯定会增强词法分析器与解析器之间的耦合,但可能被认为是词汇反馈的相对良性用途。

  • Python (和Haskell)要求词法扫描器将前导空格重新格式化为INDENT或DEDENT标记。但是,如果换行符发生在括号内,则空格处理将被抑制(包括NEWLINE令牌本身)。

  • Ecmascript (Javascript)和其他语言允许用/包围正则表达式文字。但是/也可以是除法运算符,也可以是/=突变运算符中的第一个字符。词法决定取决于解析上下文。 (这可以由词汇扫描程序从最近的令牌历史记录中猜测出来,这将被视为词汇扫描程序中解析逻辑的一部分。)

  • 与上述类似,许多语言使<重载,从而使词法扫描器中的逻辑复杂化。在扫描仪中可能会处理将其用作模板括号而不是比较运算符-例如,在C ++中,它将取决于诸如前面的标识符是否为模板之类的功能-但实际上并不会改变词汇语境。但是,使用尖括号指示X / HTML文字(或模板)的开始肯定会改变词汇上下文。与上面的正则表达式示例一样,有必要知道比较运算符在语法上是否有效。

  

是因为shell语言不是LALR(1),所以没有办法避免通过语法动作来改变yylex()的行为吗?

Posix shell语法绝对不是LALR(1),甚至与上下文无关。但是,大多数语言无法使用LALR(1)解析器进行无扫描器解析,并且如果考虑到所有语法方面的因素,许多语言就会发现没有上下文无关的语法。 (上面是C语言风格的强制转换表达式。)也许外壳比大多数柏拉图理想更远。但是后来,它的发展源于旨在简单键入而不是正式可分析的内核。 (我没有评论这个借口是否可以扩展到Perl,在这里我不打算讨论。)

我通常要说的是,嵌入其他语言(正则表达式,HTML片段,Flex / Bison语义操作,shell算术扩展等)的语言给简化的解析器/扫描器模型带来了挑战。尽管进行了大量有趣的工作和扎实的实验,但我的感觉是语言嵌入仍然缺乏良好的可实现形式结构。而且,由于大多数语言的确嵌入了子语言,因此在解析器实现中将存在并将继续存在某些障碍。在某种程度上,这就是使这个研究领域变得如此有趣的原因。