Создание парсера BBcode с проблемой PEG - PullRequest
0 голосов
/ 19 сентября 2011

Я делаю парсер bbcode с PEG (реализация Citrus для Ruby) и застреваю при разборе этого [b]sometext[anothertext[/b]

Есть код

grammar BBCodeParser
  rule document
    (open_tag | close_tag | new_line | text)*
  end
  rule open_tag
    ("[" tag_name "="? tag_data? "]")
  end

  rule close_tag
    ("[/" tag_name "]") 
  end

  rule text
    [^\n\[\]]+
  end

  rule new_line
    ("\r\n" | "\n")
  end

  rule tag_name
    # [p|br|b|i|u|hr|code|quote|list|url|img|\*|color]
    [a-zA-Z\*]+
  end

  rule tag_data
    ([^\[\]\n])+
  end
end

Проблема с правилом text Я не знаю, как сказать, что текст может содержать все, кроме \ r, \ n, open_tag или close_tag.С этой реализацией это не удается в примере из-за исключения из [и] (это неправильно)

Итак, последний вопрос - как создать правило, которое может соответствовать чему угодно, кроме \ r, \ n или точного соответствия open_tag или close_tag

Если у вас есть решение для другой реализации PEG, дайте его там же.Я могу переключиться:)

Ответы [ 3 ]

0 голосов
/ 20 сентября 2011

Это

rule text
    [^\n\[\]]+ (!open_tag text)?
end

заканчивается ошибкой синтаксического анализа

Я попытался продолжить эту идею, и результатом было ([^\n] (!open_tag | !close_tag) text*) Но это тоже не удастся.Он будет соответствовать "sometext[anothertext[/b]"

Найти временное решение ((!open_tag | !close_tag | !new_line) .) Он найдет только одну букву за одной буквой, но игнорирует все открытые и закрытые теги.Эти письма я могу объединить позже:)

0 голосов
/ 24 июля 2012

Я недавно столкнулся с подобной проблемой. Для этого есть хитрость:
Вы должны сказать, что соответствует open_tag, затем все, что не является закрывающим тегом, а затем closing_tag. Так что это дает следующее правило

rule tag
  open_tag ((!open_tag | !close_tag | !new_line ) .)+ close_tag
end
0 голосов
/ 19 сентября 2011

Это проанализирует любой текст и продолжится рекурсивно, если [ не является началом другого тега.

rule text
    [^\n\[\]]+ (!open_tag text)?
end
...