More statement types
This commit is contained in:
+33
-10
@@ -54,12 +54,12 @@ pub struct Argname {
|
|||||||
pub typename: Option<String>,
|
pub typename: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
pub statements: Vec<Statement>,
|
pub statements: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Return(Return),
|
Return(Return),
|
||||||
Assignment(Assignment),
|
Assignment(Assignment),
|
||||||
@@ -70,17 +70,40 @@ pub enum Statement {
|
|||||||
RepeatLoop(RepeatLoop),
|
RepeatLoop(RepeatLoop),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub struct Return {}
|
pub struct Return(pub Option<Node>);
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub struct Assignment {}
|
pub struct Assignment {
|
||||||
|
pub lvalue: Lvalue,
|
||||||
|
pub rvalue: Rvalue,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub struct Call {}
|
pub struct Call {
|
||||||
|
pub name: String,
|
||||||
|
pub args: Vec<Rvalue>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub struct VarDecl {}
|
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)]
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct Conditional {}
|
pub struct Conditional {}
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ val = { // These are what get evaluated and left on the stack:
|
|||||||
address = { "&" ~ name } // The address for a name
|
address = { "&" ~ name } // The address for a name
|
||||||
arrayref = { name ~ subscript } // Subscripting is only literal IDs. Anything else can be pointer arithmetic
|
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)
|
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 = { "(" ~ (rvalue ~ ("," ~ rvalue)*)? ~ ")" }
|
||||||
arglist = { "(" ~ (arg ~ ("," ~ arg)*)? ~ ")" }
|
|
||||||
subscript = { "[" ~ expr ~ "]" }
|
subscript = { "[" ~ expr ~ "]" }
|
||||||
|
|
||||||
statement = { ((return_stmt | assignment | call | var_decl) ~ ";") | conditional | while_loop | repeat_loop }
|
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 }
|
declaration = { function | global | struct_decl | const_decl }
|
||||||
program = { (COMMENT | WHITESPACE)? ~ declaration* ~ EOI }
|
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 }
|
||||||
|
|||||||
+147
-17
@@ -1,4 +1,4 @@
|
|||||||
use pest::{Parser, RuleType};
|
use pest::Parser;
|
||||||
|
|
||||||
mod inner {
|
mod inner {
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
@@ -133,7 +133,7 @@ impl AstNode for Declaration {
|
|||||||
Rule::global => Self::Global(Global::from_pair(pair)),
|
Rule::global => Self::Global(Global::from_pair(pair)),
|
||||||
Rule::struct_decl => Self::Struct(Struct::from_pair(pair)),
|
Rule::struct_decl => Self::Struct(Struct::from_pair(pair)),
|
||||||
Rule::const_decl => Self::Const(Const::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 {
|
fn from_pair(pair: Pair) -> Self {
|
||||||
let mut inner = pair.into_inner().peekable();
|
let mut inner = pair.into_inner().peekable();
|
||||||
let name = String::from(inner.next().unwrap().as_str());
|
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 {
|
Global {
|
||||||
name,
|
name,
|
||||||
typename: varinfo.typename,
|
typename,
|
||||||
size: varinfo.size,
|
size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,12 +197,12 @@ impl AstNode for Member {
|
|||||||
fn from_pair(pair: Pair<'_>) -> Self {
|
fn from_pair(pair: Pair<'_>) -> Self {
|
||||||
let mut inner = pair.into_inner().peekable();
|
let mut inner = pair.into_inner().peekable();
|
||||||
let name = String::from(inner.next().unwrap().as_str());
|
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 {
|
Member {
|
||||||
name,
|
name,
|
||||||
typename: varinfo.typename,
|
typename,
|
||||||
size: varinfo.size,
|
size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ impl AstNode for Const {
|
|||||||
match value.as_rule() {
|
match value.as_rule() {
|
||||||
Rule::string => Const {
|
Rule::string => Const {
|
||||||
name,
|
name,
|
||||||
string: Some(String::from(value.into_quoted_string())),
|
string: Some(value.into_quoted_string()),
|
||||||
value: None,
|
value: None,
|
||||||
},
|
},
|
||||||
Rule::number => Const {
|
Rule::number => Const {
|
||||||
@@ -282,8 +282,9 @@ impl AstNode for Argname {
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl AstNode for Statement {
|
impl AstNode for Statement {
|
||||||
const RULE: Rule = Rule::declaration;
|
const RULE: Rule = Rule::statement;
|
||||||
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::return_stmt => Self::Return(Return::from_pair(pair)),
|
Rule::return_stmt => Self::Return(Return::from_pair(pair)),
|
||||||
Rule::assignment => Self::Assignment(Assignment::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::conditional => Self::Conditional(Conditional::from_pair(pair)),
|
||||||
Rule::while_loop => Self::WhileLoop(WhileLoop::from_pair(pair)),
|
Rule::while_loop => Self::WhileLoop(WhileLoop::from_pair(pair)),
|
||||||
Rule::repeat_loop => Self::RepeatLoop(RepeatLoop::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 {
|
impl AstNode for Return {
|
||||||
const RULE: Rule = Rule::return_stmt;
|
const RULE: Rule = Rule::return_stmt;
|
||||||
fn from_pair(pair: Pair) -> Self {
|
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 {
|
impl AstNode for Assignment {
|
||||||
const RULE: Rule = Rule::assignment;
|
const RULE: Rule = Rule::assignment;
|
||||||
fn from_pair(pair: Pair) -> Self {
|
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 {
|
impl AstNode for Call {
|
||||||
const RULE: Rule = Rule::call;
|
const RULE: Rule = Rule::call;
|
||||||
fn from_pair(pair: Pair) -> Self {
|
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 {
|
impl AstNode for VarDecl {
|
||||||
const RULE: Rule = Rule::var_decl;
|
const RULE: Rule = Rule::var_decl;
|
||||||
fn from_pair(pair: Pair) -> Self {
|
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::val => Node::from_pair(pair.first()),
|
||||||
Rule::number => Node::Number(pair.into_number()),
|
Rule::number => Node::Number(pair.into_number()),
|
||||||
Rule::name => Node::Name(String::from(pair.as_str())),
|
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::arrayref => Node::ArrayRef(ArrayRef::from_pair(pair)),
|
||||||
Rule::address => Node::Address(pair.first_as_string()),
|
Rule::address => Node::Address(pair.first_as_string()),
|
||||||
Rule::expr | Rule::term => {
|
Rule::expr | Rule::term => {
|
||||||
@@ -387,7 +426,6 @@ fn parse_expr(mut cdr: Pairs) -> Vec<(Operator, Node)> {
|
|||||||
let mut terms = Vec::new();
|
let mut terms = Vec::new();
|
||||||
while let Some(operator) = cdr.next() {
|
while let Some(operator) = cdr.next() {
|
||||||
let rhs = cdr.next().unwrap();
|
let rhs = cdr.next().unwrap();
|
||||||
let rhs_r = rhs.as_rule();
|
|
||||||
let rhs = Node::from_pair(rhs);
|
let rhs = Node::from_pair(rhs);
|
||||||
let op = Operator::from_pair(operator);
|
let op = Operator::from_pair(operator);
|
||||||
terms.push((op, rhs));
|
terms.push((op, rhs));
|
||||||
@@ -731,4 +769,96 @@ mod test {
|
|||||||
fn parse_addresses() {
|
fn parse_addresses() {
|
||||||
assert_eq!(Node::parse("&foo"), Ok(Node::Address("foo".into())));
|
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)),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user