Parsing 解析源代码-不同语言的唯一标识符?

Parsing 解析源代码-不同语言的唯一标识符?,parsing,language-agnostic,programming-languages,Parsing,Language Agnostic,Programming Languages,我正在构建一个应用程序,它接收源代码作为输入,并分析代码的几个方面。它可以接受来自许多通用语言的代码,例如C/C++、C#、Java、Python、PHP、Pascal、SQL等(但许多语言不受支持,例如Ada、Cobol、Fortran)。一旦知道了语言,我的应用程序就知道该做什么(我对不同的语言有不同的处理程序) 目前,我要求用户输入编写代码所用的编程语言,这很容易出错:尽管用户知道编程语言,但有一小部分人(在极少数情况下)只是因为鲁莽而点击了错误的选项,这破坏了系统(即我的分析失败) 在我

我正在构建一个应用程序,它接收源代码作为输入,并分析代码的几个方面。它可以接受来自许多通用语言的代码,例如C/C++、C#、Java、Python、PHP、Pascal、SQL等(但许多语言不受支持,例如Ada、Cobol、Fortran)。一旦知道了语言,我的应用程序就知道该做什么(我对不同的语言有不同的处理程序)

目前,我要求用户输入编写代码所用的编程语言,这很容易出错:尽管用户知道编程语言,但有一小部分人(在极少数情况下)只是因为鲁莽而点击了错误的选项,这破坏了系统(即我的分析失败)

在我看来,应该有一种方法可以从输入文本本身(在大多数情况下)看出语言是什么。几点注意:

  • 我收到的是纯文本而不是文件名,因此我不能使用扩展名作为提示
  • 用户不需要输入完整的源代码,也可以输入代码片段(即,可能不包括包含/导入部分)
  • 我很清楚,我选择的任何算法都不是100%可靠的,当然对于非常短的输入代码(例如,Python和Ruby都可以接受),在这种情况下,我仍然需要用户的帮助,但是我希望尽量减少用户在过程中的参与,以尽量减少错误
示例:

    如果文本包含“x> y()”,我可以肯定地知道它是C++(?)< /LI>
  • 如果文本包含“publicstaticvoidmain”,我可以肯定它是Java(?)
  • 如果文本包含“for x:=y to z do begin”,我可以肯定它是Pascal(?)
我的问题:

  • 您是否熟悉用于自动确定输入源代码的语言的标准库/方法
  • 我可以用什么独特的代码“标记”来区分一种语言和另一种语言
  • 我正在用Python编写代码,但我认为这个问题与语言无关

    谢谢

    一些想法:

    $x- >()在PHP中是有效的,因此如果您认为C++,则确保没有$符号(虽然我认为您可以在C结构中存储函数指针,因此也可以是C)。
    publicstaticvoidmain
    如果大小写正确,则为Java-writemain,且为C#。如果考虑到许多脚本语言或Pascal等不区分大小写的语言,这会变得复杂。另一方面,C#中的[]属性语法似乎相当独特

    您还可以尝试使用语言的关键字-例如,
    Option Strict
    End Sub
    是VB等的典型,而
    yield
    很可能是C;
    初始化
    /
    实现
    是对象Pascal/Delphi


    如果您的应用程序正在分析源代码,那么您的代码会尝试对每种语言都使用您的分析代码,如果失败的很严重,则是错误的语言:)

    Vim具有自动检测文件类型功能。如果下载vim源代码,您将找到一个/vim/runtime/filetype.vim文件


    对于每种语言,它都会检查文件的扩展名,对于其中一些语言(最常见),它还有一个可以从源代码中获取文件类型的函数。你可以看看。代码很容易理解,其中有一些非常有用的注释。

    我知道一个程序,它甚至可以在同一个文件中区分几种不同的语言。你可能会有一些想法,尽管我真的不知道他们是如何做到的

    一般来说,您可以寻找独特的图案:

    • 运算符可能是一个指示器,例如Pascal/Modula/Oberon的
      :=
      =>
      或C中的整个LINQ#
    • 关键字将是另一种,因为可能没有两种语言具有相同的关键字集
    • 标识符的大小写规则,假设代码是按照最佳实践编写的。可能是一条很弱的规则
    • 标准库函数或类型。特别是对于通常严重依赖它们的语言,例如PHP,您可能只需要使用一长串标准库函数
    您可以创建一组规则,如果匹配,每个规则都表示可能的语言集。交叉的结果列表将有希望得到你只有一种语言

    然而,这种方法的问题是,您需要进行标记化和比较标记(否则您无法真正知道什么是运算符,或者您在注释或字符串中是否找到了某些内容)。但是,每种语言的标记化规则也不同;仅仅以空格和标点符号分割所有内容可能不会产生非常有用的标记序列。您可以尝试几种不同的标记化规则(每种规则也都表示一组特定的语言),并使您的规则与指定的标记化匹配。例如,尝试在VB代码段中用一条注释查找一个带引号的字符串(用于尝试Pascal)可能会失败,但另一个标记器可能更幸运


    但是,既然您想执行分析,您可能已经有了支持的语言的解析器,所以您可以尝试在每个解析器中运行代码片段,并将其作为它将使用哪种语言的指示符(正如OregonGhost所建议的)。

    非常有趣的问题,我不知道是否可以通过代码片段来区分语言,但这里有一些想法:

    • 一种简单的方法是注意单引号:在某些语言中,它用作字符包装器,而在其他语言中,它可以包含整个字符串
    • 一元星号或一元符号与运算符表示它是C/C++/C#之一
    • Pascal是(给定语言中)唯一使用两个字符进行赋值的语言