class YARD::Parser::C::CParser

Public Class Methods

new(source, file = '(stdin)') click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 5
def initialize(source, file = '(stdin)')
  @file = file
  @namespaces = {}
  @content = source
  @index = 0
  @line = 1
  @state = nil
  @newline = true
  @statements = []
  @last_comment = nil
  @last_statement = nil
end

Public Instance Methods

enumerator() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 23
def enumerator
  @statements
end
parse() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 18
def parse
  parse_toplevel
  enumerator
end
tokenize() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 27
def tokenize
  raise NotImplementedError, "no tokenization support for C/C++ files"
end

Private Instance Methods

advance(num = 1) click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 209
def advance(num = 1) @index += num end
advance_loop() { |end| ... } click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 212
  def advance_loop(&block)
    while @index <= @content.size; yield end
  end

  def nextline
    @line += 1
    @newline = true
  end

  def char(num = 1) @content[@index, num] end
  def prevchar(num = 1) @content[@index - 1, num] end
  def nextchar(num = 1) @content[@index + 1, num] end

  def struct
    /struct\s[:alnum:]+\s\{/
  end
end
attach_comment(statement) click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 191
def attach_comment(statement)
  if Comment === statement
    if @last_statement && @last_statement.line == statement.line
      @last_statement.comments = statement
      statement.statement = @last_statement
    end
    @last_comment = statement
    @last_statement = nil
  else
    if @last_comment
      statement.comments = @last_comment
      @last_comment.statement = statement
    end
    @last_statement = statement
    @last_comment = nil
  end
end
back(num = 1) click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 210
def back(num = 1) @index -= num end
char(num = 1) click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 221
def char(num = 1) @content[@index, num] end
consume_body_statements() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 92
def consume_body_statements
  stmts = []
  brace_level = 1
  while true
    strip_non_statement_data
    start, line = @index, @line
    consume_until(/[{};]/)
    brace_level += 1 if prevchar == '{'
    brace_level -= 1 if prevchar == '}'

    break if prevchar.empty? || (brace_level <= 0 && prevchar == '}')
    end_chr = @index
    end_chr -= 1 if prevchar == '}'
    src = @content[start...@index]
    if src && src !~ /\A\s*\Z|\A\}\Z/
      stmt = BodyStatement.new(src, @file, line)
      attach_comment(stmt)
      stmts << stmt
    end
  end
  stmts
end
consume_comment(add_comment = true) click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 131
def consume_comment(add_comment = true)
  return(advance) unless nextchar == '*' || nextchar == '/'
  line = @line
  type = nextchar == '*' ? :multi : :line
  advance(2)
  comment = ""
  advance_loop do
    comment << char
    if type == :multi
      nextline if char == "\n"
      if char(2) == '*/'
        if add_comment
          comment << '/'
          stmt = Comment.new(comment, @file, line)
          stmt.type = type
          attach_comment(stmt)
          @statements << stmt
        end
        return advance(2)
      end
    elsif char == "\n"
      if add_comment
        stmt = Comment.new(comment[0...-1], @file, line)
        stmt.type = type
        attach_comment(stmt)
        @statements << stmt
      end
      return
    end
    advance
  end
end
consume_directive() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 57
def consume_directive
  return(advance) unless @newline
  @last_comment = nil
  @last_statement = nil
  advance_loop do
    if char == '\' && nextchar =~ /[\r\n]/
      advance_loop { advance; break(nextline) if char == "\n" }
    elsif char == "\n"
      return
    end
    advance
  end
end
consume_quote(type = '"') click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 45
def consume_quote(type = '"')
  advance
  advance_loop do
    case char
    when "\n"; advance; nextline
    when '\'; advance(2)
    when type; advance; return
    else advance
    end
  end
end
consume_toplevel_statement() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 71
def consume_toplevel_statement
  @newline = false
  start = @index
  line = @line
  decl = consume_until(/[{;]/)
  return nil if decl =~ /\A\s*\Z/
  statement = ToplevelStatement.new(nil, @file, line)
  @statements << statement
  attach_comment(statement)
  stmts = nil
  if prevchar == '{'
    stmts = consume_body_statements
    if decl =~ /\A(typedef|enum|class|#{struct}|union)/
      consume_until(';')
    end
  end
  statement.source = @content[start..@index]
  statement.block = stmts
  statement.declaration = decl
end
consume_until(end_char, bracket_level = 0, brace_level = 0, add_comment = true) click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 164
def consume_until(end_char, bracket_level = 0, brace_level = 0, add_comment = true)
  end_char = /#{end_char}/ if end_char.is_a?(String)
  start = @index
  advance_loop do
    chr = char
    case chr
    when /\s/; consume_whitespace
    when /['"]/; consume_quote(char)
    when '#'; consume_directive
    when '/'; consume_comment(add_comment)
    when '{'; advance; brace_level += 1
    when '}'; advance; brace_level -= 1
    when '('; advance; bracket_level += 1
    when ')'; advance; bracket_level -= 1
    else advance
    end
    @newline = false if chr !~ /\s/

    if chr =~ end_char && (chr == '{' || chr == '(')
      break
    elsif chr =~ end_char && bracket_level <= 0 && brace_level <= 0
      break
    end
  end
  return @content[start...@index]
end
consume_whitespace() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 127
def consume_whitespace
  advance_loop { nextline if char == "\n"; break if char =~ /\S/; advance }
end
nextchar(num = 1) click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 223
def nextchar(num = 1) @content[@index + 1, num] end
nextline() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 216
def nextline
  @line += 1
  @newline = true
end
parse_toplevel() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 33
def parse_toplevel
  advance_loop do
    case char
    when /['"]/; consume_quote(char)
    when '#'; consume_directive
    when '/'; consume_comment
    when /\s/; consume_whitespace
    else consume_toplevel_statement
    end
  end
end
prevchar(num = 1) click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 222
def prevchar(num = 1) @content[@index - 1, num] end
strip_non_statement_data() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 115
def strip_non_statement_data
  start = @index
  begin
    start = @index
    case char
    when /\s/; consume_whitespace
    when '#';  consume_directive
    when '/';  consume_comment
    end
  end until start == @index
end
struct() click to toggle source
# File lib/yard/parser/c/c_parser.rb, line 225
def struct
  /struct\s[:alnum:]+\s\{/
end