Questions tagged «lexer»

4
何时使用解析器组合器?何时使用解析器生成器?
最近,我想深入了解解析器领域,希望创建自己的编程语言。 但是,我发现存在两种不同的编写解析器的方法:解析器生成器和解析器组合器。 有趣的是,我找不到任何可以解释哪种资源更好的资源。相反,我查询的许多资源(和人员)都不知道另一种方法,只是将其方法解释为该方法,而根本没有提及另一种方法: 在著名的龙书进入词法/扫描,并提到(F)法,但都没有提到解析器组合。 语言实现模式在很大程度上依赖于Java内置的ANTLR解析器生成器,根本没有提到解析器组合器。 Parsec上的Parsec 简介教程(是Haskell中的Parser Combinator)根本没有提到Parser Generators。 Boost :: spirit(最著名的C ++解析器组合器)根本没有提到解析器生成器。 很棒的说明性博客文章“ 您可能已经发明了解析器组合器”根本没有提到解析器生成器。 简单概述: 解析器生成器 解析器生成器获取用DSL编写的文件,该文件是Extended Backus-Naur形式的某种方言,并将其转换为源代码,然后可以(在编译时)成为该DSL中描述的输入语言的解析器。 这意味着编译过程分为两个单独的步骤。有趣的是,解析器生成器本身也是编译器(其中许多确实是自托管的)。 解析器组合器 解析器组合器描述了称为解析器的简单函数,这些函数均将输入作为参数,如果匹配则尝试提取此输入的第一个字符。它们返回一个元组(result, rest_of_input),如果解析器无法解析此输入中的任何内容,则该字段result可能为空(例如nil或Nothing)。一个例子是digit解析器。其他解析器当然可以将解析器作为第一个参数(最后一个参数仍保留在输入字符串中)来组合它们:例如,many1尝试尽可能多地匹配另一个解析器(但至少要匹配一次,否则它本身会失败)。 现在,您当然可以结合(组成)digit和many1创建新的解析器,例如integer。 同样,choice可以编写一个更高级别的解析器,该解析器获取解析器列表,依次尝试每个解析器。 这样,可以构建非常复杂的词法分析器/解析器。在支持运算符重载的语言中,这看起来也很像EBNF,尽管它仍然是直接用目标语言编写的(并且您可以使用所需的目标语言的所有功能)。 简单差异 语言: 解析器生成器使用EBNF-ish DSL和这些语句匹配时应生成的代码的组合编写。 解析器组合器直接以目标语言编写。 乐兴/解析: 解析器生成器在“词法分析器”(将字符串拆分成可能被标记以表明我们正在处理的值的标记)与“解析器”(从词法分析器获取标记的输出列表)之间有非常明显的区别并尝试将它们组合起来,形成一个抽象语法树)。 解析器组合器不需要/不需要这种区别;通常,简单的解析器执行“词法分析器”的工作,而更高级别的解析器将这些更简单的解析器称为确定要创建哪种AST节点。 题 但是,即使存在这些差异(这是差异列表,可能还远远不够!),我仍无法就何时使用哪一个做出明智的选择。我看不出这些差异的含义/后果。 哪些问题属性表明使用Parser Generator可以更好地解决问题?哪些问题属性表明使用Parser Combinator可以更好地解决问题?

6
为什么将词法分析器实现为二维数组和巨型开关?
我正在慢慢地完成学业,这个学期是Compilers101。我们正在使用Dragon Book。在课程开始不久,我们将讨论词法分析以及如何通过确定性有限自动机(以下称DFA)来实现它。设置各种词法分析器状态,定义它们之间的过渡等。 但是教授和这本书都建议通过过渡表来实现它们,过渡表相当于一个巨大的2d数组(一个维的各种非终端状态,而另一个维可能的输入符号),以及一个用于处理所有终端的switch语句以及在非终端状态下调度到过渡表。 这个理论很好,但是作为一个几十年来实际编写代码的人,实现是不道德的。它不可测试,不可维护,不可读,调试起来很麻烦。更糟糕的是,如果该语言具有UTF功能,那么我将看不到它在远程实用。每个非终端状态都有一百万个左右的过渡表条目,这会很不方便。 那怎么办?为什么有关该主题的权威书籍说要这样做呢? 函数调用的开销真的那么多吗?当语法不为人所知时(正则表达式?),这是否行得通?也许可以处理所有情况的东西,即使更具体的解决方案更适合于更具体的语法? (注意:可能重复的“ 为什么使用OO方法而不是巨大的switch语句? ”已经很接近了,但我并不关心OO。使用功能性方法甚至具有独立功能的更明智的命令式方法都可以。) 并且为了示例,考虑一种仅具有标识符的语言,而这些标识符为[a-zA-Z]+。在DFA实施中,您将获得以下内容: private enum State { Error = -1, Start = 0, IdentifierInProgress = 1, IdentifierDone = 2 } private static State[][] transition = new State[][]{ ///* Start */ new State[]{ State.Error, State.Error (repeat until 'A'), State.IdentifierInProgress, ... ///* IdentifierInProgress */ new …

3
词法分析器返回其解析器的令牌的数据类型应该是什么?
如标题中所述,词法分析器应返回/提供解析器哪种数据类型?在阅读Wikipedia 的词法分析文章时,它指出: 在计算机科学中,词法分析是将一系列字符(例如在计算机程序或网页中)转换为一系列标记(具有已标识“含义”的字符串)的过程。 但是,与上述说法完全矛盾的是,当我在另一个站点上问过另一个问题(“代码审查”,如果您很好奇)得到回答时,回答者表示: 词法分析器通常读取字符串,并将其转换为词位流。词素只需要是一串数字。 他给了这个视觉效果: nl_output => 256 output => 257 <string> => 258 稍后,在他提到的文章中Flex,他已经存在一个词法分析器,并说用它编写“规则”比手工编写词法分析器更简单。他继续给我这个例子: Space [ \r\n\t] QuotedString "[^"]*" %% nl_output {return 256;} output {return 257;} {QuotedString} {return 258;} {Space} {/* Ignore */} . {error("Unmatched character");} %% 为了进一步了解并获得更多信息,我阅读了有关Flex的Wikipedia文章。Flex文章显示,您可以通过以下方式使用令牌定义一组语法规则: digit [0-9] letter [a-zA-Z] %% "+" { return PLUS; } …
21 data-types  lexer  flex 

5
解析器组合器是否将单独的解析和词法传递为良好实践?
当我开始使用解析器组合器时,我的第一个反应是从感觉上像是在解析和词法化之间的人为区别中解放出来。突然所有的一切都只是解析! 但是,我最近在codereview.stackexchange上发现了此帖子,说明有人在恢复这种区别。起初我以为这对他们很愚蠢,但是后来Parsec中存在支持这种行为的功能这一事实使我开始质疑自己。 在解析器组合器中对已经词法化的流进行解析有什么优点/缺点?

4
用C ++编写词法分析器
有哪些关于如何使用C ++编写词法分析器的好资源(书籍,教程,文档),有哪些好的技术和实践? 我在互联网上看过,每个人都说要使用像lex这样的词法生成器。我不想这样做,我想手动编写一个词法分析器。
18 c++  compiler  lexer 

5
提出词法分析器标记
我正在为我创建的标记语言编写一个解析器(用python编写,但这与这个问题并不相关-实际上,如果这似乎是一个坏主意,我希望有一个更好的建议) 。 我在这里了解有关解析器的信息:http : //www.ferg.org/parsing/index.html,并且我正在编写词法分析器,如果我理解正确的话,应将内容拆分为标记。我无法理解的是我应该使用哪种令牌类型或如何创建它们。例如,我链接到的示例中的令牌类型为: 串 识别码 数 白空间 评论 紧急行动 许多符号,例如{和(算作自己的标记类型 我遇到的问题是,更通用的令牌类型对我来说似乎有些武断。例如,为什么要STRING自己使用单独的令牌类型,而不要使用IDENTIFIER。字符串可以表示为STRING_START +(IDENTIFIER | WHITESPACE)+ STRING_START。 这也可能与我的语言困难有关。例如,变量声明编写为,{var-name var value}并使用进行部署{var-name}。看起来'{'并且'}'应该是它们自己的令牌,但是VAR_NAME和VAR_VALUE是否符合令牌类型,或者这两者都属于IDENTIFIER吗?而且,VAR_VALUE实际上可以包含空格。after后面的空格var-name用于表示声明中值的开始。其他任何空格都是该值的一部分。这个空格会成为自己的令牌吗?在这种情况下,空白仅具有该含义。而且,{可能不是变量声明的开始..它取决于上下文(再次有该词!)。 {:开始一个名称声明,然后{ 甚至可以用作某些价值的一部分。 我的语言与Python类似,因为代码块是使用缩进创建的。我正在阅读有关Python如何使用词法分析器创建INDENT和DEDENT令牌的信息(它们或多或少的作用{以及}在许多其他语言中的作用)。Python声称是无上下文的,这对我来说意味着,至少词法分析器在创建令牌时不必关心它在流中的位置。Python的词法分析器如何在不知道先前字符的情况下就知道要构建特定长度的INDENT令牌(例如,上一行是换行符,因此开始为INDENT创建空间)?我问,因为我也需要知道这一点。 我的最后一个问题是最愚蠢的问题:为什么一个词法分析器甚至是必要的?在我看来,解析器可以逐个字符地找出它在哪里以及它期望什么。词法分析器是否增加了简单性的好处?
14 python  parsing  lexer 

1
根据语法编写词法分析器时应遵循的步骤是什么?
在阅读有关语法,词法分析器和语法分析器的澄清问题的答案时,答案指出: BNF语法包含词法分析和解析所需的所有规则。 这对我来说有点奇怪,因为直到现在,我一直认为词法分析器根本不基于语法,而解析器则很大程度上基于语法。在阅读了许多有关编写词法分析器的博客文章之后,我得出了这个结论,而从来没有人使用1 EBNF / BNF作为设计基础。 如果词法分析器以及解析器都基于EBNF / BNF语法,那么如何使用该方法创建词法分析器呢?也就是说,如何使用给定的EBNF / BNF语法构造词法分析器? 我见过很多,很多的职位,应对写的用EBNF / BNF作为指导或蓝图解析器,但我已经遇到没有到目前为止,显示与词法分析器的设计相当。 例如,采用以下语法: input = digit| string ; digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; string = '"', { all characters - '"' …

5
没有正则表达式的词法分析
我一直在用各种高级语言(Python,PHP,Javascript等)查看一些词法分析器,它们似乎都以一种或另一种形式使用正则表达式。尽管我确定正则表达式可能是实现此目的的最佳方法,但我想知道是否有任何方法可以在没有正则表达式的情况下实现基本词法分析,也许是某种直接的字符串解析等。 是的,是否可以在不使用任何形式的正则表达式的情况下,以更高级的语言*实现某种基本词汇? *高级语言是Perl / PHP / Python / Javascript等。我敢肯定,有一种方法可以用C语言实现
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.