Class: YARD::Parser::C::CParser
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
::YARD::Parser::Base
|
|
Instance Chain:
self,
::YARD::Parser::Base
|
|
Inherits: |
YARD::Parser::Base
|
Defined in: | lib/yard/parser/c/c_parser.rb |
Class Method Summary
- .new(source, file = '(stdin)') ⇒ CParser constructor
::YARD::Parser::Base
- Inherited
Instance Method Summary
- #enumerator
- #parse
- #tokenize
- #advance(num = 1) private
- #advance_loop private
- #attach_comment(statement) private
- #back(num = 1) private
- #char(num = 1) private
- #consume_body_statements private
- #consume_comment(add_comment = true) private
- #consume_directive private
- #consume_quote(type = '"') private
- #consume_toplevel_statement private
- #consume_until(end_char, bracket_level = 0, brace_level = 0, add_comment = true) private
- #consume_whitespace private
- #nextchar(num = 1) private
- #nextline private
- #parse_toplevel private
- #prevchar(num = 1) private
- #strip_non_statement_data private
- #struct private
::YARD::Parser::Base
- Inherited
#enumerator | This method should be implemented to return a list of semantic tokens representing the source code to be post-processed. |
#parse | This method should be implemented to parse the source and return itself. |
#tokenize | This method should be implemented to tokenize given source. |
Constructor Details
.new(source, file = '(stdin)') ⇒ CParser
# File 'lib/yard/parser/c/c_parser.rb', line 6
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
Instance Method Details
#advance(num = 1) (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 213
def advance(num = 1) @index += num end
#advance_loop (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 216
def advance_loop yield while @index <= @content.size end
#attach_comment(statement) (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 195
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) (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 214
def back(num = 1) @index -= num end
#char(num = 1) (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 225
def char(num = 1) @content[@index, num] end
#consume_body_statements (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 96
def consume_body_statements stmts = [] brace_level = 1 loop do strip_non_statement_data start = @index line = @line consume_until(/[{};]/) brace_level += 1 if prevchar == '{' brace_level -= 1 if prevchar == '}' break if prevchar.empty? || (brace_level <= 0 && prevchar == '}') src = @content[start...@index] next unless src && src !~ /\A\s*\Z|\A\}\Z/ stmt = BodyStatement.new(src, @file, line) attach_comment(stmt) stmts << stmt end stmts end
#consume_comment(add_comment = true) (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 136
def consume_comment(add_comment = true) return(advance) unless nextchar == '*' || nextchar == '/' line = @line type = nextchar == '*' ? :multi : :line advance(2) comment = String.new("") 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 (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 59
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 = '"') (private)
[ GitHub ]#consume_toplevel_statement (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 73
def consume_toplevel_statement @newline = false start = @index line = @line decl = consume_until(/[{;]/) return nil if decl =~ /\A\s*\Z/ # Skip C++ namespace - treat content as top level statement. return nil if decl =~ /\A(namespace)/ 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 # rubocop:disable Lint/UselessSetterCall end
#consume_until(end_char, bracket_level = 0, brace_level = 0, add_comment = true) (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 169
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 break if chr == '{' || chr == '(' break if bracket_level <= 0 && brace_level <= 0 end end @content[start...@index] end
#consume_whitespace (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 132
def consume_whitespace advance_loop { nextline if char == "\n"; break if char =~ /\S/; advance } end
#enumerator
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 24
def enumerator @statements end
#nextchar(num = 1) (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 227
def nextchar(num = 1) @content[@index + 1, num] end
#nextline (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 220
def nextline @line += 1 @newline = true end
#parse
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 19
def parse parse_toplevel enumerator end
#parse_toplevel (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 34
def parse_toplevel advance_loop do case char when /['"]/; consume_quote(char) when '#'; consume_directive when '/'; consume_comment when /\s/; consume_whitespace when '}'; advance # Skip possible C++ namespace closing brackets. else consume_toplevel_statement end end end
#prevchar(num = 1) (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 226
def prevchar(num = 1) @content[@index - 1, num] end
#strip_non_statement_data (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 118
def strip_non_statement_data start = @index loop do start = @index case char when /\s/; consume_whitespace when '#'; consume_directive when '/'; consume_comment end break if start == @index end end
#struct (private)
[ GitHub ]# File 'lib/yard/parser/c/c_parser.rb', line 229
def struct /struct\s[a-zA-Z0-9]+\s\{/ end
#tokenize
# File 'lib/yard/parser/c/c_parser.rb', line 28
def tokenize raise NotImplementedError, "no tokenization support for C/C++ files" end