Walter Bright使用“冗余”这个词......或者“哎呀这意味着什么?”

时间:2010-08-19 16:21:18

标签: parsing programming-languages error-handling d semantics

所以我正在阅读Walter Bright关于Bitwise(http://www.bitwisemag.com/copy/programming/d/interview/d_programming_language.html)中D语言的采访,我遇到了关于语言解析的非常有趣的引用:

  

然而,从理论角度来看,能够生成良好的诊断需要语法中存在冗余。冗余用于猜测预期的内容,冗余越多,猜测的可能性就越大。它就像英语一样 - 如果我们偶尔拼写错误,或者如果一个单词缺失,冗余使我们能够正确地猜出其含义。如果语言中没有冗余,则任何随机字符序列都是有效的程序。

现在我正试图弄清楚当他说“冗余”时他意味着什么。

我几乎无法绕过最后一部分,在那里他提到可以使用一种语言“任何随机的字符序列都是有效的程序”。我被告知有三种错误:句法,运行时和语义。是否存在唯一可能的错误是语义的语言?这样的集会吗?机器代码怎么样?

8 个答案:

答案 0 :(得分:24)

我会关注为什么(我认为)Walther Bright认为redunancy很好。我们以XML为例。这个片段:

<foo>...</foo>

具有冗余,如果我们使用S-Expressions,则结束标记是冗余的:

(foo ...)

它更短,并且程序员不必更频繁地键入foo来理解该片段。减少冗余。但它有缺点,例如http://www.prescod.net/xml/sexprs.html显示:

(document author: "paul@prescod.net"
    (para "This is a paragraph " (footnote "(better than the one under there)" ".")
    (para "Ha! I made you say \"underwear\"."))


<document author="paul@prescod.net">
<para>This is a paragraph <footnote>(just a little one).</para>
<para>Ha! I made you say "underwear".</para>
</document>

在两者中,缺少脚注的结束标记/结束标记。只要解析器看到</para>,xml版本就会无效。 S-Expression只在文档末尾无效,并且只有在其他地方没有不需要的结束时才会失效。因此,在某些情况下,redunancy确实有助于udnerstand作者的意思(并指出他表达错误的方式)。

答案 1 :(得分:10)

汇编语言(大多数汇编语言,完全不是) - 它们的语法非常严格,大多数随机字符串都会被诊断为错误。

机器代码更接近。由于没有涉及从“源”到“对象”代码的转换,所有错误都是语义的,而不是语法的。大多数处理器确实具有它们拒绝的各种输入(例如,执行“坏操作码”陷阱/中断)。您可能会争辩说,在某些情况下,这将是语法(例如,根本无法识别的操作码),其他语义是语义的(例如,该指令不允许的一组操作数)。

对于那些记得它的人来说,TECO因为为几乎任何可能的输入分配一些含义而闻名(臭名昭着?),所以它几乎是一样的。一个有趣的挑战是弄清楚如果你输入(例如)你的名字会发生什么。

答案 2 :(得分:9)

nglsh nclds ll srts of xtr ltrs t mk it ezr t read

答案 3 :(得分:8)

好吧,使用C#中的一个例子(因为我不知道D)。如果你有一个带抽象方法的类,那么类本身必须标记为abstract:

public abstract class MyClass
{
    public abstract MyFunc();
}

现在,编译器自动将MyClass标记为抽象(这是C ++处理它的方式)是微不足道的,但是在C#中,你必须明确地这样做,这样你的意图就清楚了。

virtual方法类似。在C ++中,如果在基类中声明virtual,则方法在所有派生类中自动为虚拟。在C#中,该方法必须明确标记为override,因此不会混淆您想要的内容。

答案 4 :(得分:5)

我认为他在谈论语言中的句法结构以及如何解释它们。例如,考虑使用多种语言呈现的简陋的“if”语句。

在bash(shell脚本)中,它看起来像这样:

if [ cond ]; then
  stmts;
elif [ other_cond ]; then
  other_stmts;
else
  other_other_stmts;
fi
C中的

(带有单个参数,没有花括号):

if (cond)
  stmt;
else if (other_cond)
  other_stmt;
else
  other_other_stmt;

你可以看到,在bash中,if语句的语法结构比C中的语法结构要多得多。实际上,bash中的所有控制结构都有自己的结束分隔符(例如if/then/fi,{{ 1}},for/do/done,...),而在C中,大括号随处可见。这些独特的分隔符消除了代码含义的歧义,从而提供了解释器/编译器可以诊断错误条件并将其报告给用户的上下文。

然而,有一个权衡。程序员通常更喜欢简洁的语法(la C,Lisp等)来详细说明语法(la Pascal,Ada等)。但是,他们也更喜欢包含行/列号和建议分辨率的描述性错误消息。这些目标当然是相互矛盾的 - 你不能吃蛋糕并且吃掉它(至少,在保持编译器/解释器的内部实现简单的同时)。

答案 5 :(得分:4)

这意味着语法包含的信息比编码工作程序所需的信息多。一个例子是函数原型。正如K&amp; R C向我们展示的那样,它们是多余的,因为编译器可以让调用者按下你想要的任何参数,然后让函数弹出正确的参数。但是C ++和其他语言强制要求它们,因为它们可以帮助编译器检查你是否以正确的方式调用函数。

另一个例子是在使用变量之前声明变量的要求。有些语言有这个,有些则没有。它显然是多余的,但它通常有助于防止错误(例如拼写错误,使用已删除的变量)。

答案 6 :(得分:3)

我认为更好的冗余示例就像int a[10] =。此时,编译器知道接下来会发生什么,一个int数组初始化器,并且如果后面的内容不是int数组初始化器,则可以提出相应的错误消息。如果语言语法说任何事都可以跟int a[10]一起,那么编译器就很难找出问题。

答案 7 :(得分:1)

  

然后任何随机字符序列都是有效的程序。

虽然不是“任何随机序列有效”,但请考虑Perl和正则表达式。它们非常短的语法使无效字符更容易通过句法和语义分析。