cleanup parse tree
This commit is contained in:
parent
f649edf9a5
commit
686e43448a
3 changed files with 111 additions and 30 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1,3 @@
|
||||||
/target
|
/target
|
||||||
|
|
||||||
|
log*
|
|
@ -436,6 +436,12 @@ impl<
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
pub trait Skippable {
|
||||||
|
fn skippable(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum NodeChild<N, S> {
|
pub enum NodeChild<N, S> {
|
||||||
Child(ParseTree<N, S>),
|
Child(ParseTree<N, S>),
|
||||||
|
@ -457,3 +463,41 @@ impl<N, S> ParseTree<N, S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N: Skippable + Debug, S: Debug> ParseTree<N, S> {
|
||||||
|
/// cleanup the parse tree
|
||||||
|
/// does not work on a subtree
|
||||||
|
pub fn clean(self) -> Self {
|
||||||
|
self.clean_internal()
|
||||||
|
.expect("Clean only works on the main tree.")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// internal clean
|
||||||
|
/// main node must not have a rule.
|
||||||
|
fn clean_internal(self) -> Result<Self, Vec<NodeChild<N, S>>> {
|
||||||
|
let childs = self
|
||||||
|
.childs
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|elem| match elem {
|
||||||
|
NodeChild::Child(parse_tree) => match parse_tree.clean_internal() {
|
||||||
|
Ok(tree) => [NodeChild::Child(tree)].into(),
|
||||||
|
Err(content) => content,
|
||||||
|
},
|
||||||
|
NodeChild::Data(d) => [NodeChild::Data(d)].into(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
if let Some((rule, _)) = &self.rule {
|
||||||
|
if rule.skippable() {
|
||||||
|
return Err(childs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if childs.is_empty() {
|
||||||
|
return Err(childs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
rule: self.rule,
|
||||||
|
childs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
81
src/main.rs
81
src/main.rs
|
@ -1,7 +1,7 @@
|
||||||
mod double_enum;
|
mod double_enum;
|
||||||
mod ll_grammar;
|
mod ll_grammar;
|
||||||
mod scanner;
|
mod scanner;
|
||||||
use ll_grammar::{LLGrammar, Sentential};
|
use ll_grammar::{LLGrammar, Sentential, Skippable};
|
||||||
use regex::{Match, Regex};
|
use regex::{Match, Regex};
|
||||||
use scanner::Scanner;
|
use scanner::Scanner;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -29,6 +29,7 @@ double_enum!(
|
||||||
Dot,
|
Dot,
|
||||||
Ident(String),
|
Ident(String),
|
||||||
Int(i64),
|
Int(i64),
|
||||||
|
Str(String),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -98,6 +99,9 @@ scanner!(
|
||||||
r"^[0-9]+.[0-9]*" : |_, m: Match<'_>| {
|
r"^[0-9]+.[0-9]*" : |_, m: Match<'_>| {
|
||||||
m.as_str().parse::<_>().ok().map(|f| Float(f))
|
m.as_str().parse::<_>().ok().map(|f| Float(f))
|
||||||
}
|
}
|
||||||
|
r#"^"(([^"\\]|(\\[a-z\\"]))*)""# : |capture: regex::Captures<'_>, _| {
|
||||||
|
capture.get(1).map(|m| Str(m.as_str().to_string()))
|
||||||
|
}
|
||||||
r"^[0-9]+" : |_, m: Match<'_>| {
|
r"^[0-9]+" : |_, m: Match<'_>| {
|
||||||
m.as_str().parse::<_>().ok().map(|i| Int(i))
|
m.as_str().parse::<_>().ok().map(|i| Int(i))
|
||||||
}
|
}
|
||||||
|
@ -109,12 +113,25 @@ enum NoneTerminals {
|
||||||
L, // Line of code
|
L, // Line of code
|
||||||
Li, // line extended for assignments
|
Li, // line extended for assignments
|
||||||
IF, // if helper
|
IF, // if helper
|
||||||
|
Sem, // optional semicolon
|
||||||
E, // Expression
|
E, // Expression
|
||||||
Ei, // Expression extended additive
|
Ei, // Expression extended additive
|
||||||
T, // Term, only containing Factors
|
T, // math term
|
||||||
Ti, // Term extend multiplicative
|
Ti, // meth term extended
|
||||||
|
S, // Summand, only containing Factors
|
||||||
|
Si, // Summand extend multiplicative
|
||||||
F, // Factor
|
F, // Factor
|
||||||
FI, // Factor extended with complex types and operators
|
Fi, // Factor extended with complex types and operators
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Skippable for NoneTerminals {
|
||||||
|
fn skippable(&self) -> bool {
|
||||||
|
use NoneTerminals::*;
|
||||||
|
match self {
|
||||||
|
P | Li | Ei | Si | Ti | Fi | IF | Sem => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<NoneTerminals> for Sentential<T, NoneTerminals> {
|
impl<T> From<NoneTerminals> for Sentential<T, NoneTerminals> {
|
||||||
|
@ -134,38 +151,50 @@ fn grammer() -> LLGrammar<NoneTerminals, BareTokens> {
|
||||||
use NoneTerminals::*;
|
use NoneTerminals::*;
|
||||||
ll_grammar![
|
ll_grammar![
|
||||||
start: P;
|
start: P;
|
||||||
P -> L,Semicolon,P;
|
P -> L,P;
|
||||||
P -> ;
|
P -> ;
|
||||||
L -> While,E,LQBrace,P,RQBrace;
|
L -> While,E,LQBrace,P,RQBrace,Sem;
|
||||||
L -> If,E,LQBrace,P,RQBrace,IF;
|
L -> If,E,LQBrace,P,RQBrace,IF;
|
||||||
IF -> ;
|
IF -> Sem;
|
||||||
IF -> Else,LQBrace,P,RQBrace;
|
IF -> Else,LQBrace,P,RQBrace,Sem;
|
||||||
L -> Ident,FI,Li;
|
Sem -> ;
|
||||||
Li -> Assign,E;
|
Sem -> Semicolon;
|
||||||
Li -> ;
|
L -> Ident,Fi,Li;
|
||||||
|
Li -> Assign,E,Semicolon;
|
||||||
|
Li -> Semicolon;
|
||||||
|
|
||||||
E -> T,Ei;
|
E -> T,Ei;
|
||||||
Ei -> Eq,T,Ei;
|
Ei -> Eq,T,Ei;
|
||||||
Ei -> Neq,T,Ei;
|
Ei -> Neq,T,Ei;
|
||||||
Ei -> Add,T,Ei;
|
|
||||||
Ei -> Sub,T,Ei;
|
|
||||||
Ei -> ;
|
Ei -> ;
|
||||||
T -> F,Ti;
|
|
||||||
Ti -> Mul,F,Ti;
|
T -> S,Ti;
|
||||||
Ti -> Div,F,Ti;
|
Ti -> Add,S,Ti;
|
||||||
|
Ti -> Sub,S,Ti;
|
||||||
Ti -> ;
|
Ti -> ;
|
||||||
|
|
||||||
|
S -> F,Si;
|
||||||
|
Si -> Mul,F,Si;
|
||||||
|
Si -> Div,F,Si;
|
||||||
|
Si -> ;
|
||||||
|
|
||||||
F -> LBrace, E, RBrace;
|
F -> LBrace, E, RBrace;
|
||||||
F -> Int;
|
F -> Int;
|
||||||
F -> Float;
|
F -> Float;
|
||||||
F -> Ident,FI;
|
F -> Str;
|
||||||
FI -> ;
|
F -> Ident,Fi;
|
||||||
FI -> LBrace,E,RBrace;
|
|
||||||
FI -> Dot, FI;
|
Fi -> ;
|
||||||
FI -> LSBrace,E,RSBrace;
|
Fi -> LBrace,E,RBrace;
|
||||||
|
Fi -> Dot, Fi;
|
||||||
|
Fi -> LSBrace,E,RSBrace;
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let code = String::from("a = 4; while a != 5 { a = a+1; }; if a == 5 { a = 4; } else {a = 5;};");
|
let code = String::from(
|
||||||
|
"a = 4; while a != 5 { a = (a+1) * 4; }; if a == 5 { a = \"abs123\"; } else {a = 5;}",
|
||||||
|
);
|
||||||
let mut m = Scanner::<Tokens>::new(code).with_skipping(Tokens::WhiteSpace);
|
let mut m = Scanner::<Tokens>::new(code).with_skipping(Tokens::WhiteSpace);
|
||||||
|
|
||||||
let mut grammar = grammer();
|
let mut grammar = grammer();
|
||||||
|
@ -176,5 +205,11 @@ fn main() {
|
||||||
println!("conflict: {conflict}");
|
println!("conflict: {conflict}");
|
||||||
println!("prase table: {:?}", grammar.parse_table);
|
println!("prase table: {:?}", grammar.parse_table);
|
||||||
println!("parse\n\n");
|
println!("parse\n\n");
|
||||||
println!("parsed: {:?}", grammar.parser(&mut m.iter_mut()).parse())
|
println!(
|
||||||
|
"parsed: {:?}",
|
||||||
|
grammar
|
||||||
|
.parser(&mut m.iter_mut())
|
||||||
|
.parse()
|
||||||
|
.map(|tree| tree.clean())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue