2014-02-26 2 views
4

Я пытаюсь захватить комментарии VBA. У меня есть следующие до сих порRegex для захвата комментариев VBA

'[^";]+\Z 

который захватывает все, что начинается с одиночной кавычки, но не содержит каких-либо двойные кавычки до конца строки. то есть он не будет соответствовать одиночным кавычкам в строке двойного кавычки.

dim s as string  ' a string variable -- works 
s = "the cat's hat" ' quote within string -- works 

Но терпит неудачу, если комментарий содержит кавычку двойной

т.е.

dim s as string ' string should be set to "ten" 

Как я могу исправить мое регулярное выражение для обработки, что тоже?

+0

[Повторить вопрос?] [1] [1]: http://stackoverflow.com/questions/311888/regular-expression-to-get-comments-in-vb-net-source -код Попробуйте '^ \ '[^ \ r \ n] + $ |' '[^ \ r \ n] + $' –

ответ

5

Узор в @Jeff Wurz's comment (^\'[^\r\n]+$|''[^\r\n]+$), даже не соответствует любой ваших тестовых образцов, и связанный вопрос не имеет смысла, регулярное выражение там будет соответствовать только , что конкретный комментарий в вопросе Ор в, а не " синтаксис комментария VBA ".

Регулярное выражение, которое вы придумали, работает даже лучше, чем у меня, когда я отказался от подхода с регулярным выражением.

Молодцы!

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

В Lexers vs Parsers, @SasQ's answer делает хорошую работу в объяснении уровней грамматики Хомского:

Уровень 3: Регулярные грамматики

Они используют регулярные выражения, то есть, они могут состоять только из символы алфавита (a, b), их конкатенации (ab, aba, bbb etd.) или альтернативы (например, a | b). Они могут быть реализованы как конечное состояние автоматов (FSA), таких как NFA (недетерминированный конечный автомат) или лучше DFA (детерминированный конечный автомат). Регулярные грамматики не могут обрабатывать с вложенным синтаксисом, например. правильные вложенные/совпадающие скобки (()() (()())), вложенные теги HTML/BBcode, вложенные блоки и т. д. Это потому, что автоматы состояний, с которыми приходится иметь дело, должны иметь бесконечное число состояний для бесконечной обработки многие уровни гнездования.

Уровень 2: контекстно-свободных грамматики

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

Уровень 1: контекстно-зависимых грамматик

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

Я понимаю, что VBA комментарий синтаксис является контекстно-зависимая грамматика (уровень 1), так как апостроф только ваш маркер, если он не является частью строкового литерала, и выяснить апостроф является ли частью строковый литерал, проще всего, чтобы перейти к вашей строке слева направо и переключить флаг IsInsideQuote, поскольку вы сталкиваетесь с двойными кавычками ... но только если они не экранированы (удваиваются). На самом деле вы даже не проверяете, есть ли апостроф внутри строки litereal: вы просто продолжаете идти до тех пор, пока открытые кавычки не будут закрыты, и только когда флаг «в кавычках» равен False, вы нашли маркер комментария, если столкнулись с одним цитаты.

Удачи вам!


Вот тест вам не хватает:

s = "abc'def ""xyz""'nutz!" 'string with apostrophes and escaped double quotes 

Если вы не заботитесь о захвате строковых литералов, вы можете просто игнорировать сбежавшие двойные кавычки и см 3 строковых литералов здесь: "abc'def ", "xyz" и "'nutz!".


Это C# код выхода 'string with apostrophes and escaped double quotes (все в струне двойные кавычки экранируются с помощью обратной косой черты в коде), и работает со всеми тестовыми строками, которые я дал его:

static void Main(string[] args) 
    { 
     var instruction = "s = \"abc'def \"\"xyz\"\"'nutz!\" 'string with apostrophes and escaped double quotes"; 
     // var instruction = "s = \"the cat's hat\" ' quote within string -- works"; 
     // var instruction = "dim s as string ' string should be set to \"ten\""; 

     int? commentStart = null; 

     var isInsideQuotes = false; 
     for (var i = 0; i < instruction.Length; i++) 
     { 
      if (instruction[i] == '"') 
      { 
       isInsideQuotes = !isInsideQuotes; 
      } 

      if (!isInsideQuotes && instruction[i] == '\'') 
      { 
       commentStart = i; 
       break; 
      } 
     } 

     if (commentStart.HasValue) 
     { 
      Console.WriteLine(instruction.Substring(commentStart.Value)); 
     } 

     Console.ReadLine(); 
    } 

Затем, если вы хотите записать все легальные комментарии, вам необходимо обработать ключевое слово Rem и рассмотреть продолжение линии:

Rem this is a legal comment 
' this _ 
    is also _ 
    a legal comment 

Другими словами, \r\n сам по себе недостаточно, чтобы правильно идентифицировать все токены конца.

Правильный лексер + парсер, кажется, единственный способ захватить все комментарии.

Смежные вопросы