More statement types

This commit is contained in:
2023-07-08 19:09:32 -05:00
parent 10e6aa7f11
commit 927600c7bc
3 changed files with 182 additions and 30 deletions
+33 -10
View File
@@ -54,12 +54,12 @@ pub struct Argname {
pub typename: Option<String>,
}
#[derive(Eq, PartialEq, Clone, Debug)]
#[derive(PartialEq, Clone, Debug)]
pub struct Block {
pub statements: Vec<Statement>,
}
#[derive(Eq, PartialEq, Clone, Debug)]
#[derive(PartialEq, Clone, Debug)]
pub enum Statement {
Return(Return),
Assignment(Assignment),
@@ -70,17 +70,40 @@ pub enum Statement {
RepeatLoop(RepeatLoop),
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Return {}
#[derive(PartialEq, Clone, Debug)]
pub struct Return(pub Option<Node>);
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Assignment {}
#[derive(PartialEq, Clone, Debug)]
pub struct Assignment {
pub lvalue: Lvalue,
pub rvalue: Rvalue,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Call {}
#[derive(PartialEq, Clone, Debug)]
pub struct Call {
pub name: String,
pub args: Vec<Rvalue>,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct VarDecl {}
#[derive(PartialEq, Clone, Debug)]
pub enum Lvalue {
ArrayRef(ArrayRef),
Name(String),
}
#[derive(PartialEq, Clone, Debug)]
pub enum Rvalue {
Expr(Node),
String(String),
}
#[derive(PartialEq, Clone, Debug)]
pub struct VarDecl {
pub name: String,
pub typename: Option<String>,
pub size: Option<i32>,
pub initial: Option<Node>,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Conditional {}
+2 -3
View File
@@ -36,8 +36,7 @@ val = { // These are what get evaluated and left on the stack:
address = { "&" ~ name } // The address for a name
arrayref = { name ~ subscript } // Subscripting is only literal IDs. Anything else can be pointer arithmetic
call = { name ~ arglist } // Call syntax is only literal IDs. Calling things dynamically is done with a builtin; CALL(foo[3], 1, 2, 3)
arg = { expr | string }
arglist = { "(" ~ (arg ~ ("," ~ arg)*)? ~ ")" }
arglist = { "(" ~ (rvalue ~ ("," ~ rvalue)*)? ~ ")" }
subscript = { "[" ~ expr ~ "]" }
statement = { ((return_stmt | assignment | call | var_decl) ~ ";") | conditional | while_loop | repeat_loop }
@@ -57,7 +56,7 @@ argname = { name ~ typename? }
declaration = { function | global | struct_decl | const_decl }
program = { (COMMENT | WHITESPACE)? ~ declaration* ~ EOI }
return_stmt = { "return" ~ expr }
return_stmt = { "return" ~ expr? }
conditional = { "if" ~ "(" ~ expr ~ ")" ~ block ~ ("else" ~ block)? }
while_loop = { "while" ~ "(" ~ expr ~ ")" ~ block }
repeat_loop = { "repeat" ~ "(" ~ expr ~ ")" ~ name ~ block }
+147 -17
View File
@@ -1,4 +1,4 @@
use pest::{Parser, RuleType};
use pest::Parser;
mod inner {
#[derive(Parser)]
@@ -133,7 +133,7 @@ impl AstNode for Declaration {
Rule::global => Self::Global(Global::from_pair(pair)),
Rule::struct_decl => Self::Struct(Struct::from_pair(pair)),
Rule::const_decl => Self::Const(Const::from_pair(pair)),
_ => todo!(),
_ => unreachable!(),
}
}
}
@@ -169,12 +169,12 @@ impl AstNode for Global {
fn from_pair(pair: Pair) -> Self {
let mut inner = pair.into_inner().peekable();
let name = String::from(inner.next().unwrap().as_str());
let varinfo = Varinfo::read_or_default(inner);
let Varinfo { typename, size } = Varinfo::read_or_default(inner);
Global {
name,
typename: varinfo.typename,
size: varinfo.size,
typename,
size,
}
}
}
@@ -197,12 +197,12 @@ impl AstNode for Member {
fn from_pair(pair: Pair<'_>) -> Self {
let mut inner = pair.into_inner().peekable();
let name = String::from(inner.next().unwrap().as_str());
let varinfo = Varinfo::read_or_default(inner);
let Varinfo { typename, size } = Varinfo::read_or_default(inner);
Member {
name,
typename: varinfo.typename,
size: varinfo.size,
typename,
size,
}
}
}
@@ -218,7 +218,7 @@ impl AstNode for Const {
match value.as_rule() {
Rule::string => Const {
name,
string: Some(String::from(value.into_quoted_string())),
string: Some(value.into_quoted_string()),
value: None,
},
Rule::number => Const {
@@ -282,8 +282,9 @@ impl AstNode for Argname {
///////////////////////////////////////////////////////////////////////////////////////////
impl AstNode for Statement {
const RULE: Rule = Rule::declaration;
const RULE: Rule = Rule::statement;
fn from_pair(pair: Pair) -> Self {
let pair = pair.first();
match pair.as_rule() {
Rule::return_stmt => Self::Return(Return::from_pair(pair)),
Rule::assignment => Self::Assignment(Assignment::from_pair(pair)),
@@ -292,7 +293,7 @@ impl AstNode for Statement {
Rule::conditional => Self::Conditional(Conditional::from_pair(pair)),
Rule::while_loop => Self::WhileLoop(WhileLoop::from_pair(pair)),
Rule::repeat_loop => Self::RepeatLoop(RepeatLoop::from_pair(pair)),
_ => todo!(),
_ => unreachable!(),
}
}
}
@@ -302,7 +303,9 @@ impl AstNode for Statement {
impl AstNode for Return {
const RULE: Rule = Rule::return_stmt;
fn from_pair(pair: Pair) -> Self {
todo!()
pair.into_inner()
.next()
.map_or(Self(None), |expr| Self(Some(Node::from_pair(expr))))
}
}
@@ -311,7 +314,30 @@ impl AstNode for Return {
impl AstNode for Assignment {
const RULE: Rule = Rule::assignment;
fn from_pair(pair: Pair) -> Self {
todo!()
let mut pairs = pair.into_inner();
let lvalue_pair = pairs.next().unwrap().first();
let lvalue = match lvalue_pair.as_rule() {
Rule::arrayref => Lvalue::ArrayRef(ArrayRef::from_pair(lvalue_pair)),
Rule::name => Lvalue::Name(String::from(lvalue_pair.as_str())),
_ => unreachable!(),
};
let rvalue = Rvalue::from_pair(pairs.next().unwrap());
Self { lvalue, rvalue }
}
}
///////////////////////////////////////////////////////////////////////////////////////////
impl AstNode for Rvalue {
const RULE: Rule = Rule::rvalue;
fn from_pair(pair: Pair) -> Self {
let pair = pair.first();
match pair.as_rule() {
Rule::string => Self::String(pair.into_quoted_string()),
Rule::expr => Self::Expr(Node::from_pair(pair)),
_ => unreachable!(),
}
}
}
@@ -320,7 +346,11 @@ impl AstNode for Assignment {
impl AstNode for Call {
const RULE: Rule = Rule::call;
fn from_pair(pair: Pair) -> Self {
todo!()
let mut inner = pair.into_inner();
let name = String::from(inner.next().unwrap().as_str());
let arg_pairs = inner.next().unwrap().into_inner();
let args: Vec<Rvalue> = arg_pairs.map(Rvalue::from_pair).collect();
Self { name, args }
}
}
@@ -329,7 +359,16 @@ impl AstNode for Call {
impl AstNode for VarDecl {
const RULE: Rule = Rule::var_decl;
fn from_pair(pair: Pair) -> Self {
todo!()
let mut inner = pair.into_inner();
let name = String::from(inner.next().unwrap().as_str());
let Varinfo { typename, size } = Varinfo::from_pair(inner.next().unwrap());
let initial = inner.next().map(Node::from_pair);
Self {
name,
typename,
size,
initial,
}
}
}
@@ -369,7 +408,7 @@ impl AstNode for Node {
Rule::val => Node::from_pair(pair.first()),
Rule::number => Node::Number(pair.into_number()),
Rule::name => Node::Name(String::from(pair.as_str())),
Rule::call => todo!(),
Rule::call => Node::Call(Call::from_pair(pair)),
Rule::arrayref => Node::ArrayRef(ArrayRef::from_pair(pair)),
Rule::address => Node::Address(pair.first_as_string()),
Rule::expr | Rule::term => {
@@ -387,7 +426,6 @@ fn parse_expr(mut cdr: Pairs) -> Vec<(Operator, Node)> {
let mut terms = Vec::new();
while let Some(operator) = cdr.next() {
let rhs = cdr.next().unwrap();
let rhs_r = rhs.as_rule();
let rhs = Node::from_pair(rhs);
let op = Operator::from_pair(operator);
terms.push((op, rhs));
@@ -731,4 +769,96 @@ mod test {
fn parse_addresses() {
assert_eq!(Node::parse("&foo"), Ok(Node::Address("foo".into())));
}
#[test]
fn parse_calls() {
use Node::Number;
let blah = Call {
name: "blah".into(),
args: vec![],
};
// Can Node parse a call?
assert_eq!(Node::parse("blah()"), Ok(Node::Call(blah.clone())));
// Can Statement parse a call?
assert_eq!(Statement::parse("blah();"), Ok(Statement::Call(blah)));
// Calls with args
assert_eq!(
Call::parse("blah(1, 2)"),
Ok(Call {
name: "blah".into(),
args: vec![Rvalue::Expr(Number(1)), Rvalue::Expr(Number(2))]
})
);
// Calls with strings
assert_eq!(
Call::parse("blah(\"foo\", 2)"),
Ok(Call {
name: "blah".into(),
args: vec![Rvalue::String("foo".into()), Rvalue::Expr(Number(2))]
})
);
}
#[test]
fn parse_return() {
assert_eq!(
Statement::parse("return;"),
Ok(Statement::Return(Return(None)))
);
assert_eq!(
Statement::parse("return 17;"),
Ok(Statement::Return(Return(Some(Node::Number(17)))))
);
}
#[test]
fn parse_assignment() {
assert_eq!(
Statement::parse("foo = 7;"),
Ok(Statement::Assignment(Assignment {
lvalue: Lvalue::Name("foo".into()),
rvalue: Rvalue::Expr(Node::Number(7))
}))
);
assert_eq!(
Assignment::parse("foo[45] = 7"),
Ok(Assignment {
lvalue: Lvalue::ArrayRef(ArrayRef {
name: "foo".into(),
subscript: Node::Number(45).into(),
}),
rvalue: Rvalue::Expr(Node::Number(7))
})
);
}
#[test]
fn parse_var_decl() {
assert_eq!(
Statement::parse("var blah;"),
Ok(Statement::VarDecl(VarDecl {
name: "blah".into(),
typename: None,
size: None,
initial: None,
}))
);
assert_eq!(
VarDecl::parse("var blah:Foo[7] = 35"),
Ok(VarDecl {
name: "blah".into(),
typename: Some("Foo".into()),
size: Some(7),
initial: Some(Node::Number(35)),
})
);
}
}