Add block AST
This commit is contained in:
parent
76ce91b6ee
commit
4b1d62b06a
6 changed files with 109 additions and 4 deletions
|
@ -25,7 +25,7 @@ fn main() {
|
||||||
let result = huia_parser::parse_file(&source_file);
|
let result = huia_parser::parse_file(&source_file);
|
||||||
|
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
println!("{:?}", result.unwrap());
|
println!("{:#?}", result.unwrap());
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
} else {
|
} else {
|
||||||
println!("{}", result.err().unwrap());
|
println!("{}", result.err().unwrap());
|
||||||
|
|
|
@ -4,8 +4,8 @@ use pest::Span;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Atom<'a> {
|
pub struct Atom<'a> {
|
||||||
span: Span<'a>,
|
pub span: Span<'a>,
|
||||||
name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<Pair<'a, Rule>> for Atom<'a> {
|
impl<'a> From<Pair<'a, Rule>> for Atom<'a> {
|
||||||
|
|
62
parser/src/ast/block.rs
Normal file
62
parser/src/ast/block.rs
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,7 +59,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn def_static() {
|
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);
|
let def = Define::from(result);
|
||||||
if let DefineWhat::Function(inner) = def.inner {
|
if let DefineWhat::Function(inner) = def.inner {
|
||||||
assert_eq!(inner.name.name, "marty");
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod argument_name;
|
mod argument_name;
|
||||||
mod array;
|
mod array;
|
||||||
mod atom;
|
mod atom;
|
||||||
|
mod block;
|
||||||
mod boolean;
|
mod boolean;
|
||||||
mod braced;
|
mod braced;
|
||||||
mod call;
|
mod call;
|
||||||
|
@ -22,6 +23,7 @@ mod variable;
|
||||||
pub use self::{
|
pub use self::{
|
||||||
array::Array,
|
array::Array,
|
||||||
atom::Atom,
|
atom::Atom,
|
||||||
|
block::Block,
|
||||||
boolean::False,
|
boolean::False,
|
||||||
boolean::True,
|
boolean::True,
|
||||||
braced::Braced,
|
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_true => Ok(Node::from(True::from(pair))),
|
||||||
Rule::boolean_false => Ok(Node::from(False::from(pair))),
|
Rule::boolean_false => Ok(Node::from(False::from(pair))),
|
||||||
Rule::braced => Ok(Node::from(Braced::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::call => Ok(Node::from(Call::from(pair))),
|
||||||
Rule::constructor => Ok(Node::from(Constructor::from(pair))),
|
Rule::constructor => Ok(Node::from(Constructor::from(pair))),
|
||||||
Rule::def => Ok(Node::from(Define::from(pair))),
|
Rule::def => Ok(Node::from(Define::from(pair))),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use ast::{
|
use ast::{
|
||||||
array::Array,
|
array::Array,
|
||||||
atom::Atom,
|
atom::Atom,
|
||||||
|
block::Block,
|
||||||
boolean::{False, True},
|
boolean::{False, True},
|
||||||
braced::Braced,
|
braced::Braced,
|
||||||
call::Call,
|
call::Call,
|
||||||
|
@ -21,6 +22,7 @@ pub enum Node<'a> {
|
||||||
Array(Array<'a>),
|
Array(Array<'a>),
|
||||||
Atom(Atom<'a>),
|
Atom(Atom<'a>),
|
||||||
Braced(Braced<'a>),
|
Braced(Braced<'a>),
|
||||||
|
Block(Block<'a>),
|
||||||
Call(Call<'a>),
|
Call(Call<'a>),
|
||||||
Constructor(Constructor<'a>),
|
Constructor(Constructor<'a>),
|
||||||
Define(Define<'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>> {
|
pub fn call(&self) -> Option<&Call<'a>> {
|
||||||
match self {
|
match self {
|
||||||
Node::Call(call) => Some(&call),
|
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> {
|
impl<'a> From<Call<'a>> for Node<'a> {
|
||||||
fn from(inner: Call<'a>) -> Self {
|
fn from(inner: Call<'a>) -> Self {
|
||||||
Node::Call(inner)
|
Node::Call(inner)
|
||||||
|
|
Reference in a new issue