代码之家  ›  专栏  ›  技术社区  ›  user1424739

在shell中解析heredoc的解析器是否可以删除lexer的内部控制?

  •  0
  • user1424739  · 技术社区  · 6 年前

    处理 heredoc 在shell(例如bash)中,语法规则将更改变量 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

    需要这里的医生 用于 read_token() ,由调用 yylex() . 这使得 yLeX() 非自主的。

    设计一个能改变如何的解析器是正常的吗? yLeX() 表现?

    是因为shell语言不是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 回复  |  直到 6 年前
        1
  •  0
  •   rici    6 年前

    设计一个能改变YLyEx()行为的解析器是否正常?

    当然。这可能不太理想,但却是非常普遍的。

    POSIX shell语法远不是Flex/BySon解析器的理想候选,而对于使用Flex和BySon的BASH实现来说,唯一可以说的是,它演示了如果将这些工具推到各自的极限,这些工具是多么灵活。在这里,文档并不是唯一需要“词汇反馈”的地方。

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

    可能最著名(或最常被评论)的词汇反馈是对c风格的转换表达式的解析,这需要lexer知道 foo 在里面 (foo) 是否为类型名。(这通常是通过解析器和lexer之间共享的符号表实现的,但是精确的实现细节是很棘手的。)

    这里还有一些其他的例子,它们可能被认为是词汇反馈的相对良性的使用,尽管它们确实增加了lexer和解析器之间的耦合。

    • 蟒蛇 (和haskell)需要词汇扫描器将前导空格重新格式化为indent或dedent标记。但是,如果换行符出现在括号内,则会抑制空白处理(包括换行标记本身)。

    • ECMAScript (javascript)和其他语言允许用 / 但是 / 也可以是除法运算符或 /= 变异算子。词法决定取决于解析上下文。(词法扫描器可以从最近的标记历史中猜出这一点,这将被视为词法扫描器中解析逻辑的一部分。)

    • 与上述类似,许多语言都会过载 < 使词汇扫描器的逻辑复杂化的方法。作为模板支架而不是比较运算符,可以在扫描仪中处理,例如,在C++中,它将取决于前面的标识符是否是模板的特征,但这实际上并不改变词法上下文。然而,使用尖括号来表示x/html文本(或模板)的开头肯定会改变词法上下文。与上面的正则表达式示例一样,需要知道比较运算符在语法上是否有效。

    是因为shell语言不是lalr(1),所以无法避免更改 yylex() 通过语法动作?

    posix shell语法肯定不是lalr(1),甚至不是上下文无关的。但是,大多数语言不能用lalr(1)解析器进行扫描式解析,如果考虑到所有的语法因素,许多语言都没有上下文无关的语法。(参见上面C风格的转换表达式)也许Shell比大多数人更远离柏拉图的理想。但是,随着时间的推移,它从一个简单到类型化,而不是形式上可分析的内核发展起来。(关于这个借口是否可以推广到Perl,我不打算在这里讨论。)

    一般来说,我要说的是,嵌入其他语言(正则表达式、html片段、flex/bison语义操作、shell算术扩展等)的语言对一个简单的解析器/扫描器模型提出了挑战。尽管有很多有趣的工作和可靠的实验,我的感觉是语言嵌入仍然缺乏一个良好的可实现的形式结构。而且由于大多数语言都嵌入了子语言,所以在它们的解析器实现中存在并将继续存在某种附加语言。在某种程度上,这就是为什么这个领域的研究如此有趣。