Skip to content

Commit

Permalink
turn OperatorDefinition into ParserRefs
Browse files Browse the repository at this point in the history
Allows us to:

- de-duplicate large operators across different versions
- add names to operators, doing in #353

note: some of the additional nodes (like `ConditionalOperator`) will be inlined in #323

closes #374
  • Loading branch information
OmarTawfik committed May 24, 2023
1 parent c803a68 commit 1f7df16
Show file tree
Hide file tree
Showing 95 changed files with 15,231 additions and 28,974 deletions.
5 changes: 5 additions & 0 deletions .changeset/hot-suits-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"changelog": minor
---

move expression operators into separate nodes
16 changes: 8 additions & 8 deletions crates/codegen/ebnf/src/precedence_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ impl GenerateEbnf for PrecedenceParserRef {
fn generate_ebnf(&self) -> EbnfNode {
let mut choices = vec![];

for operator in &self.definition.operators {
for definition in &self.definition.definitions {
let mut comment = None;

let operator_body = match operator.model {
let operator = match definition.model {
OperatorModel::BinaryLeftAssociative => EbnfNode::sequence(vec![
EbnfNode::BaseProduction,
operator.definition.generate_ebnf(),
definition.operator.generate_ebnf(),
EbnfNode::BaseProduction,
]),

Expand All @@ -21,25 +21,25 @@ impl GenerateEbnf for PrecedenceParserRef {

EbnfNode::sequence(vec![
EbnfNode::BaseProduction,
operator.definition.generate_ebnf(),
definition.operator.generate_ebnf(),
EbnfNode::BaseProduction,
])
}
OperatorModel::UnaryPrefix => EbnfNode::sequence(vec![
operator.definition.generate_ebnf(),
definition.operator.generate_ebnf(),
EbnfNode::BaseProduction,
]),

OperatorModel::UnaryPostfix => EbnfNode::sequence(vec![
EbnfNode::BaseProduction,
operator.definition.generate_ebnf(),
definition.operator.generate_ebnf(),
]),
};

choices.push(EbnfNode::sub_statement(
operator.name.to_owned(),
definition.name.to_owned(),
comment,
operator_body,
operator,
));
}

Expand Down
163 changes: 6 additions & 157 deletions crates/codegen/schema/generated/productions.schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions crates/codegen/schema/src/types/precedence_parser.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use super::parser::{ParserDefinition, ParserRef};
use crate::types::parser::ParserRef;

#[allow(dead_code)]
pub type PrecedenceParserRef = std::rc::Rc<PrecedenceParser>;
Expand All @@ -19,7 +19,7 @@ pub struct PrecedenceParser {
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct PrecedenceParserDefinition {
#[schemars(title = "Operator Definitions")]
pub operators: Vec<OperatorDefinition>,
pub definitions: Vec<OperatorDefinition>,

#[schemars(title = "Primary Expression")]
pub primary_expression: ParserRef,
Expand All @@ -30,8 +30,7 @@ pub struct PrecedenceParserDefinition {
pub struct OperatorDefinition {
pub name: String,
pub model: OperatorModel,
#[serde(flatten)]
pub definition: ParserDefinition,
pub operator: ParserRef,
}

#[derive(Clone, Copy, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Hash)]
Expand Down
14 changes: 7 additions & 7 deletions crates/codegen/schema/src/validation/ast/precedence_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{types, yaml::cst};

use super::{
node::Node,
parser::{Parser, ParserDefinition, ParserRef},
parser::{Parser, ParserRef},
production::ConcreteAbstractPair,
};

Expand All @@ -29,7 +29,7 @@ impl ConcreteAbstractPair for PrecedenceParser {
}

pub struct PrecedenceParserDefinition {
pub operators: Vec<Node<OperatorDefinition>>,
pub definitions: Vec<Node<OperatorDefinition>>,
pub primary_expression: ParserRef,
}

Expand All @@ -39,9 +39,9 @@ impl PrecedenceParserDefinition {
value: types::precedence_parser::PrecedenceParserDefinition,
) -> Self {
return Self {
operators: {
let cst_node = cst_node.field("operators");
cst_node.zip(value.operators, OperatorDefinition::new)
definitions: {
let cst_node = cst_node.field("definitions");
cst_node.zip(value.definitions, OperatorDefinition::new)
},
primary_expression: Parser::new(
&cst_node.value_of_field("primaryExpression"),
Expand All @@ -54,7 +54,7 @@ impl PrecedenceParserDefinition {
pub struct OperatorDefinition {
pub name: Node<String>,
pub model: Node<types::precedence_parser::OperatorModel>,
pub definition: Node<ParserDefinition>,
pub operator: ParserRef,
}

impl OperatorDefinition {
Expand All @@ -67,7 +67,7 @@ impl OperatorDefinition {
OperatorDefinition {
name: Node::new(cst_node.value_of_field("name"), value.name),
model: Node::new(cst_node.value_of_field("model"), value.model),
definition: ParserDefinition::new(cst_node, value.definition),
operator: Parser::new(&cst_node.value_of_field("operator"), value.operator),
},
);
}
Expand Down
6 changes: 3 additions & 3 deletions crates/codegen/schema/src/validation/ast/visitors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ impl Receiver for ParserDefinition {
impl Receiver for PrecedenceParserRef {
fn receive<V: Visitor>(&self, visitor: &mut V, reporter: &mut Reporter) {
if visitor.visit_precedence_parser(self, reporter) == VisitorResponse::StepIn {
for operator in &self.definition.operators {
operator.value.receive(visitor, reporter);
for definition in &self.definition.definitions {
definition.value.receive(visitor, reporter);
}
self.definition
.primary_expression
Expand All @@ -296,7 +296,7 @@ impl Receiver for PrecedenceParserRef {
impl Receiver for OperatorDefinition {
fn receive<V: Visitor>(&self, visitor: &mut V, reporter: &mut Reporter) {
if visitor.visit_operator_definition(self, reporter) == VisitorResponse::StepIn {
self.definition.value.receive(visitor, reporter)
self.operator.receive(visitor, reporter)
}
}
}
10 changes: 5 additions & 5 deletions crates/codegen/syntax/src/combinator_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,13 @@ impl<'context> CombinatorNode<'context> {
let primary_expression = Self::from_parser(tree, &parser.definition.primary_expression);
let operators: Vec<PrecedenceRuleOperator> = parser
.definition
.operators
.definitions
.iter()
.map(|operator| -> PrecedenceRuleOperator {
.map(|definition| -> PrecedenceRuleOperator {
PrecedenceRuleOperator {
name: operator.name.clone(),
model: operator.model,
operator: Self::from_parser_definition(tree, None, &operator.definition),
name: definition.name.clone(),
model: definition.model,
operator: Self::from_parser(tree, &definition.operator),
}
})
.collect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,26 @@
- name: "VersionPragmaExpression"
kind: "PrecedenceParser"
unversioned:
operators:
definitions:
- name: "VersionPragmaAlternatives"
model: "BinaryLeftAssociative"
reference: "BarBar"
operator:
reference: "BarBar"
- name: "VersionPragmaRange"
model: "BinaryLeftAssociative"
reference: "Minus"
operator:
reference: "Minus"
- name: "VersionPragmaComparator"
model: "UnaryPrefix"
choice:
- reference: "Caret"
- reference: "Tilde"
- reference: "Equal"
- reference: "LessThan"
- reference: "GreaterThan"
- reference: "LessThanEqual"
- reference: "GreaterThanEqual"
operator:
choice:
- reference: "Caret"
- reference: "Tilde"
- reference: "Equal"
- reference: "LessThan"
- reference: "GreaterThan"
- reference: "LessThanEqual"
- reference: "GreaterThanEqual"

primaryExpression:
reference: "VersionPragmaSpecifier"
Expand Down
Loading

0 comments on commit 1f7df16

Please sign in to comment.