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

标签 c++ perl text-processing language-recognition

这是我最近的问题(Code for identifying programming language in a text file)的跟进。我真的很感谢我收到的所有答案,这对我很有帮助。 我完成此任务的代码非常有效,可以快速,合理地准确地工作。

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

现在,我想做得更好,并在识别质量上有所作为。 问题是(很多语言的分数很小,但是没有什么比我的阈值高)的原因常常使我变得“未知”。经过一些调试,研究等,我发现这可能是由于事实,所有单词都被认为是相等的。这意味着,例如,看到“#include”与看到“while”具有相同的效果-两者都表明它可能是c/c++(我现在忽略了“while”在许多其他示例中使用的事实语言),但当然,在较大的.cpp文件中,可能会有大量的“while”,但大多数情况下只有少数“#include”。

因此忽略了“#include”更重要的事实,因为我无法提出一种好的方法来识别一个单词是否比另一个单词更重要。 现在请记住,创建数据的脚本非常愚蠢,它只是一个单词直方图,并且为每个选定的单词分配一个分数1。它甚至不查看单词(因此,如果出现“#& |?/”通常会被选作一个好词)。

我也想让数据创建部分完全自动化,所以没有人应该去看数据并更改它们,更改分数,更改单词等。所有的“brainz”都应该在脚本和cpp程序中。

有人建议如何识别关键字,或更笼统地说,重要的单词吗? 有些事情可能会有所帮助:我知道每个单词的出现次数和总单词数(因此可以计算比率)。由于直方图脚本通常会输入“continue;”,因此我还考虑过擦除;等字符。结果,但重要的词是“继续”。最后说明:所有相等性检查均进行完全匹配-没有子字符串,区分大小写。这主要是因为速度,但是子字符串可能会有所帮助(或伤害,我不知道)...

注意:感谢所有愿意回答的人,您对我有很大帮助。

我的工作即将完成,因此我将描述为取得良好效果所做的工作。

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

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

最佳答案

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

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

现在,一旦意识到这一点,您还将看到分类器需要进行哪些培训:不是样本文件的某些随机方面,而是将两种语言区分开的方法。因此,当您解析了C样本和C++样本后,您将看到#include并未将它们分开。但是,classtemplate在C++中将更加常见。另一方面,#include确实区分C++和Java。

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

这也确定了另一个分类规则:SQL通常在行首使用--,而在C语言中则通常出现在其他地方。因此,将分类器也考虑到上下文对于您的分类器可能很有用。

关于c++ - 识别(编程)语言的关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3658713/

相关文章:

javascript - C# Regex 性能纯相对 JS

从日语源估计英语翻译单词数量的算法

python - 读取输入文件的第二行和第四行并使用 python 执行文本处理

c++ - 基于 Linux 时间样本的分析器

c++ - 为什么我的 rand() 数字显示为 0?

c++ - Eclipse C++ 错误

perl - 在 Ubuntu 中自动安装基于包的 Perl 模块

perl - 如何在 native Perl 代码中复制 cat/sort/uniq?

mysql - 如何打印 Perl 的 DBI 填充占位符后执行的 SQL 查询?

c++ - 如何使用fftw Guru界面