Skip to content

Commit

Permalink
refactor Ast
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr-Leshiy committed Nov 9, 2024
1 parent c74d50f commit 01c3e1d
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 38 deletions.
2 changes: 1 addition & 1 deletion rust/cbork-cddl-parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ pub enum Extension {
/// - If there is an issue with parsing the CDDL input.
pub fn validate_cddl(input: &mut String, extension: &Extension) -> anyhow::Result<()> {
let ast = parser::parse_cddl(input, extension)?;
preprocessor::process_ast(ast)?;
let _ast = preprocessor::process_ast(ast)?;
Ok(())
}
23 changes: 13 additions & 10 deletions rust/cbork-cddl-parser/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! A parser for CDDL using the [pest](https://github.com/pest-parser/pest).
//! Utilized for parsing in accordance with RFC-8610, RFC-9165.

use pest::{iterators::Pairs, Parser};
use pest::{iterators::Pair, Parser};

use crate::Extension;

Expand Down Expand Up @@ -54,14 +54,13 @@ const POSTLUDE: &str = include_str!("grammar/postlude.cddl");

/// PEST Abstract Syntax Tree (AST) representing parsed CDDL syntax.
#[derive(Debug)]
#[allow(dead_code)]
pub(crate) enum PestAst<'a> {
pub(crate) enum Ast<'a> {
/// Represents the AST for RFC-8610 CDDL rules.
Rfc8610(Pairs<'a, rfc_8610::Rule>),
Rfc8610(Vec<Pair<'a, rfc_8610::Rule>>),
/// Represents the AST for RFC-9165 CDDL rules.
Rfc9165(Pairs<'a, rfc_9165::Rule>),
Rfc9165(Vec<Pair<'a, rfc_9165::Rule>>),
/// Represents the AST for CDDL Modules rules.
Cddl(Pairs<'a, cddl::Rule>),
Cddl(Vec<Pair<'a, cddl::Rule>>),
}

/// Parses and checks semantically a CDDL input string.
Expand All @@ -82,18 +81,22 @@ pub(crate) enum PestAst<'a> {
/// - If there is an issue with parsing the CDDL input.
pub(crate) fn parse_cddl<'a>(
input: &'a mut String, extension: &Extension,
) -> anyhow::Result<PestAst<'a>> {
) -> anyhow::Result<Ast<'a>> {
input.push_str("\n\n");
input.push_str(POSTLUDE);

let ast = match extension {
Extension::RFC8610 => {
rfc_8610::Parser::parse(rfc_8610::Rule::cddl, input).map(PestAst::Rfc8610)?
rfc_8610::Parser::parse(rfc_8610::Rule::cddl, input)
.map(|p| Ast::Rfc8610(p.collect()))?
},
Extension::RFC9165 => {
rfc_9165::Parser::parse(rfc_9165::Rule::cddl, input).map(PestAst::Rfc9165)?
rfc_9165::Parser::parse(rfc_9165::Rule::cddl, input)
.map(|p| Ast::Rfc9165(p.collect()))?
},
Extension::CDDL => {
cddl::Parser::parse(cddl::Rule::cddl, input).map(|p| Ast::Cddl(p.collect()))?
},
Extension::CDDL => cddl::Parser::parse(cddl::Rule::cddl, input).map(PestAst::Cddl)?,
};
Ok(ast)
}
43 changes: 16 additions & 27 deletions rust/cbork-cddl-parser/src/preprocessor/mod.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,37 @@
//! A CDDL AST preprocessor.
//! First processing step, which takes a CDDL `AST` and returning a list of CDDL
//! `Expression`.
//!
//! Preprocessor steps:
//! - Resolve #include and #import directives, by just adding the imported rules into the
//! final expression list
//! - Resolves all generics by taking the generic arguments and substituting it.
//! - Validates the root rule of the AST to be a `cddl` rule.
//! - Filters out all rules that are not `expr` rules.
//! - (TODO) Resolve #include and #import directives, by just adding the imported rules
//! into the final expression list

use anyhow::{anyhow, ensure};
use pest::{
iterators::{Pair, Pairs},
RuleType,
};
use pest::{iterators::Pair, RuleType};

use crate::parser::{cddl, rfc_8610, rfc_9165, PestAst};
use crate::parser::{cddl, rfc_8610, rfc_9165, Ast};

/// Processes the AST.
pub(crate) fn process_ast(ast: PestAst) -> anyhow::Result<()> {
pub(crate) fn process_ast(ast: Ast) -> anyhow::Result<Ast> {
match ast {
PestAst::Rfc8610(ast) => {
let _exprs = process_root(ast, rfc_8610::Rule::cddl, rfc_8610::Rule::expr)?;
Ast::Rfc8610(ast) => {
process_root(ast, rfc_8610::Rule::cddl, rfc_8610::Rule::expr).map(Ast::Rfc8610)
},
PestAst::Rfc9165(ast) => {
let _exprs = process_root(ast, rfc_9165::Rule::cddl, rfc_9165::Rule::expr)?;
},
PestAst::Cddl(ast) => {
let exprs = process_root(ast, cddl::Rule::cddl, cddl::Rule::expr)?;

for expr in exprs {
println!("{:?}", expr.as_rule());
}
Ast::Rfc9165(ast) => {
process_root(ast, rfc_9165::Rule::cddl, rfc_9165::Rule::expr).map(Ast::Rfc9165)
},
Ast::Cddl(ast) => process_root(ast, cddl::Rule::cddl, cddl::Rule::expr).map(Ast::Cddl),
}
Ok(())
}

/// Process the root rule of the AST.
/// Returns a vector of expressions of the underlying AST.
fn process_root<R: RuleType>(
mut ast: Pairs<'_, R>, root_rule: R, expr_rule: R,
ast: Vec<Pair<'_, R>>, root_rule: R, expr_rule: R,
) -> anyhow::Result<Vec<Pair<'_, R>>> {
let ast_root = ast.next().ok_or(anyhow!("Empty AST."))?;
let mut ast_iter = ast.into_iter();
let ast_root = ast_iter.next().ok_or(anyhow!("Empty AST."))?;
ensure!(
ast_root.as_rule() == root_rule && ast.next().is_none(),
ast_root.as_rule() == root_rule && ast_iter.next().is_none(),
"AST must have only one root rule, which must be a `{root_rule:?}` rule."
);
Ok(ast_root
Expand Down

0 comments on commit 01c3e1d

Please sign in to comment.