Add block AST

This commit is contained in:
James Harton 2018-09-06 19:41:43 +12:00
parent 76ce91b6ee
commit 4b1d62b06a
6 changed files with 109 additions and 4 deletions

View file

@ -25,7 +25,7 @@ fn main() {
let result = huia_parser::parse_file(&source_file);
if result.is_ok() {
println!("{:?}", result.unwrap());
println!("{:#?}", result.unwrap());
process::exit(0);
} else {
println!("{}", result.err().unwrap());

View file

@ -4,8 +4,8 @@ use pest::Span;
#[derive(Debug, Clone)]
pub struct Atom<'a> {
span: Span<'a>,
name: String,
pub span: Span<'a>,
pub name: String,
}
impl<'a> From<Pair<'a, Rule>> for Atom<'a> {

62
parser/src/ast/block.rs Normal file
View file

@ -0,0 +1,62 @@
use ast::{consume, node::Node};
use grammar::Rule;
use pest::iterators::Pair;
use pest::Span;
#[derive(Debug, Clone)]
pub struct Block<'a> {
pub span: Span<'a>,
pub body: Vec<Node<'a>>,
}
impl<'a> From<Pair<'a, Rule>> for Block<'a> {
fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::block);
let span = pair.clone().into_span();
let body = pair.into_inner().map(|p| consume(p)).collect();
Block {
span: span,
body: body,
}
}
}
#[cfg(test)]
mod test {
use super::*;
use grammar::parse_str;
#[test]
fn block_empty() {
let pair = parse_str("-> end", Rule::block_test);
let block = Block::from(pair);
assert!(block.body.is_empty());
}
#[test]
fn block_single() {
let pair = parse_str("-> 123 end", Rule::block_test);
let block = Block::from(pair);
assert_eq!(block.body.len(), 1);
assert_eq!(block.body[0].integer().unwrap().value, 123);
}
#[test]
fn block_multi() {
let pair = parse_str(
"->
:marty
:doc
:einstein
end",
Rule::block_test,
);
let block = Block::from(pair);
assert_eq!(block.body.len(), 3);
assert_eq!(block.body[0].atom().unwrap().name, "marty");
assert_eq!(block.body[1].atom().unwrap().name, "doc");
assert_eq!(block.body[2].atom().unwrap().name, "einstein");
}
}

View file

@ -59,7 +59,7 @@ mod test {
#[test]
fn def_static() {
let result = parse_str("defstatic marty", Rule::def_test);
let result = parse_str("defstatic marty", Rule::file);
let def = Define::from(result);
if let DefineWhat::Function(inner) = def.inner {
assert_eq!(inner.name.name, "marty");
@ -297,4 +297,29 @@ mod test {
}
}
#[test]
fn def_type_with_body() {
let result = parse_str(
"deftype Delorean speed: Integer, as: ->
defstatic <Delorean> new as: ->
Delorean { speed: 0 }
end
end",
Rule::def_test,
);
let def = Define::from(result);
if let DefineWhat::Type(inner) = def.inner {
assert_eq!(inner.name.name, "Delorean");
assert_eq!(inner.fields.len(), 2);
let (ref arg_name, ref arg_value) = inner.fields[0];
assert_eq!(arg_name.name, "speed");
assert_eq!(arg_value.clone().variable().unwrap().name, "Integer");
let (ref arg_name, ref arg_value) = inner.fields[1];
assert_eq!(arg_name.name, "as");
assert_eq!(arg_value.clone().block().unwrap().body.len(), 1);
} else {
panic!("inner is not a type definition");
}
}
}

View file

@ -1,6 +1,7 @@
mod argument_name;
mod array;
mod atom;
mod block;
mod boolean;
mod braced;
mod call;
@ -22,6 +23,7 @@ mod variable;
pub use self::{
array::Array,
atom::Atom,
block::Block,
boolean::False,
boolean::True,
braced::Braced,
@ -56,6 +58,7 @@ pub fn build<'a>(pair: Pair<'a, Rule>) -> Result<Node<'a>, ParseError<'a>> {
Rule::boolean_true => Ok(Node::from(True::from(pair))),
Rule::boolean_false => Ok(Node::from(False::from(pair))),
Rule::braced => Ok(Node::from(Braced::from(pair))),
Rule::block => Ok(Node::from(Block::from(pair))),
Rule::call => Ok(Node::from(Call::from(pair))),
Rule::constructor => Ok(Node::from(Constructor::from(pair))),
Rule::def => Ok(Node::from(Define::from(pair))),

View file

@ -1,6 +1,7 @@
use ast::{
array::Array,
atom::Atom,
block::Block,
boolean::{False, True},
braced::Braced,
call::Call,
@ -21,6 +22,7 @@ pub enum Node<'a> {
Array(Array<'a>),
Atom(Atom<'a>),
Braced(Braced<'a>),
Block(Block<'a>),
Call(Call<'a>),
Constructor(Constructor<'a>),
Define(Define<'a>),
@ -58,6 +60,13 @@ impl<'a> Node<'a> {
}
}
pub fn block(&self) -> Option<&Block<'a>> {
match self {
Node::Block(block) => Some(&block),
_ => None,
}
}
pub fn call(&self) -> Option<&Call<'a>> {
match self {
Node::Call(call) => Some(&call),
@ -168,6 +177,12 @@ impl<'a> From<Braced<'a>> for Node<'a> {
}
}
impl<'a> From<Block<'a>> for Node<'a> {
fn from(inner: Block<'a>) -> Self {
Node::Block(inner)
}
}
impl<'a> From<Call<'a>> for Node<'a> {
fn from(inner: Call<'a>) -> Self {
Node::Call(inner)