Completed the parser
This commit is contained in:
+26
-13
@@ -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)]
|
||||
|
||||
@@ -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
@@ -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(),
|
||||
]))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user