2015-05-07 2 views
0

Я хотел бы получить ваш совет относительно повторяющейся проблемы, связанной с использованием Treetop, что я не могу исправить ... время от времени. Вероятно, я что-то пропустил.Почему пустая строка кажется испущенной вместо пользовательского узла, иногда в грамматике Treetop?

Я подозреваю, что многие из вас имеют правильную идиому или привычки решать это.

Я обычно использую Treetop как следующий:

  1. Я определяю свою грамматику в файле .TT
  2. я могу изменить его испускать пользовательские дерево разбора OBJETS (которые наследуют Treetop :: RUNTIME :: SyntaxNode). Эти классы: , определенные в файле "parsetree.rb".
  3. эти пользовательские объекты имеют метод to_ast превратить их рекурсивно в «чистых» Treetop независимых классов (которые составляют мой окончательный AST). У меня есть два отдельных модуля (ParseTree & AST).

Однако, я ударил сообщение классической ошибки, что я не могу вообще исправить:

parsetree.rb:380:in `to_ast': undefined method `to_ast' for SyntaxNode 
offset=149, "":Treetop::Runtime::SyntaxNode (NoMethodError) 

Я озадачен здесь, потому что пустая строка «», кажется, испускается не один из моих пользовательских узлов.

В этом примере в этой строке 380 я следующий код (речь идет о конечных автоматах)

# in parsetree.rb 
class Next < Tree 
     def to_ast 
     ret=Ldl::Ast::Next.new 
     ret.name=ns.to_ast 
     if cond 
      ret.condition=cond.c.to_ast 
     end 
     ret.actions=acts.to_ast # <==== line 380 
     ret 
     end 
    end 

class NextActions < Tree 
     def to_ast 
     eqs.elements.collect{|eq| eq.to_ast} 
     end 
    end 

И моя часть грамматики затрагиваемого ошибки:

rule nextstate 
    space? 'next' space ns:identifier space? cond:('?' space? c:expression)? space 
    acts:next_actions? <Ldl::ParseTree::Next> 
end 

rule next_actions 
    space? eqs:equation+ space 'end' space <Ldl::ParseTree::NextActions> 
end 

ответ

1

Ваша проблема связана с поведением необязательных выражений.

Действия: next_actions не является обязательным. Если этот дополнительный элемент не имеет аналогов на входе, вы не получаете узел NextActions, а epsilon. Вы должны обнаружить, что, говоря что-то вроде:

ret.actions = acts.empty? ? [] : acts.to_ast 

Та же проблема может возникнуть, потому что последовательность названа тегом конд: не является обязательным. Если эта последовательность не существует на входе, то у нее нет содержимого «c». В этом случае «cond» будет по-прежнему определяться, и ваш оператор «if» будет правдой, но cond.c.to_ast не удастся.

Краткий ответ: когда вы используете необязательное выражение, вы должны пометить его и протестировать тег для пустого? прежде чем пытаться использовать контент.

+0

Большое спасибо. Это кристально чисто. – JCLL

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

  • Нет связанных вопросов^_^