Object
Класс парсера CLS потока.
Пример использования
parser = Parser.new( stream, stream_name, tags ) parser.parse
Если во время парсинга обнаруживается ошибка, то метод Parser#parse выбрасывает исключение.
Константа, которая означает, что разрешается доступ к самому верхнему элементу стека тегов, даже если это TopLevelTag.
Соответствие между типами токенов и методами, которые нужно вызывать у текущего тега для обработки тега.
Конструктор.
входной поток. Должен реализовывать методы getc и ungetc аналогичные методам из класса IO.
имя входного потока.
вектор тегов, которые будут участвовать в парсинге.
# File lib/cls-ruby/parser.rb, line 72 def initialize( stream, stream_name, tags ) @stack = [ TopLevelTag.new( tags ) ] @lexer = Lexers::Lexer.new( stream, stream_name ) end
Порождает исключение ParsingErrorEx, в которое добавляет описание перехваченного исключения. Вместе с данными о месте возникновения проблемы.
# File lib/cls-ruby/parser.rb, line 147 def envelop_and_reraise_exception( x ) open_tags_names = make_open_tags_names.chop open_tags_names += ': ' if 0 != open_tags_names.size envelop = ParsingErrorEx.new( @lexer.stream_name, @lexer.line_no, "#{open_tags_names} #{x.message} [#{x.class.name}]" ) envelop.nested_exception = x envelop.set_backtrace( x.backtrace ) raise envelop end
Снятие тега с вершины стека.
Порождает исключение, если в стеке хранится всего лишь TopLevelTag.
# File lib/cls-ruby/parser.rb, line 233 def pop_tag raise EmptyTagStackEx.new( "too many }" ) if 1 >= @stack.size @stack.pop end
Обработка завершения парсинга.
В стеке должен быть только один тег и для TopLevelTag вызывается tag_on_finish для того, чтобы убедиться, что все обязательные теги определены.
# File lib/cls-ruby/parser.rb, line 196 def process_parsing_finish raise NonEmptyStackEx.new( "too few }" ) if 1 != @stack.size @stack[ 0 ].tag_on_finish end
Обработка завершения очередного тега.
# File lib/cls-ruby/parser.rb, line 173 def process_tag_finish tag_to_finish = top_tag tag_to_finish.tag_on_finish pop_tag top_tag( ACCESS_TO_TOPLEVEL_ENABLED ).tag_on_tag( tag_to_finish ) end
Обработка начала очередного тега.
Порождает ошибку, если лексер извлекает из входного потока что-либо, отличное от :tok_non_space.
# File lib/cls-ruby/parser.rb, line 163 def process_tag_start n = @lexer.next if :tok_nonspace == n[1] try_start_tag_with_name( n[0] ) else raise UnexpectedTokenEx.new( "tag name expected instead of #{n[1]}" ) end end
Передача тега текущему тегу.
# File lib/cls-ruby/parser.rb, line 182 def process_token( token ) method = TOKEN_HANDLES.fetch( token[1], nil ) raise UnexpectedTokenEx.new( "unable to handle token #{token[1]} " + "('#{token[0]}')" ) unless method # Этот метод можно вызывать даже у TopLevelTag. top_tag( ACCESS_TO_TOPLEVEL_ENABLED ).send( method, token[0] ) end
Помещение очередного тега в вершину стека.
# File lib/cls-ruby/parser.rb, line 226 def push_tag( tag ) @stack.push( tag ) end
Выполнение основных действий по парсингу.
# File lib/cls-ruby/parser.rb, line 130 def run_parsing while EOF != ( n = @lexer.next ) if n[1] == :tok_open_block process_tag_start elsif n[1] == :tok_close_block process_tag_finish else process_token( n ) end end process_parsing_finish end
Получение доступа к самому верхнему тегу в стеке.
Порождает исключение, если в стеке хранится всего лишь TopLevelTag.
# File lib/cls-ruby/parser.rb, line 220 def top_tag( danger_limit = 1 ) raise EmptyTagStackEx.new( "no tags in stack" ) if danger_limit == @stack.size @stack.last end
Попытка начала тега с указанным именем.
Проверяет, есть ли тег с таким именем в списке дочерних тегов текущего тега.
# File lib/cls-ruby/parser.rb, line 205 def try_start_tag_with_name( name ) tag_to_start = top_tag( ACCESS_TO_TOPLEVEL_ENABLED ).tag_tags.find do |tag| tag.tag_compare_name( name ) end raise UnknownTagEx.new( "unknown tag name: #{name}" ) unless tag_to_start tag_to_start.tag_on_start( name ) push_tag( tag_to_start ) end
Generated with the Darkfish Rdoc Generator 2.