Я не верю, что поддержка приоритетов операторов играет здесь роль.Приоритеты операторов вступают в действие только при разрешении неоднозначностей в выражениях, подобных foo = 6 + 7
, где выражение можно интерпретировать как (foo = 6) + 7
или foo = (6 + 7)
.Предоставление неоператорам приоритета на самом деле не служит какой-либо цели.
Возможно, неясно, что на самом деле делает анализатор.Он в основном повторяется циклически, сопоставляя все правила терминала с вашей входной строкой.Для тех, которые он находит, он берет самое длинное и пытается найти правило в текущем состоянии, в которое он вписывается.Таким образом, парсер всегда найдет ваш пробел и отбросит его, так как это первое правило в вашей грамматике.
Я думаю, что вы на самом деле не хотите пропускать пробел, поскольку он важен в вашей грамматике.Вы хотите включить это в свои правила, которые позволяют это;что сделает вашу грамматику более многословной, но (в настоящее время) неизбежной.
Так что :raw
становится чем-то вроде следующего, поглощая все пробельные и несинтаксические токены в одну строку:
rule(:raw => /[^\s\{\}%]+/)
rule(:text) do |r|
r[:text, :raw].as { |text, raw| text << raw }
r[:text, :spc].as { |text, spc| text << spc }
r[:spc]
r[:raw]
end
Затем в вашем правиле :all
превратите этот текст в часть вашего AST (вы могли бы сделать это и в приведенном выше правиле, но я ничего не знаю о ваших определениях классов).
rule(:all) do |r|
# ... snip ...
r[:all, :text].as { |all, text| all << Tag::Raw.new(text) }
# ... snip ...
end
Я думал о том, как обеспечить возможность сопоставления разных токенов в разных состояниях, но я опасаюсь написать клон lex / flex, который, я думаю, будет слишком запутанным, поэтому я пытаюсьпридумать подход, который использует блоки для вложения правил друг в друга, чтобы передать, как состояния связаны друг с другом;хотя не так просто создать легко понимаемый DSL, который делает это;) Я также хочу предоставить дополнительный DSL, чтобы скрыть алгоритм, используемый для повторения;возможно, предоставляя своего рода слой PEG, который трансформируется в LR-парсер.Это все еще (очень) молодой проект;)