繁体   English   中英

识别(编程)语言的关键字

[英]Identifying keywords of a (programming) language

这是我最近的问题( 用于识别文本文件中的编程语言的代码 )的后续内容 我非常感谢我得到的所有答案,这对我非常有帮助。 我完成此任务的代码已经完成,并且运行良好 - 快速且合理准确。

我使用的方法如下:我有一个“学习”perl脚本,通过对一组示例文件执行单词直方图来识别语言中最常用的单词。 然后由c ++程序加载这些数据,然后c ++程序检查给定的文本并根据找到的单词累积每种语言的分数,然后简单地检查哪种语言累积得分最高。

现在我想让它变得更好,并对识别质量有所了解。 问题是我经常得到“未知”的结果 (许多语言积累了一个小分数,但没有任何大于我的门槛)。 经过一些调试,研究等,我发现这可能是因为所有的单词被认为是平等的。 这意味着,例如看到“#include”与看到“while”具有相同的效果 - 两者都表明它可能是c / c ++(我现在忽略了“while”用于许多其他事实的事实当然,在较大的.cpp文件中,可能会有大量的“while”,但大多数时候只有少数“#include”。

因此,“#include”更重要的事实被忽略了,因为我无法想出如何确定一个词是否比另一个更重要的好方法。 现在请记住,创建数据的脚本是相当愚蠢的,它只是一个单词直方图,并且对于每个选择的单词,它指定的分数为1.它甚至没有查看单词(所以如果有一个“#&| ?/“在文件中经常被选为好词。”

此外,我希望数据创建部分完全自动化,因此没有人应该查看数据并更改它们,更改分数,更改单词等。所有“brainz”应该在脚本和cpp程序中。

是否有人建议如何识别关键词,或更一般地说,重要词? 一些可能有用的事情:我有每个单词的出现次数和总单词数(因此可以计算比率)。 我也考虑过删除像;等等字符,因为直方图脚本经常提出例如“继续”; 在结果中,重要的是“继续”。 最后一点:所有相等的检查都是完全匹配的 - 没有子串,区分大小写。 这主要是因为速度,但子串可能有帮助(或伤害,我不知道)...

注意:感谢所有打扰回答的人,你帮助了我很多。

我的工作几乎已经完成,所以我将描述我做了什么才能取得好成绩。

1)获得一个体面的训练集,来自不同来源的每种语言约30-50个文件,以避免编码风格偏差
2)编写一个执行单词直方图的perl脚本。 实施黑名单和白名单(下面有更多相关信息)
3)将伪造的单词添加到黑名单,如“许可证”,“该”等。这些通常在许可证信息的文件开头找到。
4)将每种语言最重要的五个单词添加到白名单中。 这些是在给定语言的大多数源代码中找到的单词,但不足以进入直方图。 例如,对于C / C ++,我在白名单中有:#include,#define,#ifdef,#ifnf和#endif。
5)强调文件的开始,因此在前50-100行中找到更多的单词
6)在进行单词直方图时,使用@words = split(/[\\s\\(\\){}\\[\\];.,=]+/, $_);对文件进行标记@words = split(/[\\s\\(\\){}\\[\\];.,=]+/, $_); 这应该适用于我认为的大多数语言(给我最好的结果)。 对于每种语言,最终结果中大约有10-20个最常用的单词。
7)当直方图完成后,删除黑名单中找到的所有单词并添加白名单中找到的所有单词
8)编写一个程序,以与脚本相同的方式处理文本文件 - 使用相同的规则进行标记。 如果在直方图数据中找到单词,请将点添加到正确的语言。 直方图中仅对应一种语言的单词应该添加更多的点,属于多种语言的单词应该添加更少的点。

欢迎评论。 目前在大约1000个文本文件中我得到80个未知数(主要是在非常短的文件上 - 主要是只有一两行的javascript)。 大约20个文件被识别错误。 文件大小约为11kB,范围从100字节到100字节(总共大约11MB)。 它需要一秒钟来处理它们,这对我来说已经足够了。

我认为你是从错误的角度来看待这个问题。 根据您的描述,听起来您正在构建分类器 一个好的分类器需要区分不同的类; 它不需要精确估计输入和最可能的类之间的对应关系。

实际上:您的分类器不需要精确评估某个输入与C ++的接近程度; 它只需要确定输入是否更像C而不是C ++。 这使您的工作变得更加容易 - 大多数当前“未知”的案例将接近一种或两种语言,即使它们没有超过您的基本阈值。

现在,一旦你意识到这一点,你也会看到你的分类器需要什么样的训练:不是样本文件的一些随机方面,而是两种语言的区别。 因此,当您解析了C样本和C ++样本时,您将看到#include不会将它们分开。 但是, classtemplate在C ++中会更常见。 另一方面, #include 确实区分了C ++和Java。

除了关键字之外,您还可以使用其他方面。 例如,最明显的是{ ,和;的频率; 同样是有区别的。 分类器的另一个非常有用的功能是针对不同语言的注释令牌。 当然,基本问题是自动识别它们。 再次,硬编码///*'--#! 因为伪关键字会有所帮助。

这也标识了另一个分类规则:SQL通常会在--行的开头,而在C中它通常会出现在其他地方。 因此,分类器也可以将上下文考虑在内。

使用Google代码搜索来学习关键字集的权重:C ++中的#include获得672.000次点击,Python只能达到5000次。

您可以通过查看总体语言的结果数来规范化结果:C ++提供大约770.000个文件,而Python返回120.000。

因此“#include”在Python文件中极为罕见,但几乎存在于每个C ++文件中。 (现在你仍然需要学会区分C ++和C.)剩下的就是对概率进行正确的推理。

您需要在查找数据中获得一些独占性。
在教授您期望的编程语言时,您应该搜索一种或几种语言的典型单词。 如果一个单词出现在同一语言的几个代码文件中,但出现在很少或没有其他语言文件中,则强烈建议使用该语言。
因此,通过选择一种语言或一组语言专用的单词,可以在查找侧计算单词的分数。 找到这些单词中的几个,并通过添加分数得到这些单词的交集,并找到您将拥有的语言。

在回答你的另一个问题时,有人推荐了一个天真的贝叶斯分类器 您应该实施此建议,因为该技术擅长根据区别特征进行分离。 你提到了while关键字,但这可能不太有用,因为有这么多语言使用它 - 而且贝叶斯分类器不会将它视为有用。

您问题的一个有趣部分是如何标记未知程序。 空白分隔的块是一个不错的粗略开始,但有意义的超出这个将是棘手的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM