什么是开始编写编程语言的好资源,而这不是上下文无关的?
我希望编写一种有趣的编程语言,但是我所看到的大部分资源都是用于编写上下文无关的语言,但是我希望编写一种像python一样使用缩进的语言,据我所知,它可以不受上下文限制。
解决方案
回答
我不知道任何教程/指南,但是我们可以尝试查看tinypy的源代码,它是python这样的语言的很小的实现。
回答
我们可能想阅读这篇有关解析Python的写得不错的文章,《 Python:关于缩进的神话》。
虽然我还没有尝试使用yacc之类的东西来编写上下文无关的解析器,但我认为使用条件词法分析器可以返回缩进更改标记(如url中所述)是可能的。
顺便说一下,这是来自python.org的官方python语法:http://www.python.org/doc/current/ref/grammar.txt
回答
在语言中使用缩进并不一定意味着该语言的语法不能与上下文无关。 IE。缩进将确定语句在哪个范围内存在。无论在哪个范围内定义,一条语句仍将是一条语句(作用域通常可以在语义解析期间通常由编译器/解释器的不同部分处理)。
这就是说antlr工具(http://www.antlr.org)是一个很好的资源。该工具的作者还编写了一本书,内容涉及使用antlr为语言创建解析器(http://www.pragprog.com/titles/tpantlr/the-definitive-antlr-reference)。有相当不错的文档和大量示例语法。
回答
仅仅因为一种语言使用了重要的缩进并不意味着它本质上是上下文相关的。例如,Haskell使用了重要的缩进,并且(据我所知)其语法是上下文无关的。
需要上下文相关语法的源代码示例可能是来自Ruby的以下代码段:
my_essay = << END_STR This is within the string END_STR << self def other_method ... end end
另一个示例是Scala的XML模式:
def doSomething() = { val xml = <code>def val <tag/> class</code> xml }
通常,上下文敏感的语言在任何精确意义上都难以想象,因此不那么常见。甚至Ruby和Scala都不算真正的数字,因为它们的上下文相关功能仅包含该语言的一小部分子集。如果我是你,我会按照灵感的指示来表达我的语法,然后担心以后再解析方法论。我想我们会发现,无论我们想出什么,都自然会与上下文无关,或者非常接近上下文。
最后一点,如果我们确实需要上下文相关的解析工具,则可以尝试一些不太严格的形式化技术。解析器组合器用于Scala的解析中。它们有一些令人讨厌的局限性(没有词法),但是它们并不是一个坏工具。像ANTLR这样的LL(*)工具似乎也更擅长表达这种"临时"解析转义。不要尝试将Yacc或者Bison与上下文相关的语法一起使用,它们对于严格表达此类概念非常严格。
回答
我建议我们手动编写解析器,在这种情况下,如果空格很大,则不会出现任何实际问题。
使用解析器生成器的主要问题是很难在解析器中获得良好的错误恢复。如果我们计划为语言实现IDE,那么良好的错误恢复对于使诸如Intellisence之类的功能至关重要。智慧始终适用于不完整的语法结构,并且解析器越能弄清用户要键入的结构,就可以提供更好的智能体验。
如果我们编写了一个手写的自上而下的解析器,则几乎可以实现所需的任何规则,并在所需的位置实现。这就是使错误恢复变得容易的原因。它还将使我们轻松实现大量的空白。我们可以简单地将当前缩进级别存储在解析器类中的变量中,并且当我们在换行符的列位置小于当前缩进级别的情况下遇到令牌时,可以停止解析块。同样,我们很可能会在语法中遇到歧义。广泛使用的大多数生产语言都有句法上的歧义。一个很好的例子是C语言中的泛型(表达式上下文中的" <"周围有歧义,它可以是"小于"运算符,也可以是"泛型参数列表"的开头)。在手写解析器中,解决此类歧义是微不足道的。我们可以在需要的地方添加一些不确定性,而对其余解析器的影响相对较小,
此外,因为我们是自己设计语言,所以应该假设它的设计将快速发展(对于某些带有标准委员会的语言,例如C ++,情况并非如此)。更改自动生成的解析器以处理歧义或者发展语言,可能需要我们对语法进行大量重构,这既烦人又耗时。手写解析器(尤其是自上而下的解析器)的更改通常非常本地化。
我要说的是,解析器生成器仅在以下情况下是一个不错的选择:
- 我们从不打算编写IDE,
- 该语言的语法非常简单,或者
- 我们需要非常快速的解析器,并且可以接受不良的用户体验
回答
我们读过Aho,Sethi,Ullman的文章:"编译器:原理,技术和工具"吗?这是一本古典语言参考书。
/艾伦
回答
如果我们以前从未编写过解析器,请从简单的事情开始。解析器令人惊讶地微妙,如果我们从未学习过编程语言的结构,则可能会遇到编写它们的各种麻烦。
读Aho,Sethi和Ullman(被称为"龙书")是一个不错的计划。与其他贡献者相反,我说我们应该首先使用更简单的解析器生成器(例如Yacc和Bison),并且只有在我们因为无法使用该工具执行某些操作而被烧毁时才应该继续尝试使用LL(* )解析器,如Antlr。
回答
上下文相关的语言?这个不缩进:Protium(http://www.protiumble.com)
回答
首先,我会通读一些有关该主题的文献,以使自己熟悉这个问题。 Aho等着的经典编译器书。 al。可能在数学和比较科学上比较繁重,但更具可理解性的文本是Hyman Crenshaw的"让我们构建编译器"文章。这是Crenshaw先生在80年代后期写回的一系列文章,这是有史以来编写者最不重视的文字。这种方法很简单而且很关键:Crenshaw先生展示了一种有效的" A"方法。我们可以在几个晚上的时间范围内轻松浏览内容,并更好地了解编译器的全部含义。需要注意的是,本文中的示例是用Turbo Pascal编写的,编译器发出了68K汇编程序。这些示例很容易移植到最新的编程语言,为此我推荐Python。但是,如果我们想按照示例进行操作,则至少需要Turbo Pascal 5.5和68K汇编器和仿真器。今天的文字仍然有意义,使用这些旧技术真的很有趣。我强烈建议将其作为任何有关编译器的第一篇文章。好消息是Python和Ruby之类的语言都是开源的,我们可以下载和研究C源代码,以便更好地了解它是如何完成的。
回答
简单来说,上下文无关的语法就是不需要符号表即可正确解析代码的语法。上下文相关的语法可以做到。
D编程语言是上下文无关语法的一个示例。 C ++是上下文相关的一种。 (例如,T * x是将x声明为指向T的指针,还是将T乘以x?我们只能通过在符号表中查找T来确定它是类型还是变量来辨别。)
空格与它无关。
D使用上下文无关的语法来极大地简化对其的解析,以便简单的工具可以对其进行解析(例如语法高亮显示编辑器)。
回答
如果我们真的想在语言设计和实现上大吃一惊,则可能需要在书架中添加以下内容:
- 编程语言语用学,Scott等。
- 编程语言中的设计概念,Turbak等。
- Grune等人的《现代编译器设计》。 (与Aho等人撰写的《龙书》相比,我偏爱于此)
Gentler的介绍,例如:
- Crenshaw的教程(由@'Jonas Gorauskas'在这里建议)
- 权威的ANTLR参考
- 马丁·福勒(Martin Fowler)最近在DSL方面的工作
我们还应该考虑实现语言。这是不同语言所提供的便利差异很大的领域之一。我们应该考虑使用LISP,F / OCaml和Gilad Bracha的新语言Newspeak等语言。
回答
"无上下文"是一个相对术语。大多数无上下文解析器实际上都解析该无上下文语言的超集,然后检查生成的解析树以查看其是否有效。例如,根据C的上下文无关文法,以下两个C程序是有效的,但是在上下文检查期间一个很快就会失败:
int main() { int i; i = 1; return 0; } int main() { int i; i = "Hello, world"; return 0; }
没有上下文,i =" Hello,world";
是一个完全有效的赋值,但是在上下文中我们可以看到类型都是错误的。如果上下文是" char * i;",那就可以了。因此,上下文无关的解析器将看不到该分配有任何问题。直到编译器开始检查类型(取决于上下文)后,它才能捕获错误。
可以用键盘产生的任何东西都可以解析为上下文无关的。至少我们可以检查所有使用的字符是否有效(仅包含可显示Unicode字符的所有字符串的集合是无上下文语法)。唯一的限制是语法的实用性以及对生成的分析树必须执行多少与上下文相关的检查。
诸如Python之类的与空格相关的语言使上下文无关语法没那么有用,因此以后需要进行更多上下文相关的检查(其中许多操作是在Python运行时通过动态类型完成的)。但是,在需要上下文相关检查之前,上下文无关的解析器仍然可以做很多事情。