Я пытаюсь написать правило для статического анализатора vera ++. Так как я не нашел здесь группу для vera ++ и этот vera ++ использует TCL для реализации своего правила анализа, я разместил на форуме TCL. Я работал над vera ++ inspirel.com/vera/ce/doc/tclapi.html, но так как я не очень хорошо знаю TCL, я хотел бы посоветоваться и в дальнейшем.
Так как я новичок в программировании на TCL, но хотел бы знать, какой подход для программы на TCL перечисляет все локальные переменные в файле исходного кода C ++? Я имею в виду, какой подход и как он может быть достигнут?
Проблема, с которой я сталкиваюсь при анализе файлов исходного кода C ++ для обнаружения объявления локальной переменной?
Разобрать определения локальных (или любых других) переменных с помощью правил vera ++ довольно сложно, но, конечно, выполнимо. Основной синтаксический анализ и токенизация C ++ выполняется vera ++.
Основной подход заключается в использовании vera ++ getTokens
функция в сочетании с небольшим конечным автоматом, который проверяет завершенные операторы C ++. Вам нужно собрать токены (и, возможно, их значения дополнительно, так как вам понадобятся имена переменных позже для настройки списка) и объединить их, пока у вас не будет законченного оператора. Если у вас есть законченный оператор, вы можете использовать регулярное выражение, чтобы проверить, является ли оно определением переменной, и извлечь имя переменной из подстроки. Также вы должны помнить, если вы находитесь внутри {}
блок, чтобы узнать, является ли это определение локальной переменной.
Вы можете найти пример для создания простого автомата состояний для сбора токенов для операторов в правиле vera ++ T019, которое проверяет полные фигурные блоки кода, чтобы взять их в качестве отправной точки.
Я выполнил синтаксический анализ определений переменных с помощью vera ++ (чтобы проверить различные соглашения об именах), но, к сожалению, не могу опубликовать полный код, так как это частная работа для моего работодателя. Но я могу дать вам фрагмент, показывающий регулярное выражение, которое я использую для проверки объявлений переменных:
set isVar false
if [regexp {\s+((extern\s+)?(static\s+|mutable\s+|register\s+|volatile\s+)?(const\s+)?)?((identifier#[^#]+#\s+colon_colon\s+)*identifier#[^#]+#)\s+(star\s+|const\s+|and\s+|less.*greater\s+|greater\s+)*(identifier#[^#]+#\s+colon_colon\s+)*identifier#([^#]+)#(\s+leftbracket.*rightbracket)?(\s+assign)?.*semicolon$} $statement m s1 s2 s3 s4 s5 s6 s7 s8 s9 s10] {
set locVarname $s9
set isVar true
set currentMatch $m
} elseif [regexp {\s+((extern\s+)?(static\s+|mutable\s+|register\s+|volatile\s+)?(const\s+)?)?(char\s+|int\s+|short\s+|long\s+|void\s+|bool\s+|double\s+|float\s+|unsigned\s+|and\s+|star\s+|unsigned\s+)+(identifier#[^#]+#\s+colon_colon)*\s+identifier#([^#]+)#(\s+leftbracket.*rightbracket)?(\s+assign)?.*semicolon$} $statement m s1 s2 s3 s4 s5 s6 s7 s8] {
set locVarname $s7
set isVar true
set currentMatch $m
}
$statement
содержит полное утверждение, как упоминалось ранее. Обратите внимание, что я объединяю значение токена с identifier
использование токена identifier#<value>#
и используйте группу регулярных выражений, чтобы извлечь ее.
К сожалению, я думаю, вы сильно недооцениваете сложность задачи. Проблема в том, что вы не можете делать какие-либо догадок (хотя и образованный) о содержимом файла C ++, если у вас нет разобранный это как определено в стандарте C ++, и делать это ужасно трудно.
К настоящему времени должно быть очевидно, что вопрос о том, какой язык программирования используется для реализации такого анализа, на самом деле не так важен. Вы, безусловно, можете реализовать это в Tcl, но тогда вопрос не является конкретным, так как правильный ответ на него в его текущей форме фактически будет равносильным публикации готового кода парсера. Поэтому я проголосовал за то, чтобы закрыть ваш вопрос как неконструктивный, надеюсь, вы поймете.