2010-11-07 3 views
0

Я пишу блок кода Ruby с подсветкой синтаксиса (для Ruby), написанный на php для моего сайта, я могу получить его для цветных переменных экземпляра, комментариев, символов и глобальных переменных, поэтому далеко, но я столкнулся с проблемой при использовании следующего регулярного выражения для соответствия строк в двойных кавычках, вот мой код:RegEx: Match Non-Escaped Double Quoted Strings

<?php 
    function codebox($code, $name="", $highlighted_line = -1) 
    { 

     echo '<table class="code_table">'; 
     echo '<tr>'; 
     echo '<td class="code_table_header"></td>'; 
     echo '<td class="code_table_name">$name</td>'; 
     echo '<td class="code_table_header"><a href="" class="copy_to_clipboard_link">copy to clipboard</a></td>'; 
    echo '</tr>'; 

     $oddity = 'even'; 
     $line_number = 1; 
     foreach(preg_split('/(\r?\n)/', $code) as $line) 
     { 
      echo '<tr>'; 
      if($line_number % 10 == 0) 
      { 
       echo '<td class="line_number" style="font-weight:bold;">' . $line_number . '</td>'; 
      } else { 
       echo '<td class="line_number">' . $line_number . '</td>'; 
      } 
      if($line_number == $highlighted_line) 
      { 
       echo '<td class="selected_code_cell" colspan="2">' . syntax_highlight($line) . '</td>'; 
      } else { 
       echo '<td class="' . $oddity . '_code_cell" colspan="2">' . syntax_highlight($line) . '</td>'; 
      } 
      echo '</tr>'; 
      $line_number += 1; 
      if($oddity == 'even') 
      { 
       $oddity = 'odd'; 
      } else { 
       $oddity = 'even'; 
      }; 
     }; 
    }; 
    function syntax_highlight($code) 
    { 
     // Make it so html doesn't bodge up 
     $code = htmlentities($code); 

     // Replace tabs with 4 none blocking spaces 
     $code = str_replace(' ', '&nbsp;&nbsp;&nbsp;&nbsp;', $code); 

     //instance variables 
     $code = preg_replace('/\B(\@\w*\S)/', '<span style="color:lime;">$1</span>', $code); 

     //global variables 
     $code = preg_replace('/\B(\$\w*\S)/', '<span style="font-weight:bolder;color:#00b0f0;">$1</span>', $code); 

     //symbols 
     $code = preg_replace('/\B(\:\w*\S)/', '<span style="color:yellow;">$1</span>', $code); 

     //strings (double quote) 
     $code = preg_replace('/"(?:\.|(\\\")|[^\""\n])*"/', '<span style="font-style:italic;color:#FF5A00;">$1</span>', $code); 

     //strings (single quote) 
     //$code = preg_replace('/\'(?:\.|(\\\')|[^\'\'\n])*\'/', '<span style="font-style:italic;color:#FF5A00;">$1</span>', $code); 

     return $code; 
    }; 
?> 

по какой-то причине, двойные кавычек строки нарушает другие из них и не подсветки синтаксиса не выполняется, делает кто-нибудь знает почему? Спасибо заранее, ell.

+0

Вы уверены, что вам нужно брать только двойные и одинарные кавычки? Вот что указывают регулярные выражения. – stillstanding

ответ

1

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

+0

Почему бы и нет? Современные образцы - это не примитивные вещи, которые ограничены обычными языками, которые преподаются на курсах конечных автоматов. Я не говорю, что вы * должны использовать шаблоны для всего, что есть, подумайте; захват вывода токенизатора, очевидно, намного лучше подходит. Но ограничения вычислимости, которые преподаются на курсах автоматов, практически не имеют отношения к современным шаблонам, которые имеют обратные ссылки, условные обозначения, рекурсию и многое другое. – tchrist

+0

@tchrist: Использование регулярных выражений для нерегулярных языков может работать с реализацией в настоящее время регулярных выражений. Но он намного сложнее, подвержен ошибкам и, вероятно, неэффективен, чем при использовании синтаксического анализатора. – Gumbo

+0

При условии, что [этот ответ] (http://stackoverflow.com/questions/4044946/regex-to-split-html-tags/4045840#4045840) предназначен в качестве примера того, почему использование регулярных выражений вместо парсеров может быть плохой идеей, я не уверен, что это по своей сути более сложный, подверженный ошибкам или неэффективный, чем синтаксический анализатор. На самом деле, это ** - парсер, не согласны ли вы? – tchrist

0

Что сказал Гумбо. Вы не можете корректно работать с регулярными выражениями. Но вы можете попробовать это:

preg_match("/'([^'\n\\]|\\'|\\[^'])+'/", ... 

Или, может быть, вам больше повезет с утверждением (?<![\\]) прямо перед котировке.