Парсинг исходного кода - уникальные идентификаторы для различных языков? [закрытый]

Я бы сказал, не поймите исключение, если вы действительно не можете справиться с этим. И регистрация не считается обработкой ошибки. Лучше подать это кому-нибудь, кто может, бросив исключение.

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

11
задан Jonathan Leffler 17 July 2015 в 05:43
поделиться

14 ответов

Я думаю, вам никогда не следует полагаться на одну-единственную функцию, поскольку ее отсутствие во фрагменте (например, кто-то систематически использует WHILE вместо for) может вас смутить.

Также старайтесь держаться подальше от глобальных идентификаторов, таких как «ИМПОРТ», «МОДУЛЬ», «ЕДИНИЦА» или «ИНИЦИАЛИЗАЦИЯ / ФИНАЛИЗАЦИЯ», поскольку они могут не всегда существовать, быть необязательными в полных источниках и полностью отсутствовать во фрагментах.

Диалекты и подобные языки (например, Modula2 и Pascal) тоже опасны.

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

1
ответ дан 3 December 2019 в 01:45
поделиться

Vim has a autodetect filetype feature. If you download vim sourcecode you will find a /vim/runtime/filetype.vim file.

For each language it checks the extension of the file and also, for some of them (most common), it has a function that can get the filetype from the source code. You can check that out. The code is pretty easy to understand and there are some very useful comments there.

7
ответ дан 3 December 2019 в 01:45
поделиться

Very interesting question, I don't know if it is possible to be able to distinguish languages by code snippets, but here are some ideas:

  • One simple way is to watch out for single-quotes: In some languages, it is used as character wrapper, whereas in the others it can contain a whole string
  • A unary asterisk or a unary ampersand operator is a certain indication that it's either of C/C++/C#.
  • Pascal is the only language (of the ones given) to use two characters for assignments :=. Pascal has many unique keywords, too (begin, sub, end, ...)
  • The class initialization with a function could be a nice hint for Java.
  • Functions that do not belong to a class eliminates java (there is no max(), for example)
  • Naming of basic types (bool vs boolean)
  • Which reminds me: C++ can look very differently across projects (#define boolean int) So you can never guarantee, that you found the correct language.
  • If you run the source code through a hashing algorithm and it looks the same, you're most likely analyzing Perl
  • Indentation is a good hint for Python
  • You could use functions provided by the languages themselves - like token_get_all() for PHP - or third-party tools - like pychecker for python - to check the syntax

Summing it up: This project would make an interesting research paper (IMHO) and if you want it to work well, be prepared to put a lot of effort into it.

1
ответ дан 3 December 2019 в 01:45
поделиться

Самый надежный, но и самый трудоемкий способ - написать синтаксический анализатор для каждого языка и просто запустить их последовательно, чтобы увидеть, какой из них примет код. Это не сработает, если в коде есть синтаксические ошибки, и вам, скорее всего, придется иметь дело с таким кодом, люди действительно делают ошибки. Один из быстрых способов реализовать это - получить общие компиляторы для каждого поддерживаемого вами языка, просто запустить их и проверить, сколько ошибок они выдают.

Эвристика работает до определенного момента, и чем больше языков вы будете поддерживать, тем меньше помощи вы бы получили от них. Но для первых нескольких версий это хорошее начало, в основном потому, что оно быстро реализуется и в большинстве случаев работает достаточно хорошо. Вы можете проверить конкретные ключевые слова, имена функций / классов в API, которые часто используются, некоторые языковые конструкции и т. Д.

1
ответ дан 3 December 2019 в 01:45
поделиться

Как насчет частотного анализа слов (с изюминкой)? Анализируйте исходный код и классифицируйте его так же, как это делает спам-фильтр. Таким образом, когда в ваше приложение вводится фрагмент кода, который не может быть идентифицирован на 100%, вы можете указать ему наиболее близкие совпадения, из которых пользователь может выбрать - затем его можно будет ввести в вашу базу данных.

2
ответ дан 3 December 2019 в 01:45
поделиться

One program I know which even can distinguish several different languages within the same file is ohcount. You might get some ideas there, although I don't really know how they do it.

In general you can look for distinctive patterns:

  • Operators might be an indicator, such as := for Pascal/Modula/Oberon, => or the whole of LINQ in C#
  • Keywords would be another one as probably no two languages have the same set of keywords
  • Casing rules for identifiers, assuming the piece of code was writting conforming to best practices. Probably a very weak rule
  • Standard library functions or types. Especially for languages that usually rely heavily on them, such as PHP you might just use a long list of standard library functions.

You may create a set of rules, each of which indicates a possible set of languages if it matches. Intersecting the resulting lists will hopefully get you only one language.

The problem with this approach however, is that you need to do tokenizing and compare tokens (otherwise you can't really know what operators are or whether something you found was inside a comment or string). Tokenizing rules are different for each language as well, though; just splitting everything at whitespace and punctuation will probably not yield a very useful sequence of tokens. You can try several different tokenizing rules (each of which would indicate a certain set of languages as well) and have your rules match to a specified tokenization. For example, trying to find a single-quoted string (for trying out Pascal) in a VB snippet with one comment will probably fail, but another tokenizer might have more luck.

But since you want to perform analysis anyway you probably have parsers for the languages you support, so you can just try running the snippet through each parser and take that as indicator which language it would be (as suggested by OregonGhost as well).

3
ответ дан 3 December 2019 в 01:45
поделиться

Some thoughts:

$x->y() would be valid in PHP, so ensure that there's no $ symbol if you think C++ (though I think you can store function pointers in a C struct, so this could also be C).

public static void main is Java if it is cased properly - write Main and it's C#. This gets complicated if you take case-insensitive languages like many scripting languages or Pascal into account. The [] attribute syntax in C# on the other hand seems to be rather unique.

You can also try to use the keywords of a language - for example, Option Strict or End Sub are typical for VB and the like, while yield is likely C# and initialization/implementation are Object Pascal / Delphi.

If your application is analyzing the source code anyway, you code try to throw your analysis code at it for every language and if it fails really bad, it was the wrong language :)

2
ответ дан 3 December 2019 в 01:45
поделиться

Вот вам идея. Для каждого из ваших N языков найдите несколько файлов на этом языке, чего-то вроде 10-20 на каждый язык будет достаточно, каждый не слишком короткий. Объедините все файлы на одном языке вместе. Назовите это lang1.txt. Заархивируйте его на lang1.txt.gz. У вас будет набор из N файлов langX.txt и langX.txt.gz.

Теперь возьмите нужный файл и добавьте его к каждому из файлов langX.txt, создав langXapp.txt и соответствующий сжатый langXapp.txt. .gz. Для каждого X найдите разницу между размером langXapp.gz и langX.gz. Наименьшая разница будет соответствовать языку вашего файла.

Отказ от ответственности: это будет работать достаточно хорошо только для более длинных файлов. Кроме того, это не очень эффективно. Но с другой стороны, вам не нужно ничего знать о языке, это полностью автоматически. И он может обнаруживать естественные языки и различать французский или китайский. На всякий случай :) Но основная причина, я просто думаю, что попробовать интересно :)

2
ответ дан 3 December 2019 в 01:45
поделиться

I think the problem is impossible. The best you can do is to come up with some probability that a program is in a particular language, and even then I would guess producing a solid probability is very hard. Problems that come to mind at once:

  • use of features like the C pre-processor can effectively mask the underlyuing language altogether
  • looking for keywords is not sufficient as the keywords can be used in other languages as identifiers
  • looking for actual language constructs requires you to parse the code, but to do that you need to know the language
  • what do you do about malformed code?

Those seem enough problems to solve to be going on with.

3
ответ дан 3 December 2019 в 01:45
поделиться

создайте общий токенизатор и затем примените к нему байесовский фильтр. Используйте существующую систему «пользователь ставит отметку» для его обучения.

7
ответ дан 3 December 2019 в 01:45
поделиться

Мой подход был бы следующим:

Создайте список строк или регулярных выражений (с и без учета регистра), где каждому элементу присвоен список языков, для которых этот элемент является индикатором:

  • class => C ++, C #, Java
  • interface => C #, Java
  • реализует => Java
  • [атрибут] => процедура C #
  • => Паскаль, Модула
  • создать таблицу / вставить / ... => SQL

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

Выигрывает язык с наибольшим количеством совпадений;)

2
ответ дан 3 December 2019 в 01:45
поделиться

В ответ на 2: если есть "#!" и имя переводчика в самом начале, тогда вы точно знаете, на каком языке. (Не могу поверить, что об этом никто не упомянул.)

1
ответ дан 3 December 2019 в 01:45
поделиться

Невозможно сделать это надежным, но я бы лично начал с операторов, поскольку они в большинстве случаев «высечены в камне» (я не могу сказать, что это верно для каждого языка так как знаю только ограниченный набор). Это могло бы значительно сузить круг, но не достаточно. Например, "->" используется во многих языках (по крайней мере, C, C ++ и Perl).

Я бы сделал что-то вроде этого:

Создайте список функций для каждого языка, это могут быть операторы, комментирующие стиль (поскольку большинство из них используют какой-либо легко обнаруживаемый символ или комбинацию символов).

Например: В некоторых языках есть строки, начинающиеся с символа «#», например C, C ++ и Perl. Используют ли в своем словаре другие люди, кроме первых двух, #include и #define? Если вы обнаружите этот символ в начале строки, язык, вероятно, один из них. Если символ находится в середине строки, язык, скорее всего, Perl.

Кроме того, если вы найдете шаблон: =, это сузит его до некоторых возможных языков.

И т.д.

Я бы сделал это. иметь двумерную таблицу с найденными языками и шаблонами, и после анализа я просто подсчитываю, какой язык имеет больше всего "хитов". Если бы я хотел, чтобы это было действительно умно, я бы дал каждой функции вес, который означал бы, насколько вероятно или маловероятно, что эта функция будет включена в фрагмент этого языка. Например, если вы можете найти фрагмент, который начинается с / * и заканчивается на * /, более чем вероятно, что это либо C, либо C ++.

Проблема с ключевыми словами заключается в том, что кто-то может использовать его как обычную переменную или даже внутри Комментарии. Их можно использовать в качестве решающих (например, слово «класс» гораздо более вероятно в C ++, чем в C, если все остальное равно), но вы не можете полагаться на них.

После анализа я бы предложил наиболее вероятное язык как выбор для пользователя с упорядоченным остальным, который также может быть выбран. Таким образом, пользователь согласится с вашим предположением, просто нажав кнопку, или он может легко переключить его.

гораздо более вероятно в C ++, чем в C, если все остальное равно), но вы не можете полагаться на них.

После анализа я бы предложил наиболее вероятный язык в качестве выбора для пользователя с упорядоченным остальным, который также быть выбираемым. Таким образом, пользователь согласится с вашим предположением, просто нажав кнопку, или он может легко переключить его.

гораздо более вероятно в C ++, чем в C, если все остальное равно), но вы не можете полагаться на них.

После анализа я бы предложил наиболее вероятный язык в качестве выбора для пользователя с упорядоченным остальным, который также быть выбираемым. Таким образом, пользователь согласится с вашим предположением, просто нажав кнопку, или он может легко переключить его.

1
ответ дан 3 December 2019 в 01:45
поделиться

Вот простой способ сделать это. Просто запустите парсер на каждом языке. Независимо от того, какой язык продвинется дальше всех без ошибок (или имеет наименьшее количество ошибок), побеждает.

Этот метод имеет следующие преимущества:

  • У вас уже есть большая часть кода, необходимого для этого.
  • Анализ может быть выполняется параллельно на многоядерных машинах.
  • От большинства языков можно избавиться очень быстро.
  • Этот метод очень надежен. Языки, которые могут показаться очень похожими при использовании нечеткого анализа (например, байевский), вероятно, будут иметь много ошибок при запуске фактического анализатора.
  • Если программа анализируется правильно на двух разных языках, то никогда не было никакой надежды на различая их в первую очередь.
4
ответ дан 3 December 2019 в 01:45
поделиться