Skip to content

Commit

Permalink
refactor: Separate a dedicated model for generated kinds.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
Xanewok committed May 29, 2024
1 parent 0d144df commit 6ec9ec0
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 93 deletions.
12 changes: 6 additions & 6 deletions crates/codegen/runtime/cargo/src/runtime/kinds.rs.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub enum NonterminalKind {
Stub2,
Stub3,
{%- else -%}
{%- for variant in model.parser.nonterminal_kinds -%}
{%- for variant in model.kinds.nonterminal_kinds -%}
{# variant.documentation | indent(prefix = "/// ", first = true, blank = true) #}
{{ variant }},
{%- endfor -%}
Expand Down Expand Up @@ -65,7 +65,7 @@ pub enum EdgeLabel {
Stub2,
Stub3,
{%- else -%}
{% for variant in model.parser.labels -%}
{% for variant in model.kinds.labels -%}
{{ variant | pascal_case }},
{%- endfor -%}
{%- endif -%}
Expand Down Expand Up @@ -98,7 +98,7 @@ pub enum TerminalKind {
Stub2,
Stub3,
{%- else -%}
{%- for variant in model.parser.terminal_kinds -%}
{%- for variant in model.kinds.terminal_kinds -%}
{# variant.documentation | indent(prefix = "/// ", first = true, blank = true) #}
{{ variant }},
{%- endfor -%}
Expand All @@ -112,7 +112,7 @@ impl metaslang_cst::TerminalKind for TerminalKind {
{%- else -%}
matches!(
self,
{%- for variant in model.parser.trivia_scanner_names -%}
{%- for variant in model.kinds.trivia_scanner_names -%}
| Self::{{ variant }}
{%- endfor -%}
)
Expand All @@ -128,7 +128,7 @@ pub(crate) enum LexicalContext {
Stub2,
Stub3,
{%- else -%}
{%- for context_name, _ in model.parser.scanner_contexts %}
{%- for context_name in model.kinds.lexical_contexts %}
{{ context_name }},
{%- endfor %}
{%- endif -%}
Expand All @@ -143,7 +143,7 @@ pub(crate) trait IsLexicalContext {
#[allow(non_snake_case)]
pub(crate) mod LexicalContextType {
{%- if not rendering_in_stubs -%}
{%- for context_name, _ in model.parser.scanner_contexts %}
{%- for context_name in model.kinds.lexical_contexts %}
pub struct {{ context_name }};

impl super::IsLexicalContext for {{ context_name }} {
Expand Down
98 changes: 98 additions & 0 deletions crates/codegen/runtime/generator/src/kinds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use std::collections::BTreeSet;

use codegen_language_definition::model::{self, Identifier, Item};
use serde::Serialize;

#[derive(Default, Serialize)]
pub struct KindsModel {
/// Defines the `NonterminalKind` enum variants.
nonterminal_kinds: BTreeSet<Identifier>,
/// Defines the `TerminalKind` enum variants.
terminal_kinds: BTreeSet<Identifier>,
/// Defines `TerminalKind::is_trivia` method.
trivia_scanner_names: BTreeSet<Identifier>,
/// Defines `EdgeLabel` enum variants.
labels: BTreeSet<Identifier>,
// Defines the `LexicalContext(Type)` enum and type-level variants.
lexical_contexts: BTreeSet<Identifier>,
}

impl KindsModel {
pub fn create(language: &model::Language) -> Self {
let terminal_kinds = language
.items()
.filter(|item| item.is_terminal() && !matches!(item, Item::Fragment { .. }))
.map(|item| item.name().clone())
.collect();

let mut nonterminal_kinds = BTreeSet::default();
for item in language.items() {
match item {
Item::Struct { item } => {
nonterminal_kinds.insert(item.name.clone());
}
Item::Enum { item } => {
nonterminal_kinds.insert(item.name.clone());
}
Item::Repeated { item } => {
nonterminal_kinds.insert(item.name.clone());
}
Item::Separated { item } => {
nonterminal_kinds.insert(item.name.clone());
}
Item::Precedence { item } => {
nonterminal_kinds.insert(item.name.clone());
for op in &item.precedence_expressions {
nonterminal_kinds.insert(op.name.clone());
}
}
// Terminals
_ => {}
}
}

let trivia_scanner_names = language
.items()
.filter_map(|item| match item {
Item::Trivia { item } => Some(item.name.clone()),
_ => None,
})
.collect();

let mut labels = BTreeSet::default();
for item in language.items() {
match item {
Item::Struct { item } => {
for field_name in item.fields.keys() {
labels.insert(field_name.clone());
}
}
Item::Precedence { item } => {
for item in &item.precedence_expressions {
for item in &item.operators {
for field_name in item.fields.keys() {
labels.insert(field_name.clone());
}
}
}
}
_ => {}
}
}

let lexical_contexts: BTreeSet<_> = language
.topics()
.filter_map(|t| t.lexical_context.as_ref())
.cloned()
.chain(std::iter::once(Identifier::from("Default")))
.collect();

KindsModel {
nonterminal_kinds,
terminal_kinds,
trivia_scanner_names,
labels,
lexical_contexts,
}
}
}
1 change: 1 addition & 0 deletions crates/codegen/runtime/generator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use serde::Serialize;
use crate::model::RuntimeModel;

mod ast;
mod kinds;
mod model;
mod parser;

Expand Down
3 changes: 3 additions & 0 deletions crates/codegen/runtime/generator/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use semver::Version;
use serde::Serialize;

use crate::ast::AstModel;
use crate::kinds::KindsModel;
use crate::parser::ParserModel;

#[derive(Default, Serialize)]
Expand All @@ -14,6 +15,7 @@ pub struct RuntimeModel {
all_versions: BTreeSet<Version>,
parser: ParserModel,
ast: AstModel,
kinds: KindsModel,
}

impl RuntimeModel {
Expand All @@ -22,6 +24,7 @@ impl RuntimeModel {
all_versions: language.versions.iter().cloned().collect(),
ast: AstModel::create(language),
parser: ParserModel::from_language(language),
kinds: KindsModel::create(language),
}
}
}
88 changes: 1 addition & 87 deletions crates/codegen/runtime/generator/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::collections::{BTreeMap, BTreeSet};
use std::rc::Rc;

use codegen_language_definition::model::{Identifier, Item, Language};
use codegen_language_definition::model::{Identifier, Language};
use semver::Version;
use serde::Serialize;

Expand All @@ -29,15 +29,6 @@ pub struct ParserModel {
/// Constructs inner `Language` the state to evaluate the version-dependent branches.
referenced_versions: BTreeSet<Version>,

/// Defines the `NonterminalKind` enum variants.
nonterminal_kinds: BTreeSet<Identifier>,
/// Defines the `TerminalKind` enum variants.
terminal_kinds: BTreeSet<Identifier>,
/// Defines `TerminalKind::is_trivia` method.
trivia_scanner_names: BTreeSet<Identifier>,
/// Defines `EdgeLabel` enum variants.
labels: BTreeSet<String>,

/// Defines the top-level scanner functions in `Language`.
scanner_functions: BTreeMap<Identifier, RustCode>, // (name of scanner, code)
// Defines the `LexicalContext(Type)` enum and type-level variants.
Expand Down Expand Up @@ -98,14 +89,6 @@ struct ScannerContextAccumulatorState {
struct DslV2CollectorState {
/// Constructs inner `Language` the state to evaluate the version-dependent branches.
referenced_versions: BTreeSet<Version>,
/// Defines the `TerminalKind` enum variants.
terminal_kinds: BTreeSet<Identifier>,
/// Defines the `NonterminalKind` enum variants.
nonterminal_kinds: BTreeSet<Identifier>,
/// Defines `TerminalKind::is_trivia` method.
trivia_scanner_names: BTreeSet<Identifier>,
/// Defines `EdgeLabel` enum variants.
labels: BTreeSet<String>,
}

impl ParserModel {
Expand All @@ -117,73 +100,8 @@ impl ParserModel {
grammar.accept_visitor(&mut acc);

// WIP(#638): Gradually migrate off `GrammarVisitor`
let terminal_kinds = language
.items()
.filter(|item| item.is_terminal() && !matches!(item, Item::Fragment { .. }))
.map(|item| item.name().clone())
.collect();

let mut nonterminal_kinds = BTreeSet::default();
for item in language.items() {
match item {
Item::Struct { item } => {
nonterminal_kinds.insert(item.name.clone());
}
Item::Enum { item } => {
nonterminal_kinds.insert(item.name.clone());
}
Item::Repeated { item } => {
nonterminal_kinds.insert(item.name.clone());
}
Item::Separated { item } => {
nonterminal_kinds.insert(item.name.clone());
}
Item::Precedence { item } => {
nonterminal_kinds.insert(item.name.clone());
for op in &item.precedence_expressions {
nonterminal_kinds.insert(op.name.clone());
}
}
// Terminals
_ => {}
}
}

let trivia_scanner_names = language
.items()
.filter_map(|item| match item {
Item::Trivia { item } => Some(item.name.clone()),
_ => None,
})
.collect();

let mut labels = BTreeSet::default();
for item in language.items() {
match item {
Item::Struct { item } => {
for field_name in item.fields.keys() {
labels.insert(field_name.to_string());
}
}
Item::Precedence { item } => {
for item in &item.precedence_expressions {
for item in &item.operators {
for field_name in item.fields.keys() {
labels.insert(field_name.to_string());
}
}
}
}
_ => {}
}
}

acc.into_model(DslV2CollectorState {
referenced_versions: language.collect_breaking_versions(),
terminal_kinds,
nonterminal_kinds,
trivia_scanner_names,
labels,
})
}
}
Expand Down Expand Up @@ -288,10 +206,6 @@ impl ParserAccumulatorState {
keyword_compound_scanners,
// These are derived from the DSLv2 model directly
referenced_versions: collected.referenced_versions,
terminal_kinds: collected.terminal_kinds,
nonterminal_kinds: collected.nonterminal_kinds,
trivia_scanner_names: collected.trivia_scanner_names,
labels: collected.labels,
}
}
}
Expand Down

0 comments on commit 6ec9ec0

Please sign in to comment.