【问题标题】:Pseudocode interpreter?伪代码解释器?
【发布时间】:2011-04-11 21:09:09
【问题描述】:

和 SO 上的许多人一样,我经常用几种语言写作。当涉及到计划的东西时,(甚至回答一些 SO 问题),我实际上是用一些未指定的混合语言思考和写作的。虽然我曾经被教导使用流程图或类似 UML 的图表来做到这一点,但回想起来,我发现 "my" 伪代码语言具有 CPythonJavabashMatlabperlBasic。我似乎无意识地选择了最适合表达概念/算法的成语。

常见的习惯用法可能包括用于范围的类 Java 大括号、pythonic 列表推导或缩进、类 C++ 继承、C# 样式 lambda、类 matlab 切片和矩阵运算。

我注意到人们实际上很容易准确地识别出我正在尝试做的事情,而且人们很容易智能地翻译成其他语言。当然,这一步涉及到考虑极端情况,以及每种语言表现特殊的时刻。

但实际上,这些语言中的大多数共享关键字和库函数的子集,它们的行为通常相同 - 数学函数、类型名称、while/for/if 等。显然我必须排除许多“奇怪”的语言,如 lisp、APL 派生类,但是...

所以我的问题是,

  1. 是否已经存在识别文本文件的编程语言的代码? (与 eclipse 的语法树或 google translate 的语言猜测功能相比,这肯定是一个更简单的任务,对吧?)事实上,SO 语法高亮器会做这样的事情吗?

  2. 是否理论上可能创建一个解释器或编译器来识别您在任何时候使用的语言习语并(可能“智能地”)执行或转换为可运行的形式.并标记我的语法在行为方面模棱两可的极端情况。我看到的直接困难包括:知道何时在缩进相关模式和大括号相关模式之间切换,识别有趣的运算符(如*pointer vs *kwargs)以及知道何时使用列表和类似数组的表示。

  3. 是否存在可以管理这种灵活口译的语言或口译员?

  4. 我是否错过了实现这一目标的明显障碍?

编辑

感谢大家的回答和想法。我正计划编写一个基于约束的启发式翻译器,可能“解决”预期含义的代码并翻译成真正的 python 代码。它会注意到来自许多常用语言的关键字,并将使用句法线索来消除人类意图的歧义——比如空格、括号、可选的辅助词(如letthen)、以前如何使用变量的上下文等,以及常见的知识约定(如大写名称,i 表示迭代,以及对变量/方法命名的一些简单的有限理解,例如包含单词getasynchronouscountlastpreviousmy 等) .在真正的伪代码中,变量命名与操作本身一样具有信息量!

使用这些线索,它将为每个操作的实现创建假设(例如基于 0/1 的索引、何时应捕获或忽略异常、哪些变量应为 const/global/local、从何处开始和结束执行,以及哪些位应该在单独的线程中,请注意数字单位何时匹配/需要转换)。每个假设都有一个给定的确定性 - 程序将列出每个语句的假设,因为它会将您编写的内容变成可执行的!

对于每个假设,如果您不喜欢最初的解释,您可以“澄清”您的代码。图书馆问题非常有趣。我的翻译器,就像一些 IDE 一样,会读取所有模块中可用的所有定义,使用一些关于哪些类/方法最常使用以及在什么上下文中使用的统计数据,然后猜测! (在程序中添加一个注释,说明它为什么会这样猜测......)我猜它应该尝试执行所有内容,并警告你它不喜欢什么。它应该允许任何事情,但如果您有歧义,请让您知道几种替代解释是什么。

它肯定需要一段时间才能处理像@Albin Sunnanbo 的ImportantCustomer 示例这样不寻常的示例。但我会让你知道我的进展如何!

【问题讨论】:

  • 你知道为什么很多编程语言可以用 LL(1) 解析器解析(即只查看下一个标记),而自然语言解析仍然不起作用吗?编程语言(甚至 Perl)具有与某些语法相关的固定语义。您正在要求一个程序读取随机的胡言乱语并构成作者所想到的语义。您不妨要求一个强大的 AI。
  • 我一直认为this 是一个相当不错的伪代码解释器
  • 我讨厌成为反对者,因为我们在这个领域没有足够的疯狂想法。但即使这可行,使用起来也会令人不愉快,原因与 AppleScript 使用起来不愉快的原因相同。您实现的最终混合语言将是高度非紧凑的:很难预测任何事情会做什么,也很难弄清楚如何指定给定的行为。从历史上看,紧凑、易于建模的语言已经战胜了复杂的语言。
  • 我想最实用的步骤是设计你自己的语言,采用你喜欢的所有这些特性,然后为它构建一个解释器。与其尝试为每个程序段识别和应用不同的解析器,不如设计一种具有支持这些特性的统一且一致的语法的语言。
  • Yukihiro Matsumoto 也有同样的问题。他在大多数语言中都有他喜欢的东西(从 BASIC 到 Pascal 到 lisp),但不是所有语言都包含在一种语言中。他的解决方案?发明了他自己的伪代码语法,结合了他喜欢的所有想法,然后为它编写了一个解释器。结果:红宝石。就像 Matz 刚开始时所做的那样,您似乎已经有了语法/语义。就像你疯狂的混合语言对你来说很自然一样,Ruby 是一种由伪代码转换为真实代码的风格,对 Matz 来说很自然。我不是说使用 Ruby。我是说写一个解释器。

标签: algorithm language-agnostic artificial-intelligence interpreter pseudocode


【解决方案1】:

我认为这对于除了玩具示例和严格的数学算法之外的所有内容都毫无用处。对于其他一切,语言不仅仅是语言。围绕这些语言有很多标准库和整个环境。我认为我编写的库调用行数几乎与编写“实际代码”一样多。

在 C# 中有 .NET Framework,在 C++ 中有 STL,在 Java 中有一些 Java 库,等等。

这些库之间的差异太大而不仅仅是语法上的细微差别。


已经尝试将不同语言的语言结构统一为“统一语法”。这被称为4GL 语言,但从未真正接受过。

作为旁注,我看到了一个关于页面长的代码示例,它可以作为 c#、Java 和 Java 脚本代码有效。这可以作为无法确定实际使用的语言的示例。

编辑:

此外,伪代码的全部目的是它不需要以任何方式编译。您编写伪代码的原因是创建一个“草图”,无论您喜欢多么草率。
foreach c in ImportantCustomers{== OrderValue >=$1M}
    SendMailInviteToSpecialEvent(c)

现在告诉我它是什么语言并为此编写一个解释器。

【讨论】:

    【解决方案2】:
    1. 检测所使用的编程语言:Detecting programming language from a snippet
    2. 我认为应该可以。我认为,可以利用 1. 中的方法来做到这一点。我会尝试迭代地执行它:检测代码的第一行/子句中使用的语法,根据该检测将其“编译”为中间形式,以及任何重要的语法(例如开始/结束包装器)。然后是下一行/子句等。基本上编写一个解析器来尝试识别每个“块”。歧义可以通过相同的算法进行标记。
    3. 我怀疑这是否已经完成......似乎是学习写作的认知负荷,例如与尝试调试解释器失败的情况相比,python 兼容的伪代码要容易得多。
    4. 一个。我认为最大的问题是大多数伪代码在任何语言中都是无效的。例如,我可能会在一段伪代码中完全跳过对象初始化,因为对于人类读者来说,推断几乎总是很简单。但是对于您的情况,它可能在选择的语言语法中完全无效,并且可能无法自动确定,例如对象的类(它甚至可能不存在)。等等
      湾。我认为你能期望的最好的解释器是只为你的伪代码“工作”(受 4a 限制)的解释器,没有其他人的。

    请注意,我认为 4a,4b 不一定是它成为可能的障碍。我只是认为它对任何实际目的都没有用。

    【讨论】:

    • 要准确解析伪代码,您需要生成一个可以处理歧义语法的解析器。使用Earley parser generator 很容易做到这一点。
    【解决方案3】:

    识别程序所使用的语言真的没什么大不了的。识别 sn-p 的语言更加困难,识别没有明确分隔的 sn-ps(如果四行是 Python,下一行是 C 或 Java,你会怎么做?)将非常困难。

    假设您将行分配给正确的语言,那么进行任何类型的编译都需要针对所有可以合作的语言的专门编译器。这本身就是一项了不起的工作。

    此外,当您编写伪代码时,您不必担心语法。 (如果是,那你就做错了。)你最终会得到根本无法编译的代码,因为它不完整,甚至是矛盾的。

    而且,假设您克服了所有这些障碍,您对伪代码按照您的想法进行解释的把握有多大?

    您将拥有一种新的计算机语言,您必须用它编写正确的程序。这将是一种庞大且模棱两可的语言,很难正确使用。使用时需要非常小心。这几乎正​​是您在伪代码中不想要的。伪代码的价值在于你可以快速勾勒出你的算法,而不用担心细节。那将完全丢失。

    如果您想要一门易于编写的语言,请学习一门。 Python 是一个不错的选择。使用伪代码来勾勒出应该如何进行处理,而不是作为一种可编译的语言。

    【讨论】:

      【解决方案4】:

      我感觉 2. 的答案是否定的。我需要证明它是错误的只是一个代码 sn-p,它可以由一个称职的程序员以多种方式解释。

      【讨论】:

      • 当然这可以通过适当的工具发现,并且像我建议的那样“标记为模棱两可”?或不? C 等的编译器对语言内的歧义有规则;为什么没有针对多种语言的此类规则?如果这样的检查规则可用,即使我们用“标准”语言进行编程也可能会改进,因为编译器会采用 language-dependent 技巧。
      • 不过,there are several programs 可以自动识别编程语言。
      【解决方案5】:

      一种有趣的方法是“随用随输入”的伪代码解释器。也就是说,您可以预先设置要使用的语言,然后它会在您键入时尝试将伪代码实时转换为真实代码。可以使用交互式工具来澄清模棱两可的东西并允许更正。该机制的一部分可能是转换器尝试匹配的代码库。随着时间的推移,它可以根据特定用户的习惯学习和调整其翻译。

      在大多数情况下,一直在编程的人可能更喜欢只使用该语言。但是,我认为以上内容对学习者、“非程序员程序员”(例如科学家)来说是一个巨大的福音,并且可以用于与各种语言和技能水平的程序员进行头脑风暴会议。

      -尼尔

      【讨论】:

        【解决方案6】:

        需要为解释人工输入的程序提供“我不知道”的选项。语言 PL/I 是一个著名的系统示例,该系统旨在为任何类似于计算机程序的事物找到合理的解释,当它猜错时可能会造成严重破坏:请参阅 http://horningtales.blogspot.com/2006/10/my-first-pli-program.html

        请注意,在后来的 C++ 语言中,当它解决可能的歧义时,它会限制它尝试的类型强制的范围,并且如果没有唯一的最佳解释,它将标记错误。

        【讨论】:

        • 我对我使用的 PL/I 编译器的回忆是,它会在出现错误的情况下尝试通过编译传递,但任何错误都会导致它在此之后停止。鉴于将代码输入编译器需要操作员将一副纸牌物理加载到机器中,因此希望从每次提交中获得尽可能多的有用诊断信息,即使这意味着编译器也会输出很多有用的信息那些。与早期的 Borland 编译器非常不同,早期的 Borland 编译器只会在第一个错误处停止(但几乎没有时间到达那里)。
        【解决方案7】:

        代码是否已经存在 识别编程语言 文本文件?

        是的,Unix file 命令。

        (当然这一定是一个少 比eclipse的语法复杂的任务 树或比谷歌翻译的 语言猜测功能,对吧?)在 事实上,SO 语法高亮 做这样的事吗?

        据我所知,SO 有一个千篇一律的语法高亮器,它试图结合每种主要语言的关键字和注释语法。有时它会出错:

        def median(seq):
            """Returns the median of a list."""
            seq_sorted = sorted(seq)
            if len(seq) & 1:
                # For an odd-length list, return the middle item
                return seq_sorted[len(seq) // 2]
            else:
                # For an even-length list, return the mean of the 2 middle items
                return (seq_sorted[len(seq) // 2 - 1] + seq_sorted[len(seq) // 2]) / 2
        

        请注意,SO 的荧光笔假定 // 开始一个 C++ 样式的注释,但在 Python 中它是整数除法运算符。

        如果您尝试将多种语言合二为一,这将是一个主要问题。如果同一个标记在不同语言中具有不同的含义,你会怎么做?类似的情况有:

        • ^ 是像 BASIC 中的幂运算,还是像 C 中的按位异或?
        • || 是像 C 中的逻辑 OR,还是像 SQL 中的字符串连接?
        • 什么是1 + "2"?是数字转换成字符串(给出“12”),还是字符串转换成数字(给出 3)?

        有没有语言或翻译 存在,可以管理这个 一种灵活的口译?

        在另一个论坛上,我听说了一个编译器(IIRC,for FORTRAN)的故事,它可以编译任何程序而不管语法错误。如果你有这条线

        = Y + Z
        

        无论您的程序中是否有X,编译器都会识别出缺少变量并自动将语句转换为X = Y + Z

        这个程序员的习惯是用一行连字符开始注释块,像这样:

        C ----------------------------------------
        

        但是有一天,他们忘记了开头的 C,编译器在它认为是减法运算符之间添加几十个变量时感到窒息。

        “灵活解析”并不总是一件好事。

        【讨论】:

        • 感谢所有这些示例! Vv 有趣且对我将要做的事情有用。好吧 - 所有这些都是我所说的“不灵活解析”的例子!因此,^ 的含义取决于上下文 - 通过您在其他地方使用变量的方式猜测 - 例如与文件后面的其他逻辑操作/标志,或者它是否用作绘图坐标等。基本上,人类很少遇到问题知道伪代码的含义。所以编译器会提醒你哪里有歧义,做了哪些假设,为什么,如果意思很明显,你是想澄清还是留下。
        【解决方案8】:

        要创建“伪代码解释器”,可能需要设计一种允许用户对其语法进行自定义扩展的编程语言。已经有几种编程语言具有此功能,例如CoqSeed7AgdaLever。一个特别有趣的例子是Inform 编程语言,因为它的语法本质上是“结构化英语”。

        Coq programming language 允许“syntax extensions”,因此可以扩展语言以解析新的运算符:

        Notation "A /\ B" := (and A B).

        同样,Seed7 编程语言可以扩展为使用“structured syntax definitions”解析“伪代码”。 Seed7中的while循环是这样定义的:

        syntax expr: .while.().do.().end.while is -> 25;

        或者,也可以“训练”statistical machine translation 系统将伪代码翻译成真正的编程语言,尽管这需要大量的 parallel texts 语料库。

        【讨论】:

          猜你喜欢
          • 2012-07-20
          • 1970-01-01
          • 1970-01-01
          • 2014-08-19
          • 2015-03-23
          • 1970-01-01
          • 1970-01-01
          • 2016-06-13
          • 1970-01-01
          相关资源
          最近更新 更多