Определение языка программирования по фрагменту - PullRequest
109 голосов
/ 24 января 2009

Как лучше всего определить, какой язык программирования используется во фрагменте кода?

Ответы [ 17 ]

98 голосов
/ 24 января 2009

Я думаю, что метод, используемый в фильтрах спама, будет работать очень хорошо. Вы разбили фрагмент на слова. Затем вы сравниваете вхождения этих слов с известными фрагментами и вычисляете вероятность того, что этот фрагмент написан на языке X для каждого интересующего вас языка.

http://en.wikipedia.org/wiki/Bayesian_spam_filtering

Если у вас есть базовый механизм, то очень легко добавлять новые языки: просто обучите детектор с помощью нескольких фрагментов на новом языке (вы можете использовать его для проекта с открытым исходным кодом). Таким образом, он узнает, что «System», скорее всего, появится в фрагментах C #, а «put» - в фрагментах Ruby.

Я фактически использовал этот метод, чтобы добавить определение языка к фрагментам кода для программного обеспечения форума. Это работало 100% времени, за исключением неоднозначных случаев:

print "Hello"

Позвольте мне найти код.

Я не смог найти код, поэтому сделал новый. Это немного упрощенно, но это работает для моих тестов. В настоящее время, если вы добавляете в него гораздо больше кода Python, чем кода Ruby, вероятно, он скажет, что этот код:

def foo
   puts "hi"
end

- это код Python (хотя на самом деле это Ruby). Это потому, что в Python тоже есть ключевое слово def. Так что, если он видел 1000x def в Python и 100x def в Ruby, он все равно может сказать Python, даже если puts и end специфичны для Ruby. Вы можете исправить это, отслеживая количество слов, встречающихся в каждом языке, и деля их где-то (или передавая одинаковое количество кода на каждом языке).

Надеюсь, это поможет вам:

class Classifier
  def initialize
    @data = {}
    @totals = Hash.new(1)
  end

  def words(code)
    code.split(/[^a-z]/).reject{|w| w.empty?}
  end

  def train(code,lang)
    @totals[lang] += 1
    @data[lang] ||= Hash.new(1)
    words(code).each {|w| @data[lang][w] += 1 }
  end

  def classify(code)
    ws = words(code)
    @data.keys.max_by do |lang|
      # We really want to multiply here but I use logs 
      # to avoid floating point underflow
      # (adding logs is equivalent to multiplication)
      Math.log(@totals[lang]) +
      ws.map{|w| Math.log(@data[lang][w])}.reduce(:+)
    end
  end
end

# Example usage

c = Classifier.new

# Train from files
c.train(open("code.rb").read, :ruby)
c.train(open("code.py").read, :python)
c.train(open("code.cs").read, :csharp)

# Test it on another file
c.classify(open("code2.py").read) # => :python (hopefully)
26 голосов
/ 13 марта 2012

Определение языка решается другими:

Подход Олоха: https://github.com/blackducksw/ohcount/

Подход Гитхуба: https://github.com/github/linguist

7 голосов
/ 21 марта 2010

Вы можете найти здесь несколько полезных материалов: http://alexgorbatchev.com/wiki/SyntaxHighlighter. Алекс потратил много времени на то, чтобы понять, как анализировать большое количество разных языков и каковы основные синтаксические элементы.

6 голосов
/ 27 февраля 2018

Guesslang является возможным решением:

http://guesslang.readthedocs.io/en/latest/index.html

Есть также SourceClassifier:

https://github.com/chrislo/sourceclassifier/tree/master

Я заинтересовался этой проблемой после нахождения некоторого кода в статье блога, который я не смог идентифицировать. Добавление этого ответа, так как этот вопрос был первым поисковым хитом для «определения языка программирования».

5 голосов
/ 24 января 2009

Это очень сложно, а иногда и невозможно. С какого языка этот короткий фрагмент?

int i = 5;
int k = 0;
for (int j = 100 ; j > i ; i++) {
    j = j + 1000 / i;
    k = k + i * j;
}

(Подсказка: это может быть любой из нескольких.)

Вы можете попытаться проанализировать различные языки и попытаться решить, используя частотный анализ ключевых слов. Если в тексте встречаются определенные наборы ключевых слов с определенными частотами, вполне вероятно, что этот язык - Java и т. Д. Но я не думаю, что вы получите что-то, что полностью защищает от ошибок, поскольку вы могли бы назвать, например, переменную в C тем же именем в качестве ключевого слова в Java, и анализ частоты будет одурачен.

Если вы поднимитесь на ступеньку сложности, вы можете искать структуры, если одно ключевое слово всегда идет после другого, это даст вам больше подсказок. Но это также будет намного сложнее спроектировать и реализовать.

5 голосов
/ 12 июня 2012

Альтернативой является использование highlight.js , который выполняет подсветку синтаксиса, но использует показатель успешности процесса выделения для идентификации языка. В принципе, любая кодовая база подсветки синтаксиса может использоваться таким же образом, но хорошо в highlight.js то, что определение языка считается функцией и используется для целей тестирования .

ОБНОВЛЕНИЕ: Я попробовал это, и это не сработало. Сжатый JavaScript полностью запутал его, то есть токенизатор чувствителен к пробелам. Как правило, просто подсчет хитов не кажется очень надежным. Более сильный синтаксический анализатор или, возможно, непревзойденное количество разделов может работать лучше.

3 голосов
/ 24 января 2009

Во-первых, я бы попытался найти конкретные клавишные инструменты языка, например

"package, class, implements "=> JAVA
"<?php " => PHP
"include main fopen strcmp stdout "=>C
"cout"=> C++
etc...
2 голосов
/ 24 января 2009

Это будет зависеть от того, какой у вас фрагмент кода, но я бы проверил его через серию токенизаторов и посмотрел, с каким BNF какого языка он подходит.

1 голос
/ 08 июня 2015

Мне нужно было это, поэтому я создал свой собственный. https://github.com/bertyhell/CodeClassifier

Его очень легко расширить, добавив обучающий файл в нужную папку. Написано в C #. Но я думаю, что код легко конвертируется на любой другой язык.

1 голос
/ 05 апреля 2012

Prettify - это пакет Javascript, который отлично справляется с обнаружением языков программирования:

http://code.google.com/p/google-code-prettify/

В основном это подсветка синтаксиса, но, вероятно, есть способ извлечь часть обнаружения для обнаружения языка из фрагмента.

...