Finally building an AST with Pest.

This commit is contained in:
Jesse Brault 2025-01-30 18:36:35 -06:00
parent 085f60ab4f
commit 040961ed67
5 changed files with 143 additions and 2 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
/target
.idea
.idea
*.swp

134
src/ast/mod.rs Normal file
View File

@ -0,0 +1,134 @@
use pest::{iterators::{Pair, Pairs}, Parser};
use crate::parser::{DeimosParser, Rule};
#[derive(Debug)]
pub struct CompilationUnit {
namespace: Option<Fqn>,
declarations: Vec<Declaration>,
}
#[derive(Debug)]
pub struct Fqn {
identifiers: Vec<Identifier>
}
#[derive(Debug)]
pub enum Declaration {
Interface {
identifier: Identifier,
type_declaration: TypeDeclaration,
},
Implementation {
identifier: Identifier,
type_declaration: TypeDeclaration
},
Module {
identifier: Identifier,
declarations: Vec<Declaration>,
},
Function {
identifier: Identifier,
statement: Statement
}
}
#[derive(Debug)]
pub struct TypeDeclaration {
generics: Vec<GenericParameter>,
extends: Vec<Identifier>,
declarations: Vec<Declaration>,
}
#[derive(Debug)]
pub struct Identifier {
name: String
}
#[derive(Debug)]
pub struct GenericParameter {
identifier: Identifier,
bound: Option<GenericBound>
}
#[derive(Debug)]
pub enum GenericBound {
Extends {
identifier: Identifier
},
Super {
identifier: Identifier
}
}
#[derive(Debug)]
pub enum Statement {
BlockStatement {
statements: Vec<Statement>
},
CallStatement,
AssignmentStatement
}
fn build_identifier(pair: Pair<Rule>) -> Identifier {
match pair.as_rule() {
Rule::identifier => {
Identifier {
name: String::from(pair.as_str())
}
}
_ => panic!("Expected an identifier.")
}
}
fn build_fqn(fqn_pair: Pair<Rule>) -> Fqn {
let mut identifiers: Vec<Identifier> = vec![];
for pair in fqn_pair.into_inner() {
match pair.as_rule() {
Rule::identifier => {
identifiers.push(build_identifier(pair));
}
_ => panic!("Expected only identifiers.")
}
}
Fqn {
identifiers
}
}
fn build_compilation_unit(pair: Pair<Rule>)-> CompilationUnit {
let mut namespace: Option<Fqn> = None;
let mut declarations: Vec<Declaration> = vec![];
for pair in pair.into_inner() {
match pair.as_rule() {
Rule::namespace => {
let fqn_pair = pair.into_inner().next().unwrap();
namespace = Some(build_fqn(fqn_pair));
}
Rule::declaration => {
todo!();
}
Rule::EOI => {} // ignore
_ => panic!("Expected only namespace, declaration, or EOI rules, found: {}", pair)
}
}
CompilationUnit {
namespace,
declarations
}
}
pub fn build_ast(src: &str) -> CompilationUnit {
let pair = DeimosParser::parse(Rule::compilation_unit, src)
.expect("Unsuccessful parse.")
.next()
.expect("Expcted compilation_unit.");
match pair.as_rule() {
Rule::compilation_unit => {
build_compilation_unit(pair)
},
_ => panic!("Expected compilation_unit rule.")
}
}

View File

@ -1,3 +1,4 @@
use deimos::ast::build_ast;
use deimos::vm::dm_type::DmType;
use deimos::vm::lib::{DmConstant, DmLib};
use deimos::vm::object_type::{DmField, DmFn, DmImplementation, DmInterface, DmMethod};
@ -13,6 +14,9 @@ fn main() {
// - write a single lib with a main()
// - call the main fn
// fn main() { println "Hello, World!" }
let compilation_unit = build_ast("ns hello::test::bye");
println!("{:?}", compilation_unit);
// std/core/array lib
let mut array_lib = DmLib::new("std/core/array");

View File

@ -1,4 +1,6 @@
#![allow(warnings)]
mod compiler;
pub mod parser;
mod util;
pub mod vm;
pub mod ast;

View File

@ -58,4 +58,4 @@ string_char = {
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
}
WHITESPACE = _{ " " | "\t" | "\n" | "\r" }
WHITESPACE = _{ " " | "\t" | "\n" | "\r" }