Module: Hecks::Projections::ParserTable
- Extended by:
- Hecks::Projector::Target
- Defined in:
- lib/hecks/projections/parser_table.rb
Overview
THE RUST PARSER'S KEYWORD TABLE, projected from the chapter's own Syntax aggregate — "the parser's grammar knowledge is DERIVED from hecks's self-description, not hand-typed a second time", which is the anti-drift idea the whole Rust-parser plan rests on.
A REGISTERED TARGET NOW, rather than a module living inside its own bin/ script. It was already a projection in everything but call shape; this only stops it being a fifth way of spelling one.
Constant Summary collapse
- KEYWORD_FIELDS =
%i[word context body inner opens fills status was resolves_via disambiguator].freeze
- ARGUMENT_FIELDS =
%i[keyword context at named kind required fills selects pair_key_fills pair_value_fills pairs_shape status variadic minimum].freeze
Class Method Summary collapse
- .argument_row(row) ⇒ Object
- .call(bluebook:, options: {}) ⇒ Object
- .closed_set_members(bluebook, name) ⇒ Object
- .const_str_array(name, values) ⇒ Object
- .keyword_row(row) ⇒ Object
-
.render(bluebook) ⇒ Object
S14, ADR 0026 — Keyword/Argument are genuine entities of Syntax now, dispatched (not merely declared) so their own
statusreally is a lifecycle. -
.rows(bluebook, name) ⇒ Object
Every cell as text — exactly spec/syntax_conformance_spec.rb's own
rowshelper, reused rather than re-derived: a member's fields decode back through typed literal decoding on the way out of reconstruction, and this reads it back as what was written. -
.rust_string(value) ⇒ Object
A Rust string literal for one field's value — every field here is plain ASCII (a word, a context name, a digit, "true"/"false"), so this only has to be safe against the two characters Rust string literals themselves reserve.
-
.syntax(bluebook) ⇒ Object
THE CHAPTER IS HANDED OVER, not reached for.
Methods included from Hecks::Projector::Target
projection_declares, projection_emits, projection_key, projection_requires, projects_as
Class Method Details
.argument_row(row) ⇒ Object
55 56 57 58 |
# File 'lib/hecks/projections/parser_table.rb', line 55 def argument_row(row) fields = ARGUMENT_FIELDS.map { |field| rust_string(row[field]) } " ArgumentRow { #{ARGUMENT_FIELDS.zip(fields).map { |name, value| "#{name}: #{value}" }.join(', ')} }," end |
.call(bluebook:, options: {}) ⇒ Object
19 |
# File 'lib/hecks/projections/parser_table.rb', line 19 def call(bluebook:, options: {}) = render(bluebook) |
.closed_set_members(bluebook, name) ⇒ Object
38 |
# File 'lib/hecks/projections/parser_table.rb', line 38 def closed_set_members(bluebook, name) = rows(bluebook, name).map { |row| row[:name] } |
.const_str_array(name, values) ⇒ Object
60 61 62 63 |
# File 'lib/hecks/projections/parser_table.rb', line 60 def const_str_array(name, values) lines = values.map { |value| " #{rust_string(value)}," } "pub static #{name}: &[&str] = &[\n#{lines.join("\n")}\n];\n" end |
.keyword_row(row) ⇒ Object
50 51 52 53 |
# File 'lib/hecks/projections/parser_table.rb', line 50 def keyword_row(row) fields = KEYWORD_FIELDS.map { |field| rust_string(row[field]) } " KeywordRow { #{KEYWORD_FIELDS.zip(fields).map { |name, value| "#{name}: #{value}" }.join(', ')} }," end |
.render(bluebook) ⇒ Object
S14, ADR 0026 — Keyword/Argument are genuine entities of Syntax
now, dispatched (not merely declared) so their own status
really is a lifecycle. SyntaxBoot.call reads the STILL-STATIC
seed rows (KeywordSeed/ArgumentSeed), dispatches each one
through the real admission/lifecycle door, and hands back the
exact same shape rows used to read straight off the closed set
— symbol keys, string values, status included — so nothing
else in this file needed to change.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 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 156 |
# File 'lib/hecks/projections/parser_table.rb', line 73 def render(bluebook) table = Hecks::Bluebook::MetaValidator::SyntaxBoot.call keywords = table[:keywords] arguments = table[:arguments] <<~RUST // GENERATED by bin/project_parser_table from // aggregate-local syntax tables under lib/hecks/language/ — DO NOT EDIT BY HAND. // // Re-run `bin/project_parser_table` after any syntax-table change. // spec/parser_table_spec.rb regenerates this into memory and fails the // normal `bundle exec rspec` suite the moment this file drifts from what // the language currently declares — see that spec and // bin/project_parser_table's own header for why this file is never // hand-edited. #[derive(Debug, Clone, Copy)] pub struct KeywordRow { pub word: &'static str, pub context: &'static str, pub body: &'static str, pub inner: &'static str, pub opens: &'static str, pub fills: &'static str, pub status: &'static str, pub was: &'static str, /// Which shared Hecks::Bluebook::DSL::RuleReference /// primitive this word's own bare form resolves through, /// once it has one ("hash_chain" / "owner_keyed" / /// "sibling_scan") — "" for every word that only ever /// declares. pub resolves_via: &'static str, /// Which disambiguator keyword argument a bare reference /// may supply — "declared_by" today, "" otherwise. pub disambiguator: &'static str, } #[derive(Debug, Clone, Copy)] pub struct ArgumentRow { pub keyword: &'static str, pub context: &'static str, pub at: &'static str, pub named: &'static str, pub kind: &'static str, pub required: &'static str, pub fills: &'static str, pub selects: &'static str, pub pair_key_fills: &'static str, pub pair_value_fills: &'static str, pub pairs_shape: &'static str, pub status: &'static str, pub variadic: &'static str, pub minimum: &'static str, } impl KeywordRow { /// An absent status reads as admitted — the grown-column convention /// syntax_conformance_spec.rb's own `status_of`/`live?` already use. pub fn live(&self) -> bool { matches!(self.status, "" | "admitted" | "deprecated") } } impl ArgumentRow { pub fn live(&self) -> bool { matches!(self.status, "" | "admitted" | "deprecated") } } pub static KEYWORDS: &[KeywordRow] = &[ #{keywords.map { |row| keyword_row(row) }.join("\n")} ]; pub static ARGUMENTS: &[ArgumentRow] = &[ #{arguments.map { |row| argument_row(row) }.join("\n")} ]; #{const_str_array('CONTEXTS', closed_set_members(bluebook, 'Context'))} #{const_str_array('BODIES', closed_set_members(bluebook, 'Body'))} #{const_str_array('ARGUMENT_KINDS', closed_set_members(bluebook, 'ArgumentKind'))} #{const_str_array('PAIRS_SHAPES', closed_set_members(bluebook, 'PairsShape'))} #{const_str_array('STATUSES', closed_set_members(bluebook, 'Status'))} RUST end |
.rows(bluebook, name) ⇒ Object
Every cell as text — exactly spec/syntax_conformance_spec.rb's own
rows helper, reused rather than re-derived: a member's fields decode
back through typed literal decoding on the way out of reconstruction,
and this reads it back as what was written.
33 34 35 36 |
# File 'lib/hecks/projections/parser_table.rb', line 33 def rows(bluebook, name) syntax(bluebook).value_objects.find { |vo| vo.hecks_name == name } .members.map { |row| row.to_h.transform_values(&:to_s) } end |
.rust_string(value) ⇒ Object
A Rust string literal for one field's value — every field here is plain ASCII (a word, a context name, a digit, "true"/"false"), so this only has to be safe against the two characters Rust string literals themselves reserve.
48 |
# File 'lib/hecks/projections/parser_table.rb', line 48 def rust_string(value) = "\"#{value.to_s.gsub('\\', '\\\\\\\\').gsub('"', '\\"')}\"" |
.syntax(bluebook) ⇒ Object
THE CHAPTER IS HANDED OVER, not reached for. This used to open the grammar registry itself, which meant the projection could only ever project one chapter — the language's own. Taking it as an argument is what the projector protocol asks for, and it costs nothing.
27 |
# File 'lib/hecks/projections/parser_table.rb', line 27 def syntax(bluebook) = bluebook.aggregate("Syntax") |