2010-04-14 2 views
1

Я запускаю код, который читает файлы, выполняет синтаксический анализ, но должен игнорировать все комментарии. Есть хорошие объяснения, как вести его, как ответ на How can I strip multiline C comments from a file using Perl?Как я могу игнорировать комментарии C, когда обрабатываю исходный файл C с помощью Perl?

$/ = undef; 
$_ = <>; 
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse; 
print; 

Моя первая проблема заключается, что после запуска этой линии $/ = undef; мой код не работает должным образом. На самом деле, я не знаю, что он делает. Но если бы я мог вернуть его после игнорирования всех комментариев, это будет полезно.

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

+0

Смотрите также http://stackoverflow.com/questions/2578671/where-can-i-find-information-about-perls-special- переменные –

ответ

1

Вы хотите сделать $/ местный , как в

$_ = do { local $/; <> }; 

или

{ 
    local $/; 
    $_ = <>; 
    #... 
} 

В качестве альтернативы, вы можете использовать File::Slurp

2

AWK

$ cat file.c 
one 
two 
three // comment at the back 
// comment in front 
four /* another comment */ 
/* comment spanning 
    multiple 
    lines 
*/ five 
six 
seven 

$ awk -vRS='*/' '{ gsub(/\/\*.*/,"");gsub("//.*","")}1' file.c 
one 
two 
three 


    five 
six 
seven 

команда AWK устанавливает разделитель RS в */, который закрывающий тег для многострочного стиль комментария. поэтому он выполняет итерацию записей, проверяя /*, открывающий тег, а затем получает все, что находится перед /*. эта концепция проста, и для этого вам не нужно создавать сложное регулярное выражение. Похоже, если вы должны были сделать это с Python,

>>> data=open("file").read() 
>>> for item in data.split("*/"): 
...  if "//" in item: item=item.split("//")[0] 
...  if "/*" in item: item=item.split("/*")[0] 
...  print item 
... 
one 
two 
three 


    five 
six 
seven 
1

Если вы зачистки «вложенными» комментарии, т.е .:

/* This is a comment 
/* that has been re-commented */ possibly /* due to */ 
various modifications */ 

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

Последний раз, когда я должен был сделать что-то подобное, я читал строки по одному, сохраняя количество уровней «/ *» (или независимо от того, какой разделитель был для конкретного языка) и не печатал ничего если счетчик не был на 0.

Вот пример - я заранее извиняюсь, потому что это очень плохо Perl, но это должно дать вам представление о том, по крайней мере:

use strict; 

my $infile = $ARGV[0]; # File name 

# Slurp up input file in an array 
open (FH, "< $infile") or die "Opening: $infile"; 
my @INPUT_ARRAY = <FH>; 
my @ARRAY; 
my ($i,$j); 
my $line; 


# Removes all kind of comments (single-line, multi-line, nested). 
# Further parsing will be carried on the stripped lines (in @ARRAY) but 
# the error messaging routine will reference the original @INPUT_ARRAY 
# so line fragments may contain comments. 
my $commentLevel = 0; 

for ($i=0; $i < @INPUT_ARRAY; $i++) 
{ 
    my @explodedLine = split(//,$INPUT_ARRAY[$i]); 
    my $resultLine =""; 

    for ($j=0; $j < @explodedLine; $j++) 
    { 
     if ($commentLevel > 0) 
     { 
      $resultLine .= " "; 
     } 
     if ($explodedLine[$j] eq "/" && $explodedLine[($j+1)] eq "*") 
     { 
       $commentLevel++; 
       next; 
     }   
     if ($explodedLine[$j] eq "*" && $explodedLine[($j+1)] eq "/") 
     { 
       $commentLevel--; 
       $j++; 
       next; 
     }  
     if (($commentLevel == 0) || ($explodedLine[$j] eq "\n")) 
     { 
      $resultLine .= $explodedLine[$j]; 
     } 
    } 

$ARRAY[$i]=join(" ",$resultLine); 
} 


close(FH) or die "Closing: $!";