Parent

Class/Module Index [+]

Quicksearch

ClsRuby::Parser

Класс парсера CLS потока.

Пример использования

parser = Parser.new( stream, stream_name, tags )
parser.parse

Если во время парсинга обнаруживается ошибка, то метод Parser#parse выбрасывает исключение.

Constants

ACCESS_TO_TOPLEVEL_ENABLED

Константа, которая означает, что разрешается доступ к самому верхнему элементу стека тегов, даже если это TopLevelTag.

EOF
TOKEN_HANDLES

Соответствие между типами токенов и методами, которые нужно вызывать у текущего тега для обработки тега.

Public Class Methods

new( stream, stream_name, tags ) click to toggle source

Конструктор.

stream

входной поток. Должен реализовывать методы getc и ungetc аналогичные методам из класса IO.

stream_name

имя входного потока.

tags

вектор тегов, которые будут участвовать в парсинге.

# 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

Public Instance Methods

parse() click to toggle source

Выполнение парсинга входного потока.

Результат парсинга будет содержаться в тегах, которые были переданны в конструкторе.

# File lib/cls-ruby/parser.rb, line 81
def parse
  begin
    run_parsing
  rescue Exception => x
    envelop_and_reraise_exception( x )
  end
end

Private Instance Methods

envelop_and_reraise_exception( x ) click to toggle source

Порождает исключение 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
make_open_tags_names() click to toggle source

Возвращает в виде строки имена всех незакрытых к текущему моменту тегов.

# File lib/cls-ruby/parser.rb, line 239
def make_open_tags_names
  @stack[ 1...@stack.size ].inject( '' ) do
    |names, tag|
    names << "{#{tag.tag_name} "
  end
end
pop_tag() click to toggle source

Снятие тега с вершины стека.

Порождает исключение, если в стеке хранится всего лишь TopLevelTag.

# File lib/cls-ruby/parser.rb, line 233
def pop_tag
  raise EmptyTagStackEx.new( "too many }" ) if 1 >= @stack.size
  @stack.pop
end
process_parsing_finish() click to toggle source

Обработка завершения парсинга.

В стеке должен быть только один тег и для 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
process_tag_finish() click to toggle source

Обработка завершения очередного тега.

# 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
process_tag_start() click to toggle source

Обработка начала очередного тега.

Порождает ошибку, если лексер извлекает из входного потока что-либо, отличное от :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
process_token( token ) click to toggle source

Передача тега текущему тегу.

# 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
push_tag( tag ) click to toggle source

Помещение очередного тега в вершину стека.

# File lib/cls-ruby/parser.rb, line 226
def push_tag( tag )
  @stack.push( tag )
end
run_parsing() click to toggle source

Выполнение основных действий по парсингу.

# 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
top_tag( danger_limit = 1 ) click to toggle source

Получение доступа к самому верхнему тегу в стеке.

Порождает исключение, если в стеке хранится всего лишь 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
try_start_tag_with_name( name ) click to toggle source

Попытка начала тега с указанным именем.

Проверяет, есть ли тег с таким именем в списке дочерних тегов текущего тега.

# 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

[Validate]

Generated with the Darkfish Rdoc Generator 2.