Class: CExtractorDefinitions
- Defined in:
- lib/ceedling/c_extractor/c_extractor_definitions.rb
Overview
=========================================================================
Ceedling - Test-Centered Build System for C ThrowTheSwitch.org Copyright (c) 2010-26 Mike Karlesky, Mark VanderVoord, & Greg Williams SPDX-License-Identifier: MIT
Instance Method Summary collapse
-
#try_extract_aggregate_definition(scanner) ⇒ Array(Boolean, String|nil)
Tracks brace depth and uses post-body lookahead to distinguish type definitions from variable declarations — not suitable for collect_balanced().
-
#try_extract_typedef(scanner) ⇒ Array(Boolean, String)
Tracks brace depth but terminates on ';' rather than '}' — not suitable for collect_balanced() Try to extract a C typedef declaration from the scanner.
Instance Method Details
#try_extract_aggregate_definition(scanner) ⇒ Array(Boolean, String|nil)
Tracks brace depth and uses post-body lookahead to distinguish type definitions from variable declarations — not suitable for collect_balanced()
Try to extract a file-scope struct, enum, or union type definition (non-typedef form). Called as a feature extractor by CExtractor#extract_next_feature. Collects standalone aggregate type definitions (body required, ';' follows '}' directly with only optional whitespace/comments between) as raw text. Comments are replaced with a single space; string literals are verbatim.
Handles:
struct [tag] { member-list };
enum [tag] { enumerator-list };
union [tag] { member-list };
Does NOT handle (returns [false, nil], scanner unchanged):
struct/enum/union { ... } declarator; — variable declaration; falls to variable extractor
struct/enum/union tag; — forward declaration without body; not collected
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/ceedling/c_extractor/c_extractor_definitions.rb', line 87 def try_extract_aggregate_definition(scanner) return [false, nil] unless scanner.check(/(?:struct|enum|union)\b/) start_pos = scanner.pos text = +'' depth = 0 until scanner.eos? ch = scanner.peek(1) if ch == '"' || ch == "'" # Capture string/char literals verbatim — ';' or '{'/'}' inside must not affect state before = scanner.pos @c_extractor_code_text.skip_c_string(scanner, ch) text << scanner.string[before...scanner.pos] elsif scanner.check(%r{/[/*]}) # Replace comment with a single space — ';' inside must not terminate @c_extractor_code_text.skip_comment(scanner) text << ' ' elsif scanner.scan(/\{/) depth += 1 text << '{' elsif scanner.scan(/\}/) depth -= 1 text << '}' if depth == 0 # Body closed. Speculatively advance past whitespace/comments to peek at next char. # Do NOT commit whitespace to text yet — we may need to rollback entirely. ws_start = scanner.pos loop do init = scanner.pos scanner.skip(/\s+/) @c_extractor_code_text.skip_comment(scanner) if scanner.check(%r{/[/*]}) break if scanner.pos == init end if scanner.peek(1) == ';' # Standalone type definition — commit text << scanner.string[ws_start...scanner.pos] # include whitespace before ';' text << scanner.scan(/;/) scanner.scan(/[ \t]*\n/) # absorb optional trailing newline return [true, text.rstrip] else # Declarator present (variable name, '*', '[', etc.) — not a standalone type definition. # Rollback entirely so the variable extractor sees the full text. scanner.pos = start_pos return [false, nil] end end elsif depth == 0 && scanner.scan(/;/) # Hit ';' at depth 0 before any '{' — forward declaration or variable declaration. # Neither is a standalone aggregate type definition; rollback. scanner.pos = start_pos return [false, nil] else text << scanner.getch end end # EOF without completing extraction — rollback scanner.pos = start_pos [false, nil] end |
#try_extract_typedef(scanner) ⇒ Array(Boolean, String)
Tracks brace depth but terminates on ';' rather than '}' — not suitable for collect_balanced()
Try to extract a C typedef declaration from the scanner.
Called as a feature extractor by CExtractor#extract_next_feature.
Collects everything from the typedef keyword through the terminating ;
(handling nested braces for struct/union/enum bodies, string literals,
and comments) and returns it as a raw string including any trailing newline.
Comments are replaced with a single space; string literals are verbatim.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/ceedling/c_extractor/c_extractor_definitions.rb', line 24 def try_extract_typedef(scanner) return [false, nil] unless scanner.check(/typedef\b/) text = +'' depth = 0 # brace nesting — typedef body terminates only at depth == 0 until scanner.eos? ch = scanner.peek(1) if ch == '"' || ch == "'" # Capture string/char literals verbatim — a ';' inside must not terminate before = scanner.pos @c_extractor_code_text.skip_c_string(scanner, ch) text << scanner.string[before...scanner.pos] elsif scanner.check(%r{/[/*]}) # Replace comment with a single space — a ';' inside must not terminate @c_extractor_code_text.skip_comment(scanner) text << ' ' elsif scanner.scan(/\{/) depth += 1 text << '{' elsif scanner.scan(/\}/) depth -= 1 text << '}' elsif depth == 0 && scanner.scan(/;/) text << ';' scanner.scan(/[ \t]*\n/) # absorb optional trailing newline return [true, text.rstrip] else text << scanner.getch end end [false, nil] # EOF without finding ';' end |