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 {
Function(Function),
Global(Global),
@@ -39,13 +42,17 @@ pub struct Const {
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 name: String,
pub org: Option<i32>,
pub typename: Option<String>,
pub inline: bool,
pub args: Vec<Argname>,
pub body: Block,
}
#[derive(Eq, PartialEq, Clone, Debug)]
@@ -54,11 +61,6 @@ pub struct Argname {
pub typename: Option<String>,
}
#[derive(PartialEq, Clone, Debug)]
pub struct Block {
pub statements: Vec<Statement>,
}
#[derive(PartialEq, Clone, Debug)]
pub enum Statement {
Return(Return),
@@ -105,14 +107,25 @@ pub struct VarDecl {
pub initial: Option<Node>,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Conditional {}
#[derive(PartialEq, Clone, Debug)]
pub struct Conditional {
pub condition: Node,
pub body: Block,
pub alternative: Option<Block>,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct WhileLoop {}
#[derive(PartialEq, Clone, Debug)]
pub struct WhileLoop {
pub condition: Node,
pub body: Block,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct RepeatLoop {}
#[derive(PartialEq, Clone, Debug)]
pub struct RepeatLoop {
pub count: Node,
pub name: Option<String>,
pub body: Block,
}
/// One of the five arithmetical operators
#[derive(Debug, PartialEq, Copy, Clone)]
+1 -1
View File
@@ -59,7 +59,7 @@ program = { (COMMENT | WHITESPACE)? ~ declaration* ~ EOI }
return_stmt = { "return" ~ expr? }
conditional = { "if" ~ "(" ~ expr ~ ")" ~ block ~ ("else" ~ block)? }
while_loop = { "while" ~ "(" ~ expr ~ ")" ~ block }
repeat_loop = { "repeat" ~ "(" ~ expr ~ ")" ~ name ~ block }
repeat_loop = { "repeat" ~ "(" ~ expr ~ ")" ~ name? ~ block }
var_decl = { "var" ~ name ~ varinfo ~ ("=" ~ expr)? }
global = { "global" ~ name ~ varinfo ~ ";" }
typename = { ":" ~ name }
+150 -26
View File
@@ -128,6 +128,7 @@ impl<T: AstNode> Parseable for T {
impl AstNode for Declaration {
const RULE: Rule = Rule::declaration;
fn from_pair(pair: Pair) -> Self {
let pair = pair.first();
match pair.as_rule() {
Rule::function => Self::Function(Function::from_pair(pair)),
Rule::global => Self::Global(Global::from_pair(pair)),
@@ -259,12 +260,15 @@ impl AstNode for Function {
.map(Argname::from_pair)
.collect();
let body = Block::from_pair(inner.next().unwrap());
Self {
name,
org,
typename,
inline,
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 {
const RULE: Rule = Rule::conditional;
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 {
const RULE: Rule = Rule::while_loop;
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 {
const RULE: Rule = Rule::repeat_loop;
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)]
mod test {
use super::*;
@@ -614,6 +662,7 @@ mod test {
org: None,
typename: None,
args: vec![],
body: Block(vec![]),
})
);
assert_eq!(
@@ -633,6 +682,7 @@ mod test {
typename: None
}
],
body: Block(vec![]),
})
);
assert_eq!(
@@ -652,34 +702,27 @@ mod test {
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!(
Function::parse("fn foo<inline, org=0x400>(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(Function {
name: "foo".into(),
inline: true,
org: Some(0x400),
typename: None,
args: vec![Argname {
name: "a".into(),
typename: None
},],
})
Ok(func.clone())
);
assert_eq!(Function::parse("fn foo<org=0x400, inline>(a) {}"), Ok(func));
}
#[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(),
]))
)
}
}