Completed the parser

This commit is contained in:
2023-07-08 20:54:23 -05:00
parent 927600c7bc
commit bc3a1ad88f
3 changed files with 177 additions and 40 deletions
+26 -13
View File
@@ -1,4 +1,7 @@
#[derive(Eq, PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
pub struct Program(pub Vec<Declaration>);
#[derive(PartialEq, Clone, Debug)]
pub enum Declaration { pub enum Declaration {
Function(Function), Function(Function),
Global(Global), Global(Global),
@@ -39,13 +42,17 @@ pub struct Const {
pub string: Option<String>, pub string: Option<String>,
} }
#[derive(Eq, PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
pub struct Block(pub Vec<Statement>);
#[derive(PartialEq, Clone, Debug)]
pub struct Function { pub struct Function {
pub name: String, pub name: String,
pub org: Option<i32>, pub org: Option<i32>,
pub typename: Option<String>, pub typename: Option<String>,
pub inline: bool, pub inline: bool,
pub args: Vec<Argname>, pub args: Vec<Argname>,
pub body: Block,
} }
#[derive(Eq, PartialEq, Clone, Debug)] #[derive(Eq, PartialEq, Clone, Debug)]
@@ -54,11 +61,6 @@ pub struct Argname {
pub typename: Option<String>, pub typename: Option<String>,
} }
#[derive(PartialEq, Clone, Debug)]
pub struct Block {
pub statements: Vec<Statement>,
}
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
pub enum Statement { pub enum Statement {
Return(Return), Return(Return),
@@ -105,14 +107,25 @@ pub struct VarDecl {
pub initial: Option<Node>, pub initial: Option<Node>,
} }
#[derive(Eq, PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
pub struct Conditional {} pub struct Conditional {
pub condition: Node,
pub body: Block,
pub alternative: Option<Block>,
}
#[derive(Eq, PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
pub struct WhileLoop {} pub struct WhileLoop {
pub condition: Node,
pub body: Block,
}
#[derive(Eq, PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
pub struct RepeatLoop {} pub struct RepeatLoop {
pub count: Node,
pub name: Option<String>,
pub body: Block,
}
/// One of the five arithmetical operators /// One of the five arithmetical operators
#[derive(Debug, PartialEq, Copy, Clone)] #[derive(Debug, PartialEq, Copy, Clone)]
+1 -1
View File
@@ -59,7 +59,7 @@ program = { (COMMENT | WHITESPACE)? ~ declaration* ~ EOI }
return_stmt = { "return" ~ expr? } return_stmt = { "return" ~ expr? }
conditional = { "if" ~ "(" ~ expr ~ ")" ~ block ~ ("else" ~ block)? } conditional = { "if" ~ "(" ~ expr ~ ")" ~ block ~ ("else" ~ block)? }
while_loop = { "while" ~ "(" ~ expr ~ ")" ~ block } while_loop = { "while" ~ "(" ~ expr ~ ")" ~ block }
repeat_loop = { "repeat" ~ "(" ~ expr ~ ")" ~ name ~ block } repeat_loop = { "repeat" ~ "(" ~ expr ~ ")" ~ name? ~ block }
var_decl = { "var" ~ name ~ varinfo ~ ("=" ~ expr)? } var_decl = { "var" ~ name ~ varinfo ~ ("=" ~ expr)? }
global = { "global" ~ name ~ varinfo ~ ";" } global = { "global" ~ name ~ varinfo ~ ";" }
typename = { ":" ~ name } typename = { ":" ~ name }
+150 -26
View File
@@ -128,6 +128,7 @@ impl<T: AstNode> Parseable for T {
impl AstNode for Declaration { impl AstNode for Declaration {
const RULE: Rule = Rule::declaration; const RULE: Rule = Rule::declaration;
fn from_pair(pair: Pair) -> Self { fn from_pair(pair: Pair) -> Self {
let pair = pair.first();
match pair.as_rule() { match pair.as_rule() {
Rule::function => Self::Function(Function::from_pair(pair)), Rule::function => Self::Function(Function::from_pair(pair)),
Rule::global => Self::Global(Global::from_pair(pair)), Rule::global => Self::Global(Global::from_pair(pair)),
@@ -259,12 +260,15 @@ impl AstNode for Function {
.map(Argname::from_pair) .map(Argname::from_pair)
.collect(); .collect();
let body = Block::from_pair(inner.next().unwrap());
Self { Self {
name, name,
org, org,
typename, typename,
inline, inline,
args, args,
body,
} }
} }
} }
@@ -374,10 +378,28 @@ impl AstNode for VarDecl {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
impl AstNode for Block {
const RULE: Rule = Rule::block;
fn from_pair(pair: Pair) -> Self {
Self(pair.into_inner().map(Statement::from_pair).collect())
}
}
///////////////////////////////////////////////////////////////////////////////////////////
impl AstNode for Conditional { impl AstNode for Conditional {
const RULE: Rule = Rule::conditional; const RULE: Rule = Rule::conditional;
fn from_pair(pair: Pair) -> Self { fn from_pair(pair: Pair) -> Self {
todo!() let mut inner = pair.into_inner();
let condition = Node::from_pair(inner.next().unwrap());
let body = Block::from_pair(inner.next().unwrap());
let alternative = inner.next().map(Block::from_pair);
Self {
condition,
body,
alternative,
}
} }
} }
@@ -386,7 +408,11 @@ impl AstNode for Conditional {
impl AstNode for WhileLoop { impl AstNode for WhileLoop {
const RULE: Rule = Rule::while_loop; const RULE: Rule = Rule::while_loop;
fn from_pair(pair: Pair) -> Self { fn from_pair(pair: Pair) -> Self {
todo!() let mut inner = pair.into_inner();
Self {
condition: Node::from_pair(inner.next().unwrap()),
body: Block::from_pair(inner.next().unwrap()),
}
} }
} }
@@ -395,7 +421,13 @@ impl AstNode for WhileLoop {
impl AstNode for RepeatLoop { impl AstNode for RepeatLoop {
const RULE: Rule = Rule::repeat_loop; const RULE: Rule = Rule::repeat_loop;
fn from_pair(pair: Pair) -> Self { fn from_pair(pair: Pair) -> Self {
todo!() let mut inner = pair.into_inner().peekable();
let count = Node::from_pair(inner.next().unwrap());
let name = inner
.next_if_rule(Rule::name)
.map(|p| String::from(p.as_str()));
let body = Block::from_pair(inner.next().unwrap());
Self { count, name, body }
} }
} }
@@ -482,6 +514,22 @@ impl AstNode for ArrayRef {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
impl AstNode for Program {
const RULE: Rule = Rule::program;
fn from_pair(pair: Pair) -> Self {
// Program captures EOI, to make sure that it's parsing the entire stream. We need to
// ignore that though:
Self(
pair.into_inner()
.filter(|p| p.as_rule() != Rule::EOI)
.map(Declaration::from_pair)
.collect(),
)
}
}
///////////////////////////////////////////////////////////////////////////////////////////
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@@ -614,6 +662,7 @@ mod test {
org: None, org: None,
typename: None, typename: None,
args: vec![], args: vec![],
body: Block(vec![]),
}) })
); );
assert_eq!( assert_eq!(
@@ -633,6 +682,7 @@ mod test {
typename: None typename: None
} }
], ],
body: Block(vec![]),
}) })
); );
assert_eq!( assert_eq!(
@@ -652,34 +702,27 @@ mod test {
typename: None typename: None
} }
], ],
body: Block(vec![]),
}) })
); );
let func = Function {
name: "foo".into(),
inline: true,
org: Some(0x400),
typename: None,
args: vec![Argname {
name: "a".into(),
typename: None,
}],
body: Block(vec![]),
};
assert_eq!( assert_eq!(
Function::parse("fn foo<inline, org=0x400>(a) {}"), Function::parse("fn foo<inline, org=0x400>(a) {}"),
Ok(Function { Ok(func.clone())
name: "foo".into(),
inline: true,
org: Some(0x400),
typename: None,
args: vec![Argname {
name: "a".into(),
typename: None
},],
})
);
assert_eq!(
Function::parse("fn foo<org=0x400, inline>(a) {}"),
Ok(Function {
name: "foo".into(),
inline: true,
org: Some(0x400),
typename: None,
args: vec![Argname {
name: "a".into(),
typename: None
},],
})
); );
assert_eq!(Function::parse("fn foo<org=0x400, inline>(a) {}"), Ok(func));
} }
#[test] #[test]
@@ -861,4 +904,85 @@ mod test {
}) })
); );
} }
#[test]
fn parse_block() {
assert_eq!(
Block::parse("{ foo(); bar(); }"),
Ok(Block(vec![
Statement::Call(Call {
name: "foo".into(),
args: vec![]
}),
Statement::Call(Call {
name: "bar".into(),
args: vec![]
}),
]))
);
}
#[test]
fn parse_conditional() {
assert_eq!(
Statement::parse("if(cond) { foo(); }"),
Ok(Statement::Conditional(Conditional {
condition: Node::parse("cond").unwrap(),
body: Block::parse("{ foo(); }").unwrap(),
alternative: None
}))
);
assert_eq!(
Statement::parse("if(cond) { foo(); } else { bar(); }"),
Ok(Statement::Conditional(Conditional {
condition: Node::parse("cond").unwrap(),
body: Block::parse("{ foo(); }").unwrap(),
alternative: Some(Block::parse("{ bar(); }").unwrap()),
}))
);
}
#[test]
fn parse_while_loops() {
assert_eq!(
Statement::parse("while(cond) { foo(); }"),
Ok(Statement::WhileLoop(WhileLoop {
condition: Node::parse("cond").unwrap(),
body: Block::parse("{ foo(); }").unwrap(),
}))
);
}
#[test]
fn parse_repeat_loops() {
assert_eq!(
Statement::parse("repeat(10) x { foo(x); }"),
Ok(Statement::RepeatLoop(RepeatLoop {
count: Node::Number(10),
name: Some("x".into()),
body: Block::parse("{ foo(x); }").unwrap(),
}))
);
assert_eq!(
Statement::parse("repeat(10) { foo(); }"),
Ok(Statement::RepeatLoop(RepeatLoop {
count: Node::Number(10),
name: None,
body: Block::parse("{ foo(); }").unwrap(),
}))
);
}
#[test]
fn parse_program() {
assert_eq!(
Program::parse("global foo; struct Point { x, y }"),
Ok(Program(vec![
Declaration::parse("global foo;").unwrap(),
Declaration::parse("struct Point { x, y }").unwrap(),
]))
)
}
} }