Skip to content

Commit

Permalink
Use model::VersionSpecifier instead of VersionQualityRange
Browse files Browse the repository at this point in the history
  • Loading branch information
Xanewok committed May 22, 2024
1 parent 7c72891 commit 6dc9776
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 160 deletions.
56 changes: 41 additions & 15 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, Language};
use codegen_language_definition::model::{Identifier, Language, VersionSpecifier};
use quote::{format_ident, quote};
use semver::Version;
use serde::Serialize;
Expand Down Expand Up @@ -254,13 +254,21 @@ impl GrammarVisitor for ParserAccumulatorState {
for def in scanner.definitions() {
let versions = def.enabled.iter().chain(def.reserved.iter());

self.referenced_versions.extend(
versions
.map(|vqr| &vqr.from)
// "Removed from 0.0.0" is an alias for "never"; it's never directly checked
.filter(|v| *v != &Version::new(0, 0, 0))
.cloned(),
);
for version in versions {
match version {
VersionSpecifier::Never => {}
VersionSpecifier::From { from } => {
self.referenced_versions.insert(from.clone());
}
VersionSpecifier::Till { till } => {
self.referenced_versions.insert(till.clone());
}
VersionSpecifier::Range { from, till } => {
self.referenced_versions.insert(from.clone());
self.referenced_versions.insert(till.clone());
}
}
}
}
}

Expand Down Expand Up @@ -338,20 +346,38 @@ impl GrammarVisitor for ParserAccumulatorState {
}

fn scanner_definition_node_enter(&mut self, node: &ScannerDefinitionNode) {
if let ScannerDefinitionNode::Versioned(_, version_quality_ranges) = node {
for vqr in version_quality_ranges {
self.referenced_versions.insert(vqr.from.clone());
if let ScannerDefinitionNode::Versioned(_, version_specifier) = node {
match version_specifier {
VersionSpecifier::Never => {}
VersionSpecifier::From { from } => {
self.referenced_versions.insert(from.clone());
}
VersionSpecifier::Till { till } => {
self.referenced_versions.insert(till.clone());
}
VersionSpecifier::Range { from, till } => {
self.referenced_versions.insert(from.clone());
self.referenced_versions.insert(till.clone());
}
}
}
}

fn parser_definition_node_enter(&mut self, node: &ParserDefinitionNode) {
match node {
ParserDefinitionNode::Versioned(_, version_quality_ranges) => {
for vqr in version_quality_ranges {
self.referenced_versions.insert(vqr.from.clone());
ParserDefinitionNode::Versioned(_, version_specifier) => match version_specifier {
VersionSpecifier::Never => {}
VersionSpecifier::From { from } => {
self.referenced_versions.insert(from.clone());
}
}
VersionSpecifier::Till { till } => {
self.referenced_versions.insert(till.clone());
}
VersionSpecifier::Range { from, till } => {
self.referenced_versions.insert(from.clone());
self.referenced_versions.insert(till.clone());
}
},
ParserDefinitionNode::ScannerDefinition(scanner) => {
self.top_level_scanner_names.insert(scanner.name().clone());
self.terminal_kinds.insert(scanner.name().clone());
Expand Down
2 changes: 0 additions & 2 deletions crates/codegen/runtime/generator/src/parser/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ pub mod constructor;
pub mod parser_definition;
pub mod precedence_parser_definition;
pub mod scanner_definition;
pub mod version_quality;
pub mod visitor;

pub use parser_definition::*;
pub use precedence_parser_definition::*;
pub use scanner_definition::*;
pub use version_quality::*;
pub use visitor::*;

pub struct Grammar {
Expand Down
60 changes: 9 additions & 51 deletions crates/codegen/runtime/generator/src/parser/grammar/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ use indexmap::IndexMap;
use once_cell::sync::Lazy;

use crate::parser::grammar::{
DelimitedRecoveryTokenThreshold, Grammar, GrammarElement, KeywordScannerDefinition,
KeywordScannerDefinitionVersionedNode, Labeled, ParserDefinition, ParserDefinitionNode,
PrecedenceParserDefinition, PrecedenceParserDefinitionNode, ScannerDefinition,
ScannerDefinitionNode, TriviaParserDefinition, VersionQuality, VersionQualityRange,
DelimitedRecoveryTokenThreshold, Grammar, GrammarElement, KeywordScannerDefinition, Labeled,
ParserDefinition, ParserDefinitionNode, PrecedenceParserDefinition,
PrecedenceParserDefinitionNode, ScannerDefinition, ScannerDefinitionNode,
TriviaParserDefinition,
};

impl Grammar {
Expand Down Expand Up @@ -133,15 +133,15 @@ impl ScannerDefinition for NamedScanner {
struct NamedKeywordScanner {
name: Identifier,
identifier_scanner_name: Identifier,
defs: Vec<KeywordScannerDefinitionVersionedNode>,
defs: Vec<model::KeywordDefinition>,
}

impl KeywordScannerDefinition for NamedKeywordScanner {
fn name(&self) -> &Identifier {
&self.name
}

fn definitions(&self) -> &[KeywordScannerDefinitionVersionedNode] {
fn definitions(&self) -> &[model::KeywordDefinition] {
&self.defs
}

Expand Down Expand Up @@ -237,37 +237,6 @@ impl ParserThunk {
}
}

fn enabled_to_range(spec: impl Into<Option<model::VersionSpecifier>>) -> Vec<VersionQualityRange> {
let Some(spec) = spec.into() else {
return vec![];
};

match spec {
model::VersionSpecifier::Never => vec![VersionQualityRange {
from: semver::Version::new(0, 0, 0),
quality: VersionQuality::Removed,
}],
model::VersionSpecifier::From { from } => vec![VersionQualityRange {
from,
quality: VersionQuality::Introduced,
}],
model::VersionSpecifier::Till { till } => vec![VersionQualityRange {
from: till,
quality: VersionQuality::Removed,
}],
model::VersionSpecifier::Range { from, till } => vec![
VersionQualityRange {
from,
quality: VersionQuality::Introduced,
},
VersionQualityRange {
from: till,
quality: VersionQuality::Removed,
},
],
}
}

struct ResolveCtx<'a> {
items: &'a HashMap<Identifier, (Option<Identifier>, Item)>,
resolved: &'a mut HashMap<Identifier, GrammarElement>,
Expand Down Expand Up @@ -384,21 +353,10 @@ fn resolve_grammar_element(ident: &Identifier, ctx: &mut ResolveCtx<'_>) -> Gram
def: resolve_token(item.deref().clone(), ctx),
},
Item::Keyword { item } => {
let defs: Vec<_> = item
.definitions
.iter()
.cloned()
.map(|def| KeywordScannerDefinitionVersionedNode {
value: def.value,
enabled: enabled_to_range(def.enabled),
reserved: enabled_to_range(def.reserved),
})
.collect();

let kw_scanner = NamedKeywordScanner {
name: ident.clone(),
identifier_scanner_name: item.identifier.clone(),
defs,
defs: item.definitions.clone(),
};

// Keywords are special scanners and are handled separately
Expand Down Expand Up @@ -812,7 +770,7 @@ trait VersionWrapped {
impl VersionWrapped for ParserDefinitionNode {
fn versioned(self, enabled: Option<model::VersionSpecifier>) -> Self {
if let Some(enabled) = enabled {
Self::Versioned(Box::new(self), enabled_to_range(enabled))
Self::Versioned(Box::new(self), enabled)
} else {
self
}
Expand All @@ -822,7 +780,7 @@ impl VersionWrapped for ParserDefinitionNode {
impl VersionWrapped for ScannerDefinitionNode {
fn versioned(self, enabled: Option<model::VersionSpecifier>) -> Self {
if let Some(enabled) = enabled {
Self::Versioned(Box::new(self), enabled_to_range(enabled))
Self::Versioned(Box::new(self), enabled)
} else {
self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use codegen_language_definition::model::{self, Identifier};
use crate::parser::grammar::visitor::{GrammarVisitor, Visitable};
use crate::parser::grammar::{
KeywordScannerDefinitionRef, PrecedenceParserDefinitionRef, ScannerDefinitionRef,
VersionQualityRange,
};

/// A named wrapper, used to give a name to a [`ParserDefinitionNode`].
Expand Down Expand Up @@ -76,7 +75,7 @@ impl From<model::FieldDelimiters> for DelimitedRecoveryTokenThreshold {

#[derive(Clone, Debug)]
pub enum ParserDefinitionNode {
Versioned(Box<Self>, Vec<VersionQualityRange>),
Versioned(Box<Self>, model::VersionSpecifier),
Optional(Box<Self>),
ZeroOrMore(Labeled<Box<Self>>),
OneOrMore(Labeled<Box<Self>>),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::rc::Rc;

use codegen_language_definition::model::{self, Identifier};

use crate::parser::grammar::{GrammarVisitor, VersionQualityRange, Visitable};
use crate::parser::grammar::{GrammarVisitor, Visitable};

pub trait ScannerDefinition: Debug {
fn name(&self) -> &Identifier;
Expand All @@ -21,7 +21,7 @@ impl Visitable for ScannerDefinitionRef {

#[derive(Clone, Debug)]
pub enum ScannerDefinitionNode {
Versioned(Box<Self>, Vec<VersionQualityRange>),
Versioned(Box<Self>, model::VersionSpecifier),
Optional(Box<Self>),
ZeroOrMore(Box<Self>),
OneOrMore(Box<Self>),
Expand Down Expand Up @@ -71,7 +71,7 @@ impl Visitable for ScannerDefinitionNode {
pub trait KeywordScannerDefinition: Debug {
fn name(&self) -> &Identifier;
fn identifier_scanner(&self) -> &Identifier;
fn definitions(&self) -> &[KeywordScannerDefinitionVersionedNode];
fn definitions(&self) -> &[model::KeywordDefinition];
}

pub type KeywordScannerDefinitionRef = Rc<dyn KeywordScannerDefinition>;
Expand All @@ -82,16 +82,6 @@ impl Visitable for KeywordScannerDefinitionRef {
}
}

#[derive(Debug)]
pub struct KeywordScannerDefinitionVersionedNode {
// Underlying keyword scanner (i.e. identifier scanner)
pub value: model::KeywordValue,
/// When the keyword scanner is enabled
pub enabled: Vec<VersionQualityRange>,
/// When the keyword is reserved, i.e. can't be used in other position (e.g. as a name)
pub reserved: Vec<VersionQualityRange>,
}

impl From<model::KeywordValue> for ScannerDefinitionNode {
fn from(val: model::KeywordValue) -> Self {
match val {
Expand Down Expand Up @@ -121,7 +111,7 @@ impl KeywordScannerAtomic {
/// Wraps the keyword scanner definition if it is a single atom value.
pub fn try_from_def(def: &KeywordScannerDefinitionRef) -> Option<Self> {
match def.definitions() {
[KeywordScannerDefinitionVersionedNode {
[model::KeywordDefinition {
value: model::KeywordValue::Atom { .. },
..
}] => Some(Self(Rc::clone(def))),
Expand All @@ -139,13 +129,16 @@ impl std::ops::Deref for KeywordScannerAtomic {
}

impl KeywordScannerAtomic {
pub fn definition(&self) -> &KeywordScannerDefinitionVersionedNode {
let def = &self.0.definitions().first();
def.expect("KeywordScannerAtomic should have exactly one definition")
pub fn definition(&self) -> &model::KeywordDefinition {
self.0
.definitions()
.first()
.expect("KeywordScannerAtomic should have exactly one definition")
}

pub fn value(&self) -> &str {
match self.definition() {
KeywordScannerDefinitionVersionedNode {
model::KeywordDefinition {
value: model::KeywordValue::Atom { atom },
..
} => atom,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ impl KeywordScannerDefinitionExtensions for KeywordScannerDefinitionRef {
.iter()
.map(|versioned_kw| {
let scanner = versioned_kw.value.to_scanner_code();
let enabled_cond = versioned_kw.enabled.as_bool_expr();
let reserved_cond = versioned_kw.reserved.as_bool_expr();
let enabled_cond = versioned_kw.enabled.as_ref().as_bool_expr();
let reserved_cond = versioned_kw.reserved.as_ref().as_bool_expr();

// Simplify the emitted code if we trivially know that reserved or enabled is true
match (&*reserved_cond.to_string(), &*enabled_cond.to_string()) {
Expand Down
Loading

0 comments on commit 6dc9776

Please sign in to comment.