2013-04-10 2 views
0

Этот вопрос является дополнением к: Recursive processing of markup using Regular Expression and DOMDocumentСинтаксический разметки в абстрактное синтаксическое дерево с помощью регулярного выражения

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

{<anchor>} 
{!image!} 
{*strong*} 
{/emphasis/} 
{|code|} 
{-strikethrough-} 
{>small<} 

Две метки, a и small также требуют отличаясь конечных тегов. Я пробовал модифицировать $re_closetag из исходного образца кода, чтобы отразить это, но он по-прежнему совпадает с текстом.

Например:

http://www.google.com/>} bang 
smäll<} boom 

Моя тестовая строка:

tëstïng {{ 汉字/漢字 }} testing {<http://www.google.com/>} bang {>smäll<} boom {* strông{/ ëmphäsïs {- strïkë {| côdë |} -} /} *} {*wôw*} 1, 2, 3 

ответ

1

Вы можете контролировать это в самом RE или после матча.

В ре, чтобы контролировать, какие теги могут быть «открытыми» изменить эту часть $re_next:

(?:\{(?P<opentag>[^{\s])) # match an open tag 
     #which is "{" followed by anything other than whitespace or another "{" 

В настоящее время это выглядит для любого символа, который не является { или пробелы. Просто измените на это:

(?:\{(?P<opentag>[<!*/|>-])) 

Теперь он ищет только ваши конкретные открытые теги.

Часть тега тега соответствует только одному символу за раз в зависимости от того, какой тег открыт в текущем контексте. (Это аргумент $opentag.) Таким образом, чтобы сопоставить пару символов, просто измените $opentag на поиск в рекурсивном вызове. Например:

 if (isset($m['opentag']) && $m['opentag'][1] !== -1) { 
      list($newopen, $_) = $m['opentag']; 

      // change the close character to look for in the new context 
      if ($newopen==='>') $newopen = '<'; 
      else if ($newopen==='<') $newopen = '>'; 

      list($subast, $offset) = str_to_ast($s, $offset, array(), $newopen); 
      $ast[] = array($newopen, $subast); 
     } else if (isset($m['text']) && $m['text'][1] !== -1) { 

В качестве альтернативы вы можете сохранить RE как есть и решить, что делать с игрой после факта. Например, если вы совпадаете с символом @, но {@ не является разрешенным открытым тегом, вы можете либо поднять ошибку синтаксического анализа, либо просто обработать его как текстовый узел (прикрепляя array('#text', '{@') к ast), или что-либо между ними.

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