Возможно ли добавить nowiki-теги в этот парсер? - PullRequest
0 голосов
/ 17 сентября 2009

Обновление: для записи, вот реализация, которую я в итоге использовал .

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

class Markup
  def initialize(markup)
    @markup = markup
  end

  def to_html
    @html ||= @markup.split(/(\r\n){2,}|\n{2,}/).map {|p| Paragraph.new(p).to_html }.join("\n")
  end

  class Paragraph
    def initialize(paragraph)
      @p = paragraph
    end

    def to_html
      @p.gsub!(/'{3}([^']+)'{3}/, "<strong>\\1</strong>")
      @p.gsub!(/'{2}([^']+)'{2}/, "<em>\\1</em>")
      @p.gsub!(/`([^`]+)`/, "<code>\\1</code>")

      case @p
      when /^=/
        level = (@p.count("=") / 2) + 1 # Starting on h2
        @p.gsub!(/^[= ]+|[= ]+$/, "")
        "<h#{level}>" + @p + "</h#{level}>"
      when /^(\*|\#)/
        # I'm parsing lists here. Quite a lot of code, and not relevant, so
        # I'm leaving it out.
      else
        @p.gsub!("\n", "\n<br/>")
        "<p>" + @p + "</p>"
      end
    end
  end
end

p Markup.new("Here is `code` and ''emphasis'' and '''bold'''!

Baz").to_html

# => "<p>Here is <code>code</code> and <em>emphasis</em> and <strong>bold</strong>!</p>\n<p>Baz</p>"

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

Реально ли добавить поддержку тегов nowiki (где все между не анализируется) для такого синтаксического анализатора? Не стесняйтесь отвечать «нет» и предлагать альтернативные способы создания парсера:)

В качестве sidenote вы можете увидеть фактический код парсера на Github. markup.rb и параграф.rb

1 Ответ

3 голосов
/ 17 сентября 2009

Если вы используете простой токенизатор, гораздо проще управлять такими вещами. Один из подходов заключается в создании единого регулярного выражения, которое может охватить всю грамматику, но это может оказаться проблематичным. Альтернативой является разделение документа на разделы, которые необходимо переписать, и разделы, которые следует пропустить, что, вероятно, является более простым подходом.

Вот простая структура, которую вы можете расширить по мере необходимости:

def wiki_subst(string)
  buffer = string.dup
  result = ''

  while (m = buffer.match(/<\s*nowiki\s*>.*?<\s*\/\s*nowiki\s*>/i))
    result << yield(m.pre_match)
    result << m.to_s
    buffer = m.post_match
  end

  result << yield(buffer)

  result
end

example = "replace me<nowiki>but not me</nowiki>replace me too<NOWIKI>but not me either</nowiki>and me"

puts wiki_subst(example) { |s| s.upcase }
# => REPLACE ME<nowiki>but not me</nowiki>REPLACE ME TOO<NOWIKI>but not me either</nowiki>AND ME
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...