Skip to content

Commit

Permalink
🚧 (parser): Work on earley parser
Browse files Browse the repository at this point in the history
semver: chore
  • Loading branch information
Somfic committed Jun 24, 2024
1 parent 53e8bae commit e34f27a
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 79 deletions.
92 changes: 21 additions & 71 deletions src/abstract_syntax_tree/builder.rs
Original file line number Diff line number Diff line change
@@ -1,82 +1,32 @@
use crate::{
abstract_syntax_tree::Statement,
concrete_syntax_tree::{grammar::NonTerminal, ConcreteSyntax},
diagnostic::{Diagnostic, Error},
diagnostic::{Diagnostic, Error, Severity},
};

use super::AstractSyntax;

pub fn build_ast<'a>(
syntax: &'a ConcreteSyntax<'a>,
) -> Result<AstractSyntax<'a>, Vec<Diagnostic<'a>>> {
let mut diagnostics = Vec::new();
let mut ast = AstractSyntax::Statement(Statement::Empty);

match syntax {
ConcreteSyntax::NonTerminal(NonTerminal::Start, children) => {
match children
.iter()
.map(|child| build_ast(child))
.collect::<Result<Vec<_>, _>>()
{
Ok(_) => {}
Err(err) => {
diagnostics.extend(err);
}
}

ast = AstractSyntax::Statement(Statement::Empty);
}
_ => {
let range = syntax.range();

diagnostics.push(
Diagnostic::error("Structure error").with_error(Error::primary(
range.file_id,
range.position,
range.length,
format!("Expected start, got {:?}", syntax),
)),
);
}
}

if !diagnostics.is_empty() {
Err(diagnostics)
} else {
Ok(ast)
}
}

pub fn build_top_level_statement<'a>(
parse_tree: &'a ConcreteSyntax<'a>,
) -> Result<AstractSyntax<'a>, Vec<Diagnostic<'a>>> {
match parse_tree {
ConcreteSyntax::NonTerminal(NonTerminal::RootItems, children) => {
let root_items = children
.iter()
.map(|child| build_ast(child))
.collect::<Result<Vec<_>, _>>()?;

Ok(AstractSyntax::Statement(Statement::Empty))
}
_ => {
let range = parse_tree.range();

return Err(vec![Diagnostic::error("Structure error").with_error(
Error::primary(
range.file_id,
range.position,
range.length,
"Expected root items",
),
)]);
}
}
}

#[cfg(test)]
mod test {
#[test]
fn test() {}
println!("Parsing {}", syntax);

// match syntax {
// ConcreteSyntax::NonTerminal(NonTerminal::EnumDeclaration, children) => {
// let identifier = children[1].clone();
// let items = children[3].clone();
// }
// _ => Err(vec![Diagnostic {
// severity: Severity::Error,
// title: "Failed to build AST".to_string(),
// errors: vec![Error::primary(
// syntax.range().file_id,
// syntax.range().position,
// syntax.range().length,
// "Failed to build AST",
// )],
// }]),
// }

todo!()
}
10 changes: 7 additions & 3 deletions src/abstract_syntax_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@ use crate::diagnostic::Range;

pub mod builder;

#[derive(Debug)]
pub enum AstractSyntax<'a> {
Statement(Statement<'a>),
}

#[derive(Debug)]
pub enum Statement<'a> {
Empty,
EnumDeclaration(Spanned<'a, EnumDeclaration<'a>>),
}

#[derive(Debug)]
pub struct EnumDeclaration<'a> {
pub identifier: Spanned<'a, &'a str>,
pub items: Vec<Spanned<'a, &'a str>>,
}

#[derive(Debug)]
pub struct Spanned<'a, T> {
pub value: T,
pub range: Range<'a>,
pub value: &'a T,
pub range: &'a Range<'a>,
}
19 changes: 18 additions & 1 deletion src/concrete_syntax_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
diagnostic::{Diagnostic, Error, Range},
scanner::token::Token,
};
use std::collections::HashSet;
use std::{collections::HashSet, fmt::Display};

pub mod grammar;

Expand Down Expand Up @@ -42,6 +42,22 @@ pub enum ConcreteSyntax<'a> {
NonTerminal(NonTerminal, Vec<ConcreteSyntax<'a>>),
}

impl<'a> Display for ConcreteSyntax<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConcreteSyntax::Terminal(token) => write!(f, "{}", token.token_type),
ConcreteSyntax::NonTerminal(non_terminal, children) => {
write!(f, "{}", non_terminal)?;
if !children.is_empty() {
// And (n) children
write!(f, " ({})", children.len())?;
}
Ok(())
}
}
}
}

impl<'a> ConcreteSyntax<'a> {
pub fn range(&'a self) -> Range<'a> {
match self {
Expand Down Expand Up @@ -286,3 +302,4 @@ impl<'a> EarleyParser<'a> {
}
}
}
q
10 changes: 6 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn main() -> Result<()> {
files.insert(
"main",
"
enum colors: green blue red;
enum colors: green blue red
",
);

Expand All @@ -33,7 +33,7 @@ fn main() -> Result<()> {

let parser = concrete_syntax_tree::EarleyParser::default();

let parse_tree = match parser.parse(tokens) {
let concrete_syntax = match parser.parse(tokens) {
Ok(parse_tree) => parse_tree,
Err(diagnostics) => {
diagnostics
Expand All @@ -43,9 +43,9 @@ fn main() -> Result<()> {
}
};

println!("{:#?}", parse_tree);
println!("Concrete syntax:\n{:#?}", concrete_syntax);

let ast = match build_ast(&parse_tree) {
let ast = match build_ast(&concrete_syntax) {
Ok(ast) => ast,
Err(diagnostics) => {
diagnostics
Expand All @@ -55,5 +55,7 @@ fn main() -> Result<()> {
}
};

println!("Abstract syntax:\n{:#?}", ast);

Ok(())
}

0 comments on commit e34f27a

Please sign in to comment.