Merge branch 'master' into lets-invent-a-linter

This commit is contained in:
James Harton 2018-09-15 17:24:09 +12:00
commit e5a2bc1291
30 changed files with 329 additions and 451 deletions

View file

@ -1,11 +1,16 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ArgumentName<'a> { pub struct ArgumentName<'a> {
pub span: Span<'a>, span: Span<'a>,
pub name: String, name: String,
}
impl<'a> Parse<'a> for ArgumentName<'a> {
const RULE: Rule = Rule::argument_keyword;
} }
impl<'a> From<Pair<'a, Rule>> for ArgumentName<'a> { impl<'a> From<Pair<'a, Rule>> for ArgumentName<'a> {
@ -31,13 +36,10 @@ impl<'a> ArgumentName<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn argument_name() { fn argument_name() {
let pair = parse_str("marty_mcfly:", Rule::argument_keyword); let argument_name = ArgumentName::parse("marty_mcfly:").unwrap();
let argument_name = ArgumentName::from(pair); assert_eq!(argument_name.name(), "marty_mcfly");
assert_eq!(argument_name.name, "marty_mcfly");
} }
} }

View file

@ -1,5 +1,6 @@
use ast::expression::Expression; use ast::expression::Expression;
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -9,6 +10,10 @@ pub struct Array<'a> {
values: Vec<Expression<'a>>, values: Vec<Expression<'a>>,
} }
impl<'a> Parse<'a> for Array<'a> {
const RULE: Rule = Rule::array;
}
impl<'a> From<Pair<'a, Rule>> for Array<'a> { impl<'a> From<Pair<'a, Rule>> for Array<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::array); assert_eq!(pair.as_rule(), Rule::array);
@ -32,12 +37,10 @@ impl<'a> Array<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn array_of_ints() { fn array_of_ints() {
let result = parse_str("[1, 2, 3]", Rule::array); let array = Array::parse("[1, 2, 3]").unwrap();
let array = Array::from(result);
let mut value = 0; let mut value = 0;
for expr in array.values() { for expr in array.values() {
value = value + 1; value = value + 1;

View file

@ -1,5 +1,6 @@
use ast::into_span::IntoSpan; use ast::into_span::IntoSpan;
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -9,6 +10,10 @@ pub struct Atom<'a> {
pub name: String, pub name: String,
} }
impl<'a> Parse<'a> for Atom<'a> {
const RULE: Rule = Rule::atom;
}
impl<'a> From<Pair<'a, Rule>> for Atom<'a> { impl<'a> From<Pair<'a, Rule>> for Atom<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
match pair.as_rule() { match pair.as_rule() {
@ -62,12 +67,10 @@ impl<'a> IntoSpan<'a> for Atom<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn atom() { fn atom() {
let pair = parse_str(":marty_mcfly", Rule::atom); let atom = Atom::parse(":marty_mcfly").unwrap();
let atom = Atom::from(pair);
assert_eq!(atom.name(), "marty_mcfly"); assert_eq!(atom.name(), "marty_mcfly");
} }
} }

View file

@ -1,5 +1,6 @@
use ast::{define_function::DefineFunction, expression::Expression}; use ast::{define_function::DefineFunction, expression::Expression};
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -15,6 +16,10 @@ pub enum Inner<'a> {
Expression(Expression<'a>), Expression(Expression<'a>),
} }
impl<'a> Parse<'a> for Block<'a> {
const RULE: Rule = Rule::block;
}
impl<'a> From<Pair<'a, Rule>> for Block<'a> { impl<'a> From<Pair<'a, Rule>> for Block<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::block); assert_eq!(pair.as_rule(), Rule::block);
@ -26,8 +31,7 @@ impl<'a> From<Pair<'a, Rule>> for Block<'a> {
Rule::def_function => Inner::DefineFunction(DefineFunction::from(p)), Rule::def_function => Inner::DefineFunction(DefineFunction::from(p)),
Rule::expression => Inner::Expression(Expression::from(p)), Rule::expression => Inner::Expression(Expression::from(p)),
_ => unreachable!(), _ => unreachable!(),
}) }).collect();
.collect();
Block { Block {
span: span, span: span,
@ -61,19 +65,16 @@ impl<'a> Block<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn block_empty() { fn block_empty() {
let pair = parse_str("-> end", Rule::block_test); let block = Block::parse("-> end").unwrap();
let block = Block::from(pair);
assert!(block.body().is_empty()); assert!(block.body().is_empty());
} }
#[test] #[test]
fn block_single() { fn block_single() {
let pair = parse_str("-> 123 end", Rule::block_test); let block = Block::parse("-> 123 end").unwrap();
let block = Block::from(pair);
assert_eq!(block.body().len(), 1); assert_eq!(block.body().len(), 1);
assert_eq!( assert_eq!(
block.body()[0] block.body()[0]
@ -90,15 +91,13 @@ mod test {
#[test] #[test]
fn block_multi() { fn block_multi() {
let pair = parse_str( let block = Block::parse(
"-> "->
:marty :marty
:doc :doc
:einstein :einstein
end", end",
Rule::block_test, ).unwrap();
);
let block = Block::from(pair);
assert_eq!(block.body().len(), 3); assert_eq!(block.body().len(), 3);
assert_eq!( assert_eq!(
block.body()[0] block.body()[0]
@ -137,8 +136,7 @@ mod test {
#[test] #[test]
fn block_with_function_define() { fn block_with_function_define() {
let pair = parse_str("-> def marty? end", Rule::block); let block = Block::parse("-> def marty? end").unwrap();
let block = Block::from(pair);
assert_eq!(block.body()[0].define_function().unwrap().name(), "marty?"); assert_eq!(block.body()[0].define_function().unwrap().name(), "marty?");
} }
} }

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -8,6 +9,10 @@ pub struct Boolean<'a> {
value: bool, value: bool,
} }
impl<'a> Parse<'a> for Boolean<'a> {
const RULE: Rule = Rule::boolean;
}
impl<'a> From<Pair<'a, Rule>> for Boolean<'a> { impl<'a> From<Pair<'a, Rule>> for Boolean<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::boolean); assert_eq!(pair.as_rule(), Rule::boolean);
@ -44,19 +49,16 @@ impl<'a> Boolean<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn boolean_true() { fn boolean_true() {
let pair = parse_str("true", Rule::boolean); let b = Boolean::parse("true").unwrap();
let b = Boolean::from(pair);
assert!(b.value()); assert!(b.value());
} }
#[test] #[test]
fn boolean_false() { fn boolean_false() {
let pair = parse_str("false", Rule::boolean); let b = Boolean::parse("false").unwrap();
let b = Boolean::from(pair);
assert!(!b.value()); assert!(!b.value());
} }

View file

@ -1,6 +1,7 @@
use ast::call::{message::Message, receiver::Receiver}; use ast::call::{message::Message, receiver::Receiver};
use ast::expression::Expression; use ast::expression::Expression;
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -12,6 +13,10 @@ pub struct Call<'a> {
arguments: Vec<Expression<'a>>, arguments: Vec<Expression<'a>>,
} }
impl<'a> Parse<'a> for Call<'a> {
const RULE: Rule = Rule::call;
}
impl<'a> From<Pair<'a, Rule>> for Call<'a> { impl<'a> From<Pair<'a, Rule>> for Call<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::call); assert_eq!(pair.as_rule(), Rule::call);
@ -53,13 +58,10 @@ impl<'a> Call<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::{parse_str, Rule};
#[test] #[test]
fn call_no_arg() { fn call_no_arg() {
let result = parse_str("delorean.accelerate()", Rule::call); let call = Call::parse("delorean.accelerate()").unwrap();
let call = Call::from(result);
assert_eq!(call.receiver().name(), "delorean"); assert_eq!(call.receiver().name(), "delorean");
assert_eq!(call.message().name(), "accelerate"); assert_eq!(call.message().name(), "accelerate");
assert_eq!(call.arguments().len(), 0); assert_eq!(call.arguments().len(), 0);
@ -67,10 +69,8 @@ mod test {
#[test] #[test]
fn call_with_arg() { fn call_with_arg() {
let result = parse_str("delorean.accelerate(88)", Rule::call); let call = Call::parse("delorean.accelerate(88)").unwrap();
let call = Call::from(result);
let ref arg = call.arguments[0]; let ref arg = call.arguments[0];
assert_eq!(call.receiver().name(), "delorean"); assert_eq!(call.receiver().name(), "delorean");
assert_eq!(call.message().name(), "accelerate"); assert_eq!(call.message().name(), "accelerate");
assert_eq!(arg.literal().unwrap().integer().unwrap().value(), 88); assert_eq!(arg.literal().unwrap().integer().unwrap().value(), 88);

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -8,6 +9,10 @@ pub struct Message<'a> {
name: String, name: String,
} }
impl<'a> Parse<'a> for Message<'a> {
const RULE: Rule = Rule::call_message;
}
impl<'a> From<Pair<'a, Rule>> for Message<'a> { impl<'a> From<Pair<'a, Rule>> for Message<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::call_message); assert_eq!(pair.as_rule(), Rule::call_message);
@ -31,12 +36,10 @@ impl<'a> Message<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::{parse_str, Rule};
#[test] #[test]
fn message() { fn message() {
let result = parse_str("marty_mcfly", Rule::call_message); let node = Message::parse("marty_mcfly").unwrap();
let node = Message::from(result);
assert_eq!(node.name(), "marty_mcfly"); assert_eq!(node.name(), "marty_mcfly");
} }
} }

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -8,6 +9,10 @@ pub struct Receiver<'a> {
name: String, name: String,
} }
impl<'a> Parse<'a> for Receiver<'a> {
const RULE: Rule = Rule::call_receiver;
}
impl<'a> From<Pair<'a, Rule>> for Receiver<'a> { impl<'a> From<Pair<'a, Rule>> for Receiver<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::call_receiver); assert_eq!(pair.as_rule(), Rule::call_receiver);
@ -31,12 +36,10 @@ impl<'a> Receiver<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::{parse_str, Rule};
#[test] #[test]
fn receiver() { fn receiver() {
let result = parse_str("marty_mcfly", Rule::call_receiver); let node = Receiver::parse("marty_mcfly").unwrap();
let node = Receiver::from(result);
assert_eq!(node.name(), "marty_mcfly"); assert_eq!(node.name(), "marty_mcfly");
} }
} }

View file

@ -1,5 +1,6 @@
use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName}; use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName};
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -10,6 +11,10 @@ pub struct Constructor<'a> {
fields: Vec<(ArgumentName<'a>, Expression<'a>)>, fields: Vec<(ArgumentName<'a>, Expression<'a>)>,
} }
impl<'a> Parse<'a> for Constructor<'a> {
const RULE: Rule = Rule::constructor;
}
impl<'a> From<Pair<'a, Rule>> for Constructor<'a> { impl<'a> From<Pair<'a, Rule>> for Constructor<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::constructor); assert_eq!(pair.as_rule(), Rule::constructor);
@ -48,12 +53,10 @@ impl<'a> Constructor<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn constructor() { fn constructor() {
let pair = parse_str("Delorean { speed: 88 }", Rule::constructor); let constructor = Constructor::parse("Delorean { speed: 88 }").unwrap();
let constructor = Constructor::from(pair);
assert_eq!(constructor.type_name().name(), "Delorean"); assert_eq!(constructor.type_name().name(), "Delorean");
let (ref arg_name, ref arg_value) = constructor.fields()[0]; let (ref arg_name, ref arg_value) = constructor.fields()[0];
assert_eq!(arg_name.name(), "speed"); assert_eq!(arg_name.name(), "speed");

View file

@ -1,5 +1,6 @@
use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName}; use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName};
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::{Pair, Pairs}; use pest::iterators::{Pair, Pairs};
use pest::Span; use pest::Span;
@ -26,6 +27,10 @@ pub struct FunctionName<'a> {
predicate: bool, predicate: bool,
} }
impl<'a> Parse<'a> for DefineFunction<'a> {
const RULE: Rule = Rule::def_function;
}
impl<'a> DefineFunction<'a> { impl<'a> DefineFunction<'a> {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.fn_name.name &self.fn_name.name
@ -125,8 +130,7 @@ fn get_arguments<'a>(pairs: Pairs<'a, Rule>) -> Vec<(ArgumentName<'a>, Expressio
let arg_name = pairs.next().unwrap(); let arg_name = pairs.next().unwrap();
let value = pairs.next().unwrap(); let value = pairs.next().unwrap();
(ArgumentName::from(arg_name), Expression::from(value)) (ArgumentName::from(arg_name), Expression::from(value))
}) }).collect()
.collect()
} }
impl<'a> From<Pair<'a, Rule>> for FunctionType { impl<'a> From<Pair<'a, Rule>> for FunctionType {
@ -143,12 +147,10 @@ impl<'a> From<Pair<'a, Rule>> for FunctionType {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn name_only() { fn name_only() {
let pair = parse_str("def marty", Rule::def_function); let fun = DefineFunction::parse("def marty").unwrap();
let fun = DefineFunction::from(pair);
assert!(fun.is_public()); assert!(fun.is_public());
assert!(!fun.is_predicate()); assert!(!fun.is_predicate());
assert_eq!(fun.name(), "marty"); assert_eq!(fun.name(), "marty");
@ -156,8 +158,7 @@ mod test {
#[test] #[test]
fn name_with_predicate() { fn name_with_predicate() {
let pair = parse_str("def marty?", Rule::def_function); let fun = DefineFunction::parse("def marty?").unwrap();
let fun = DefineFunction::from(pair);
assert!(fun.is_public()); assert!(fun.is_public());
assert!(fun.is_predicate()); assert!(fun.is_predicate());
assert_eq!(fun.name(), "marty?"); assert_eq!(fun.name(), "marty?");
@ -165,8 +166,7 @@ mod test {
#[test] #[test]
fn with_return_type() { fn with_return_type() {
let pair = parse_str("def <McFly> marty", Rule::def_function); let fun = DefineFunction::parse("def <McFly> marty").unwrap();
let fun = DefineFunction::from(pair);
assert!(fun.is_public()); assert!(fun.is_public());
assert!(!fun.is_predicate()); assert!(!fun.is_predicate());
assert_eq!(fun.name(), "marty"); assert_eq!(fun.name(), "marty");
@ -175,8 +175,7 @@ mod test {
#[test] #[test]
fn with_arguments() { fn with_arguments() {
let pair = parse_str("def marty family: McFly, car: Delorean", Rule::def_function); let fun = DefineFunction::parse("def marty family: McFly, car: Delorean").unwrap();
let fun = DefineFunction::from(pair);
assert!(fun.is_public()); assert!(fun.is_public());
assert!(!fun.is_predicate()); assert!(!fun.is_predicate());
assert_eq!(fun.name(), "marty"); assert_eq!(fun.name(), "marty");

View file

@ -1,5 +1,6 @@
use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName}; use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName};
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::{Pair, Pairs}; use pest::iterators::{Pair, Pairs};
use pest::Span; use pest::Span;
@ -60,6 +61,10 @@ impl<'a> From<Pair<'a, Rule>> for ModuleType {
} }
} }
impl<'a> Parse<'a> for DefineModule<'a> {
const RULE: Rule = Rule::def_module;
}
impl<'a> From<Pair<'a, Rule>> for DefineModule<'a> { impl<'a> From<Pair<'a, Rule>> for DefineModule<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::def_module); assert_eq!(pair.as_rule(), Rule::def_module);
@ -87,43 +92,37 @@ fn get_arguments<'a>(pairs: Pairs<'a, Rule>) -> Vec<(ArgumentName<'a>, Expressio
let arg_name = pairs.next().unwrap(); let arg_name = pairs.next().unwrap();
let value = pairs.next().unwrap(); let value = pairs.next().unwrap();
(ArgumentName::from(arg_name), Expression::from(value)) (ArgumentName::from(arg_name), Expression::from(value))
}) }).collect()
.collect()
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn type_name_only() { fn type_name_only() {
let pair = parse_str("deftype Marty", Rule::def_module); let module = DefineModule::parse("deftype Marty").unwrap();
let module = DefineModule::from(pair);
assert!(module.is_type()); assert!(module.is_type());
assert_eq!(module.type_name().name(), "Marty"); assert_eq!(module.type_name().name(), "Marty");
} }
#[test] #[test]
fn trait_name_only() { fn trait_name_only() {
let pair = parse_str("deftrait Marty", Rule::def_module); let module = DefineModule::parse("deftrait Marty").unwrap();
let module = DefineModule::from(pair);
assert!(module.is_trait()); assert!(module.is_trait());
assert_eq!(module.type_name().name(), "Marty"); assert_eq!(module.type_name().name(), "Marty");
} }
#[test] #[test]
fn impl_name_only() { fn impl_name_only() {
let pair = parse_str("defimpl Marty", Rule::def_module); let module = DefineModule::parse("defimpl Marty").unwrap();
let module = DefineModule::from(pair);
assert!(module.is_implementation()); assert!(module.is_implementation());
assert_eq!(module.type_name().name(), "Marty"); assert_eq!(module.type_name().name(), "Marty");
} }
#[test] #[test]
fn type_with_fields() { fn type_with_fields() {
let pair = parse_str("deftype Delorean speed: Integer", Rule::def_module); let module = DefineModule::parse("deftype Delorean speed: Integer").unwrap();
let module = DefineModule::from(pair);
assert!(module.is_type()); assert!(module.is_type());
assert_eq!(module.type_name().name(), "Delorean"); assert_eq!(module.type_name().name(), "Delorean");
let (ref arg_name, ref arg_value) = module.fields()[0]; let (ref arg_name, ref arg_value) = module.fields()[0];

View file

@ -3,6 +3,7 @@ use ast::{
unary::Unary, unary::Unary,
}; };
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -21,6 +22,10 @@ pub enum Inner<'a> {
Unary(Unary<'a>), Unary(Unary<'a>),
} }
impl<'a> Parse<'a> for Expression<'a> {
const RULE: Rule = Rule::expression;
}
impl<'a> From<Pair<'a, Rule>> for Expression<'a> { impl<'a> From<Pair<'a, Rule>> for Expression<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::expression); assert_eq!(pair.as_rule(), Rule::expression);
@ -159,20 +164,17 @@ impl<'a> Expression<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn block() { fn block() {
let pair = parse_str("-> 123 end", Rule::expression); let expr = Expression::parse("-> 123 end").unwrap();
let expr = Expression::from(pair);
assert!(expr.is_block()); assert!(expr.is_block());
assert_eq!(expr.block().unwrap().body().len(), 1); assert_eq!(expr.block().unwrap().body().len(), 1);
} }
#[test] #[test]
fn call() { fn call() {
let pair = parse_str("marty.mcfly()", Rule::expression); let expr = Expression::parse("marty.mcfly()").unwrap();
let expr = Expression::from(pair);
assert!(expr.is_call()); assert!(expr.is_call());
assert_eq!(expr.call().unwrap().receiver().name(), "marty"); assert_eq!(expr.call().unwrap().receiver().name(), "marty");
assert_eq!(expr.call().unwrap().message().name(), "mcfly"); assert_eq!(expr.call().unwrap().message().name(), "mcfly");
@ -180,8 +182,7 @@ mod test {
#[test] #[test]
fn infix() { fn infix() {
let pair = parse_str("123 * 234", Rule::expression); let expr = Expression::parse("123 * 234").unwrap();
let expr = Expression::from(pair);
assert!(expr.is_infix()); assert!(expr.is_infix());
assert_eq!( assert_eq!(
expr.infix() expr.infix()
@ -209,16 +210,14 @@ mod test {
#[test] #[test]
fn literal() { fn literal() {
let pair = parse_str("123", Rule::expression); let expr = Expression::parse("123").unwrap();
let expr = Expression::from(pair);
assert!(expr.is_literal()); assert!(expr.is_literal());
assert_eq!(expr.literal().unwrap().integer().unwrap().value(), 123); assert_eq!(expr.literal().unwrap().integer().unwrap().value(), 123);
} }
#[test] #[test]
fn unary() { fn unary() {
let pair = parse_str("!123", Rule::expression); let expr = Expression::parse("!123").unwrap();
let expr = Expression::from(pair);
assert!(expr.is_unary()); assert!(expr.is_unary());
assert!(expr.unary().unwrap().op().is_logical_not()); assert!(expr.unary().unwrap().op().is_logical_not());
assert_eq!( assert_eq!(

View file

@ -1,5 +1,6 @@
use ast::define_module::DefineModule; use ast::define_module::DefineModule;
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -9,6 +10,10 @@ pub struct File<'a> {
modules: Vec<DefineModule<'a>>, modules: Vec<DefineModule<'a>>,
} }
impl<'a> Parse<'a> for File<'a> {
const RULE: Rule = Rule::file;
}
impl<'a> From<Pair<'a, Rule>> for File<'a> { impl<'a> From<Pair<'a, Rule>> for File<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::file); assert_eq!(pair.as_rule(), Rule::file);
@ -32,12 +37,10 @@ impl<'a> File<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn file() { fn file() {
let pair = parse_str("deftype Marty", Rule::file); let file = File::parse("deftype Marty").unwrap();
let file = File::from(pair);
assert_eq!(file.modules().len(), 1); assert_eq!(file.modules().len(), 1);
} }
} }

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
use std::str::FromStr; use std::str::FromStr;
@ -9,6 +10,10 @@ pub struct Float<'a> {
value: f64, value: f64,
} }
impl<'a> Parse<'a> for Float<'a> {
const RULE: Rule = Rule::float;
}
impl<'a> From<Pair<'a, Rule>> for Float<'a> { impl<'a> From<Pair<'a, Rule>> for Float<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::float); assert_eq!(pair.as_rule(), Rule::float);
@ -33,19 +38,16 @@ impl<'a> Float<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn float_zero_zero() { fn float_zero_zero() {
let pair = parse_str("0.0", Rule::float); let flt = Float::parse("0.0").unwrap();
let flt = Float::from(pair);
assert_eq!(flt.value, 0.0); assert_eq!(flt.value, 0.0);
} }
#[test] #[test]
fn float_123_123() { fn float_123_123() {
let pair = parse_str("123.123", Rule::float); let flt = Float::parse("123.123").unwrap();
let flt = Float::from(pair);
assert_eq!(flt.value, 123.123); assert_eq!(flt.value, 123.123);
} }

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -9,6 +10,10 @@ pub struct Integer<'a> {
pub value: u64, pub value: u64,
} }
impl<'a> Parse<'a> for Integer<'a> {
const RULE: Rule = Rule::integer;
}
impl<'a> From<Pair<'a, Rule>> for Integer<'a> { impl<'a> From<Pair<'a, Rule>> for Integer<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::integer); assert_eq!(pair.as_rule(), Rule::integer);
@ -50,44 +55,38 @@ impl<'a> Integer<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn integer_zero() { fn integer_zero() {
let pair = parse_str("0", Rule::integer); let int = Integer::parse("0").unwrap();
let int = Integer::from(pair);
assert_eq!(int.radix, 0); assert_eq!(int.radix, 0);
assert_eq!(int.value, 0); assert_eq!(int.value, 0);
} }
#[test] #[test]
fn integer_binary() { fn integer_binary() {
let pair = parse_str("0b10101", Rule::integer); let int = Integer::parse("0b10101").unwrap();
let int = Integer::from(pair);
assert_eq!(int.radix, 2); assert_eq!(int.radix, 2);
assert_eq!(int.value, 21); assert_eq!(int.value, 21);
} }
#[test] #[test]
fn integer_octal() { fn integer_octal() {
let pair = parse_str("0o76543210", Rule::integer); let int = Integer::parse("0o76543210").unwrap();
let int = Integer::from(pair);
assert_eq!(int.radix, 8); assert_eq!(int.radix, 8);
assert_eq!(int.value, 16434824); assert_eq!(int.value, 16434824);
} }
#[test] #[test]
fn integer_decimal() { fn integer_decimal() {
let pair = parse_str("9876543210", Rule::integer); let int = Integer::parse("9876543210").unwrap();
let int = Integer::from(pair);
assert_eq!(int.radix, 10); assert_eq!(int.radix, 10);
assert_eq!(int.value, 9876543210); assert_eq!(int.value, 9876543210);
} }
#[test] #[test]
fn integer_hexadecimal() { fn integer_hexadecimal() {
let pair = parse_str("0xfEdCbA9876543210", Rule::integer); let int = Integer::parse("0xfEdCbA9876543210").unwrap();
let int = Integer::from(pair);
assert_eq!(int.radix, 16); assert_eq!(int.radix, 16);
assert_eq!(int.value, 18364758544493064720); assert_eq!(int.value, 18364758544493064720);
} }

View file

@ -4,6 +4,7 @@ use ast::{
type_name::TypeName, variable::Variable, type_name::TypeName, variable::Variable,
}; };
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -28,6 +29,10 @@ pub enum Inner<'a> {
Variable(Variable<'a>), Variable(Variable<'a>),
} }
impl<'a> Parse<'a> for Literal<'a> {
const RULE: Rule = Rule::literal;
}
impl<'a> From<Pair<'a, Rule>> for Literal<'a> { impl<'a> From<Pair<'a, Rule>> for Literal<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::literal); assert_eq!(pair.as_rule(), Rule::literal);
@ -231,92 +236,80 @@ impl<'a> Literal<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn array() { fn array() {
let pair = parse_str("[1, 2, 3]", Rule::literal); let lit = Literal::parse("[1, 2, 3]").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_array()); assert!(lit.is_array());
assert_eq!(lit.array().unwrap().values().len(), 3); assert_eq!(lit.array().unwrap().values().len(), 3);
} }
#[test] #[test]
fn map() { fn map() {
let pair = parse_str("{a: 1, b: 2}", Rule::literal); let lit = Literal::parse("{a: 1, b: 2}").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_map()); assert!(lit.is_map());
assert_eq!(lit.map().unwrap().values().len(), 2); assert_eq!(lit.map().unwrap().values().len(), 2);
} }
#[test] #[test]
fn atom() { fn atom() {
let pair = parse_str(":marty_mcfly", Rule::literal); let lit = Literal::parse(":marty_mcfly").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_atom()); assert!(lit.is_atom());
assert_eq!(lit.atom().unwrap().name(), "marty_mcfly"); assert_eq!(lit.atom().unwrap().name(), "marty_mcfly");
} }
#[test] #[test]
fn boolean() { fn boolean() {
let pair = parse_str("true", Rule::literal); let lit = Literal::parse("true").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_boolean()); assert!(lit.is_boolean());
assert!(lit.boolean().unwrap().is_true()); assert!(lit.boolean().unwrap().is_true());
} }
#[test] #[test]
fn constructor() { fn constructor() {
let pair = parse_str("Delorean { speed: 88 }", Rule::literal); let lit = Literal::parse("Delorean { speed: 88 }").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_constructor()); assert!(lit.is_constructor());
assert_eq!(lit.constructor().unwrap().type_name().name(), "Delorean"); assert_eq!(lit.constructor().unwrap().type_name().name(), "Delorean");
} }
#[test] #[test]
fn float() { fn float() {
let pair = parse_str("123.456", Rule::literal); let lit = Literal::parse("123.456").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_float()); assert!(lit.is_float());
assert_eq!(lit.float().unwrap().value(), 123.456); assert_eq!(lit.float().unwrap().value(), 123.456);
} }
#[test] #[test]
fn integer() { fn integer() {
let pair = parse_str("123", Rule::literal); let lit = Literal::parse("123").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_integer()); assert!(lit.is_integer());
assert_eq!(lit.integer().unwrap().value(), 123); assert_eq!(lit.integer().unwrap().value(), 123);
} }
#[test] #[test]
fn property() { fn property() {
let pair = parse_str("@doc_brown", Rule::literal); let lit = Literal::parse("@doc_brown").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_property()); assert!(lit.is_property());
assert_eq!(lit.property().unwrap().name(), "doc_brown"); assert_eq!(lit.property().unwrap().name(), "doc_brown");
} }
#[test] #[test]
fn string() { fn string() {
let pair = parse_str("\"Doc \\\"Emmet\\\" Brown\"", Rule::literal); let lit = Literal::parse("\"Doc \\\"Emmet\\\" Brown\"").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_string()); assert!(lit.is_string());
assert_eq!(lit.string().unwrap().value(), "Doc \"Emmet\" Brown"); assert_eq!(lit.string().unwrap().value(), "Doc \"Emmet\" Brown");
} }
#[test] #[test]
fn type_name() { fn type_name() {
let pair = parse_str("MartyMcFly", Rule::literal); let lit = Literal::parse("MartyMcFly").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_type_name()); assert!(lit.is_type_name());
assert_eq!(lit.type_name().unwrap().name(), "MartyMcFly"); assert_eq!(lit.type_name().unwrap().name(), "MartyMcFly");
} }
#[test] #[test]
fn variable() { fn variable() {
let pair = parse_str("marty_mcfly", Rule::literal); let lit = Literal::parse("marty_mcfly").unwrap();
let lit = Literal::from(pair);
assert!(lit.is_variable()); assert!(lit.is_variable());
assert_eq!(lit.variable().unwrap().name(), "marty_mcfly"); assert_eq!(lit.variable().unwrap().name(), "marty_mcfly");
} }

View file

@ -1,5 +1,6 @@
use ast::{atom::Atom, expression::Expression, literal::Literal}; use ast::{atom::Atom, expression::Expression, literal::Literal};
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -16,6 +17,10 @@ pub struct MapPair<'a> {
value: Box<Expression<'a>>, value: Box<Expression<'a>>,
} }
impl<'a> Parse<'a> for Map<'a> {
const RULE: Rule = Rule::map;
}
impl<'a> From<Pair<'a, Rule>> for Map<'a> { impl<'a> From<Pair<'a, Rule>> for Map<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::map); assert_eq!(pair.as_rule(), Rule::map);
@ -71,12 +76,10 @@ impl<'a> Map<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn keyword_map() { fn keyword_map() {
let pair = parse_str("{a: 1, b: 2}", Rule::map); let map = Map::parse("{a: 1, b: 2}").unwrap();
let map = Map::from(pair);
let map_pair = &map.values()[0]; let map_pair = &map.values()[0];
assert_eq!( assert_eq!(
@ -113,8 +116,7 @@ mod test {
#[test] #[test]
fn expression_map() { fn expression_map() {
let pair = parse_str("{ 1 : 2, 3 : 4 }", Rule::map); let map = Map::parse("{ 1 : 2, 3 : 4 }").unwrap();
let map = Map::from(pair);
let map_pair = &map.values()[0]; let map_pair = &map.values()[0];
assert_eq!( assert_eq!(

View file

@ -1,11 +1,16 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Operator<'a> { pub struct Operator<'a> {
pub span: Span<'a>, span: Span<'a>,
pub op: Op, op: Op,
}
impl<'a> Parse<'a> for Operator<'a> {
const RULE: Rule = Rule::all_operators;
} }
impl<'a> From<Pair<'a, Rule>> for Operator<'a> { impl<'a> From<Pair<'a, Rule>> for Operator<'a> {
@ -194,27 +199,27 @@ impl<'a> Operator<'a> {
impl<'a> From<Pair<'a, Rule>> for Op { impl<'a> From<Pair<'a, Rule>> for Op {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
match pair.as_rule() { match pair.as_rule() {
Rule::multiply => Op::Multiply, Rule::assign => Op::Assign,
Rule::divide => Op::Divide,
Rule::modulus => Op::Modulo,
Rule::plus => Op::Plus,
Rule::minus => Op::Minus,
Rule::shift_left => Op::ShiftLeft,
Rule::shift_right => Op::ShiftRight,
Rule::less_than => Op::LessThan,
Rule::less_than_or_equal => Op::LessThanOrEqual,
Rule::greater_than => Op::GreaterThan,
Rule::greater_than_or_equal => Op::GreaterThanOrEqual,
Rule::not_equal => Op::NotEqual,
Rule::equal => Op::Equal,
Rule::exponent => Op::Exponent,
Rule::logical_and => Op::LogicalAnd,
Rule::logical_or => Op::LogicalOr,
Rule::logical_not => Op::LogicalNot,
Rule::bitwise_and => Op::BitwiseAnd, Rule::bitwise_and => Op::BitwiseAnd,
Rule::bitwise_or => Op::BitwiseOr, Rule::bitwise_or => Op::BitwiseOr,
Rule::bitwise_xor => Op::BitwiseXor, Rule::bitwise_xor => Op::BitwiseXor,
Rule::assign => Op::Assign, Rule::divide => Op::Divide,
Rule::equal => Op::Equal,
Rule::exponent => Op::Exponent,
Rule::greater_than => Op::GreaterThan,
Rule::greater_than_or_equal => Op::GreaterThanOrEqual,
Rule::less_than => Op::LessThan,
Rule::less_than_or_equal => Op::LessThanOrEqual,
Rule::logical_and => Op::LogicalAnd,
Rule::logical_not => Op::LogicalNot,
Rule::logical_or => Op::LogicalOr,
Rule::minus => Op::Minus,
Rule::modulus => Op::Modulo,
Rule::multiply => Op::Multiply,
Rule::not_equal => Op::NotEqual,
Rule::plus => Op::Plus,
Rule::shift_left => Op::ShiftLeft,
Rule::shift_right => Op::ShiftRight,
_ => panic!("Node {:?} is not an operator", pair), _ => panic!("Node {:?} is not an operator", pair),
} }
} }
@ -223,256 +228,131 @@ impl<'a> From<Pair<'a, Rule>> for Op {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::{parse_str, Rule};
mod operator {
use super::*;
#[test] #[test]
fn multiply() { fn assign() {
let result = parse_str("*", Rule::all_operators); let op = Operator::parse("=").unwrap();
assert_eq!(Op::Multiply, Operator::from(result).op) assert!(op.is_assign());
}
#[test]
fn divide() {
let result = parse_str("/", Rule::all_operators);
assert_eq!(Op::Divide, Operator::from(result).op);
}
#[test]
fn modulus() {
let result = parse_str("%", Rule::all_operators);
assert_eq!(Op::Modulo, Operator::from(result).op);
}
#[test]
fn plus() {
let result = parse_str("+", Rule::all_operators);
assert_eq!(Op::Plus, Operator::from(result).op);
}
#[test]
fn minus() {
let result = parse_str("-", Rule::all_operators);
assert_eq!(Op::Minus, Operator::from(result).op);
}
#[test]
fn shift_left() {
let result = parse_str("<<", Rule::all_operators);
assert_eq!(Op::ShiftLeft, Operator::from(result).op);
}
#[test]
fn shift_right() {
let result = parse_str(">>", Rule::all_operators);
assert_eq!(Op::ShiftRight, Operator::from(result).op);
}
#[test]
fn less_than() {
let result = parse_str("<", Rule::all_operators);
assert_eq!(Op::LessThan, Operator::from(result).op);
}
#[test]
fn less_than_or_equal() {
let result = parse_str("<=", Rule::all_operators);
assert_eq!(Op::LessThanOrEqual, Operator::from(result).op);
}
#[test]
fn greater_than() {
let result = parse_str(">", Rule::all_operators);
assert_eq!(Op::GreaterThan, Operator::from(result).op);
}
#[test]
fn greater_than_or_equal() {
let result = parse_str(">=", Rule::all_operators);
assert_eq!(Op::GreaterThanOrEqual, Operator::from(result).op);
}
#[test]
fn not_equal() {
let result = parse_str("!=", Rule::all_operators);
assert_eq!(Op::NotEqual, Operator::from(result).op);
}
#[test]
fn equal() {
let result = parse_str("==", Rule::all_operators);
assert_eq!(Op::Equal, Operator::from(result).op);
}
#[test]
fn logical_and() {
let result = parse_str("&&", Rule::all_operators);
assert_eq!(Op::LogicalAnd, Operator::from(result).op);
}
#[test]
fn logical_or() {
let result = parse_str("||", Rule::all_operators);
assert_eq!(Op::LogicalOr, Operator::from(result).op);
}
#[test]
fn logical_not() {
let result = parse_str("!", Rule::all_operators);
assert_eq!(Op::LogicalNot, Operator::from(result).op);
} }
#[test] #[test]
fn bitwise_and() { fn bitwise_and() {
let result = parse_str("&", Rule::all_operators); let op = Operator::parse("&").unwrap();
assert_eq!(Op::BitwiseAnd, Operator::from(result).op); assert!(op.is_bitwise_and());
} }
#[test] #[test]
fn bitwise_or() { fn bitwise_or() {
let result = parse_str("|", Rule::all_operators); let op = Operator::parse("|").unwrap();
assert_eq!(Op::BitwiseOr, Operator::from(result).op); assert!(op.is_bitwise_or());
} }
#[test] #[test]
fn bitwise_xor() { fn bitwise_xor() {
let result = parse_str("^", Rule::all_operators); let op = Operator::parse("^").unwrap();
assert_eq!(Op::BitwiseXor, Operator::from(result).op); assert!(op.is_bitwise_xor());
}
#[test]
fn assign() {
let result = parse_str("=", Rule::all_operators);
assert_eq!(Op::Assign, Operator::from(result).op);
}
}
mod op {
use super::*;
#[test]
fn multiply() {
let result = parse_str("*", Rule::all_operators);
assert_eq!(Op::Multiply, Op::from(result));
} }
#[test] #[test]
fn divide() { fn divide() {
let result = parse_str("/", Rule::all_operators); let op = Operator::parse("/").unwrap();
assert_eq!(Op::Divide, Op::from(result)); assert!(op.is_divide());
}
#[test]
fn modulus() {
let result = parse_str("%", Rule::all_operators);
assert_eq!(Op::Modulo, Op::from(result));
}
#[test]
fn plus() {
let result = parse_str("+", Rule::all_operators);
assert_eq!(Op::Plus, Op::from(result));
}
#[test]
fn minus() {
let result = parse_str("-", Rule::all_operators);
assert_eq!(Op::Minus, Op::from(result));
}
#[test]
fn shift_left() {
let result = parse_str("<<", Rule::all_operators);
assert_eq!(Op::ShiftLeft, Op::from(result));
}
#[test]
fn shift_right() {
let result = parse_str(">>", Rule::all_operators);
assert_eq!(Op::ShiftRight, Op::from(result));
}
#[test]
fn less_than() {
let result = parse_str("<", Rule::all_operators);
assert_eq!(Op::LessThan, Op::from(result));
}
#[test]
fn less_than_or_equal() {
let result = parse_str("<=", Rule::all_operators);
assert_eq!(Op::LessThanOrEqual, Op::from(result));
}
#[test]
fn greater_than() {
let result = parse_str(">", Rule::all_operators);
assert_eq!(Op::GreaterThan, Op::from(result));
}
#[test]
fn greater_than_or_equal() {
let result = parse_str(">=", Rule::all_operators);
assert_eq!(Op::GreaterThanOrEqual, Op::from(result));
}
#[test]
fn not_equal() {
let result = parse_str("!=", Rule::all_operators);
assert_eq!(Op::NotEqual, Op::from(result));
} }
#[test] #[test]
fn equal() { fn equal() {
let result = parse_str("==", Rule::all_operators); let op = Operator::parse("==").unwrap();
assert_eq!(Op::Equal, Op::from(result)); assert!(op.is_equal());
}
#[test]
fn exponent() {
let op = Operator::parse("**").unwrap();
assert!(op.is_exponent());
}
#[test]
fn greater_than() {
let op = Operator::parse(">").unwrap();
assert!(op.is_greater_than());
}
#[test]
fn greater_than_or_equal() {
let op = Operator::parse(">=").unwrap();
assert!(op.is_greater_than_or_equal());
}
#[test]
fn less_than() {
let op = Operator::parse("<").unwrap();
assert!(op.is_less_than());
}
#[test]
fn less_than_or_equal() {
let op = Operator::parse("<=").unwrap();
assert!(op.is_less_than_or_equal());
} }
#[test] #[test]
fn logical_and() { fn logical_and() {
let result = parse_str("&&", Rule::all_operators); let op = Operator::parse("&&").unwrap();
assert_eq!(Op::LogicalAnd, Op::from(result)); assert!(op.is_logical_and());
}
#[test]
fn logical_or() {
let result = parse_str("||", Rule::all_operators);
assert_eq!(Op::LogicalOr, Op::from(result));
} }
#[test] #[test]
fn logical_not() { fn logical_not() {
let result = parse_str("!", Rule::all_operators); let op = Operator::parse("!").unwrap();
assert_eq!(Op::LogicalNot, Op::from(result)); assert!(op.is_logical_not());
} }
#[test] #[test]
fn bitwise_and() { fn logical_or() {
let result = parse_str("&", Rule::all_operators); let op = Operator::parse("||").unwrap();
assert_eq!(Op::BitwiseAnd, Op::from(result)); assert!(op.is_logical_or());
} }
#[test] #[test]
fn bitwise_or() { fn minus() {
let result = parse_str("|", Rule::all_operators); let op = Operator::parse("-").unwrap();
assert_eq!(Op::BitwiseOr, Op::from(result)); assert!(op.is_minus());
} }
#[test] #[test]
fn bitwise_xor() { fn modulus() {
let result = parse_str("^", Rule::all_operators); let op = Operator::parse("%").unwrap();
assert_eq!(Op::BitwiseXor, Op::from(result)); assert!(op.is_modulo());
} }
#[test] #[test]
fn assign() { fn multiply() {
let result = parse_str("=", Rule::all_operators); let op = Operator::parse("*").unwrap();
assert_eq!(Op::Assign, Op::from(result)); assert!(op.is_multiply());
} }
#[test]
fn not_equal() {
let op = Operator::parse("!=").unwrap();
assert!(op.is_not_equal());
}
#[test]
fn plus() {
let op = Operator::parse("+").unwrap();
assert!(op.is_plus());
}
#[test]
fn shift_left() {
let op = Operator::parse("<<").unwrap();
assert!(op.is_shift_left());
}
#[test]
fn shift_right() {
let op = Operator::parse(">>").unwrap();
assert!(op.is_shift_right());
} }
} }

View file

@ -43,12 +43,11 @@ pub fn climb<'a>(pair: Pair<'a, Rule>) -> Expression<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str; use parse::Parse;
#[test] #[test]
fn precedence_test() { fn precedence_test() {
let result = parse_str("10 * 20 + 30", Rule::expression_test); let expr = Expression::parse("10 * 20 + 30").unwrap();
let expr = Expression::from(result);
let infix0 = expr.infix().unwrap(); let infix0 = expr.infix().unwrap();
assert!(infix0.op().is_plus()); assert!(infix0.op().is_plus());
assert_eq!( assert_eq!(

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -8,6 +9,10 @@ pub struct Property<'a> {
name: String, name: String,
} }
impl<'a> Parse<'a> for Property<'a> {
const RULE: Rule = Rule::property;
}
impl<'a> From<Pair<'a, Rule>> for Property<'a> { impl<'a> From<Pair<'a, Rule>> for Property<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::property); assert_eq!(pair.as_rule(), Rule::property);
@ -37,13 +42,10 @@ impl<'a> Property<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn property() { fn property() {
let pair = parse_str("@marty_mcfly", Rule::property); let property = Property::parse("@marty_mcfly").unwrap();
let property = Property::from(pair);
assert_eq!(property.name(), "marty_mcfly"); assert_eq!(property.name(), "marty_mcfly");
} }
} }

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
use regex::{Captures, Regex}; use regex::{Captures, Regex};
@ -14,6 +15,10 @@ pub struct StringLiteral<'a> {
value: String, value: String,
} }
impl<'a> Parse<'a> for StringLiteral<'a> {
const RULE: Rule = Rule::string;
}
impl<'a> From<Pair<'a, Rule>> for StringLiteral<'a> { impl<'a> From<Pair<'a, Rule>> for StringLiteral<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::string); assert_eq!(pair.as_rule(), Rule::string);
@ -60,91 +65,70 @@ impl<'a> StringLiteral<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn basic() { fn basic() {
let pair = parse_str(r#""hello world""#, Rule::string); let value = StringLiteral::parse(r#""hello world""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "hello world"); assert_eq!(value.value(), "hello world");
} }
#[test] #[test]
fn vartical_tab_escape() { fn vartical_tab_escape() {
let pair = parse_str(r#""\v""#, Rule::string); let value = StringLiteral::parse(r#""\v""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\u{000b}"); assert_eq!(value.value(), "\u{000b}");
} }
#[test] #[test]
fn tab_escape() { fn tab_escape() {
let pair = parse_str(r#""\t""#, Rule::string); let value = StringLiteral::parse(r#""\t""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\t"); assert_eq!(value.value(), "\t");
} }
#[test] #[test]
fn carriage_return_escape() { fn carriage_return_escape() {
let pair = parse_str(r#""\r""#, Rule::string); let value = StringLiteral::parse(r#""\r""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\r"); assert_eq!(value.value(), "\r");
} }
#[test] #[test]
fn newline_escape() { fn newline_escape() {
let pair = parse_str(r#""\n""#, Rule::string); let value = StringLiteral::parse(r#""\n""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\n"); assert_eq!(value.value(), "\n");
} }
#[test] #[test]
fn formfeed_escape() { fn formfeed_escape() {
let pair = parse_str(r#""\f""#, Rule::string); let value = StringLiteral::parse(r#""\f""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\u{000c}"); assert_eq!(value.value(), "\u{000c}");
} }
#[test] #[test]
fn backspace_escape() { fn backspace_escape() {
let pair = parse_str(r#""\b""#, Rule::string); let value = StringLiteral::parse(r#""\b""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\u{0008}"); assert_eq!(value.value(), "\u{0008}");
} }
#[test] #[test]
fn alert_escape() { fn alert_escape() {
let pair = parse_str(r#""\a""#, Rule::string); let value = StringLiteral::parse(r#""\a""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\u{0007}"); assert_eq!(value.value(), "\u{0007}");
} }
#[test] #[test]
fn unicode_escape() { fn unicode_escape() {
let pair = parse_str(r#""\u26f5""#, Rule::string); let value = StringLiteral::parse(r#""\u26f5""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\u{26f5}"); assert_eq!(value.value(), "\u{26f5}");
} }
#[test] #[test]
fn backslash_escape() { fn backslash_escape() {
let pair = parse_str(r#""\\""#, Rule::string); let value = StringLiteral::parse(r#""\\""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), "\\"); assert_eq!(value.value(), "\\");
} }
#[test] #[test]
fn doublequote_escape() { fn doublequote_escape() {
let pair = parse_str(r#""\""""#, Rule::string); let value = StringLiteral::parse(r#""\""""#).unwrap();
let value = StringLiteral::from(pair);
assert_eq!(value.value(), r#"""#); assert_eq!(value.value(), r#"""#);
} }
} }

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -8,6 +9,10 @@ pub struct TypeName<'a> {
pub name: String, pub name: String,
} }
impl<'a> Parse<'a> for TypeName<'a> {
const RULE: Rule = Rule::type_name;
}
impl<'a> From<Pair<'a, Rule>> for TypeName<'a> { impl<'a> From<Pair<'a, Rule>> for TypeName<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::type_name); assert_eq!(pair.as_rule(), Rule::type_name);
@ -30,12 +35,10 @@ impl<'a> TypeName<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn name() { fn name() {
let pair = parse_str("DocBrown", Rule::type_name); let type_name = TypeName::parse("DocBrown").unwrap();
let type_name = TypeName::from(pair);
assert_eq!(type_name.name(), "DocBrown"); assert_eq!(type_name.name(), "DocBrown");
} }
} }

View file

@ -1,5 +1,6 @@
use ast::{expression::Expression, operator::Operator}; use ast::{expression::Expression, operator::Operator};
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -10,6 +11,10 @@ pub struct Unary<'a> {
expression: Box<Expression<'a>>, expression: Box<Expression<'a>>,
} }
impl<'a> Parse<'a> for Unary<'a> {
const RULE: Rule = Rule::unary;
}
impl<'a> From<Pair<'a, Rule>> for Unary<'a> { impl<'a> From<Pair<'a, Rule>> for Unary<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::unary); assert_eq!(pair.as_rule(), Rule::unary);
@ -41,12 +46,10 @@ impl<'a> Unary<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn unary() { fn unary() {
let result = parse_str("!123", Rule::unary); let unary = Unary::parse("!123").unwrap();
let unary = Unary::from(result);
assert!(unary.op().is_logical_not()); assert!(unary.op().is_logical_not());
assert_eq!( assert_eq!(

View file

@ -1,4 +1,5 @@
use grammar::Rule; use grammar::Rule;
use parse::Parse;
use pest::iterators::Pair; use pest::iterators::Pair;
use pest::Span; use pest::Span;
@ -8,6 +9,10 @@ pub struct Variable<'a> {
pub name: String, pub name: String,
} }
impl<'a> Parse<'a> for Variable<'a> {
const RULE: Rule = Rule::variable;
}
impl<'a> From<Pair<'a, Rule>> for Variable<'a> { impl<'a> From<Pair<'a, Rule>> for Variable<'a> {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::variable); assert_eq!(pair.as_rule(), Rule::variable);
@ -30,13 +35,10 @@ impl<'a> Variable<'a> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use grammar::parse_str;
#[test] #[test]
fn variable() { fn variable() {
let pair = parse_str("marty_mcfly", Rule::variable); let variable = Variable::parse("marty_mcfly").unwrap();
let variable = Variable::from(pair);
assert_eq!(variable.name(), "marty_mcfly"); assert_eq!(variable.name(), "marty_mcfly");
} }
} }

View file

@ -38,7 +38,7 @@ boolean_false = @{ keyword_false }
boolean_true = @{ keyword_true } boolean_true = @{ keyword_true }
braced = !{ "(" ~ newline* ~ expression ~ newline* ~ ")" } braced = !{ "(" ~ newline* ~ expression ~ newline* ~ ")" }
constructor = !{ type_name ~ "{" ~ argument_list? ~ "}" } constructor = !{ type_name ~ "{" ~ argument_list? ~ "}" }
literal = !{ constructor | array | map | float | integer | string | atom | property | variable | braced | boolean | type_name } literal = !{ constructor | array | map | float | integer | string | atom | property | type_name | variable | braced | boolean }
property = ${ "@" ~ identifier } property = ${ "@" ~ identifier }
unary = ${ unary_operator ~ expression } unary = ${ unary_operator ~ expression }
variable = @{ identifier } variable = @{ identifier }
@ -87,7 +87,7 @@ keyword_false = { "false" }
identifier_test = _{ soi ~ identifier ~ eoi } identifier_test = _{ soi ~ identifier ~ eoi }
identifier = @{ !keyword ~ identifier_head ~ identifier_tail? } identifier = @{ !keyword ~ identifier_head ~ identifier_tail? }
identifier_head = @{ 'a'..'z' | "_" } identifier_head = @{ 'A'..'Z' | 'a'..'z' | "_" }
identifier_tail = @{ ('a'..'z' | 'A'..'Z' | "_" | '0'..'9')+ } identifier_tail = @{ ('a'..'z' | 'A'..'Z' | "_" | '0'..'9')+ }
type_name = @{ !keyword ~ type_name_head ~ type_name_tail? } type_name = @{ !keyword ~ type_name_head ~ type_name_tail? }
type_name_head = @{ 'A'..'Z' } type_name_head = @{ 'A'..'Z' }

View file

@ -6,16 +6,3 @@ pub struct Grammar;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
use pest::iterators::Pair;
use pest::Parser;
pub fn parse_str<'a>(source: &'a str, rule: Rule) -> Pair<'a, Rule> {
let result = Grammar::parse(rule, source);
if result.is_err() {
println!("{}", result.err().unwrap());
panic!("Parses without failure");
} else {
result.unwrap().next().unwrap()
}
}

View file

@ -1,4 +1,3 @@
use super::assert_parses_expression;
use grammar::{Grammar, Rule}; use grammar::{Grammar, Rule};
#[test] #[test]

View file

@ -1,4 +1,4 @@
use grammar::{Grammar, Rule}; // use grammar::{Grammar, Rule};
// #[test] // #[test]
// fn binary_operators() { // fn binary_operators() {

View file

@ -16,4 +16,8 @@ mod parse;
pub use ast::*; pub use ast::*;
pub use error::ParseError; pub use error::ParseError;
pub use parse::parse_file; pub use parse::Parse;
pub fn parse_file<'a>(source: &'a str) -> Result<File<'a>, ParseError<'a>> {
File::parse(source)
}

View file

@ -1,16 +1,18 @@
use ast::File;
use error::ParseError; use error::ParseError;
use grammar::{Grammar, Rule}; use grammar::{Grammar, Rule};
use pest::{iterators::Pair, Parser}; use pest::{iterators::Pair, Parser};
pub fn parse_file<'a>(source: &'a str) -> Result<File<'a>, ParseError<'a>> { pub trait Parse<'a, Node = Self>
run_parser(source, Rule::file).and_then(|p| Ok(File::from(p))) where
} Node: From<Pair<'a, Rule>>,
{
const RULE: Rule;
fn run_parser<'a>(source: &'a str, rule: Rule) -> Result<Pair<'a, Rule>, ParseError<'a>> { fn parse(source: &'a str) -> Result<Node, ParseError<'a>> {
let result = Grammar::parse(rule, source); let result = Grammar::parse(Self::RULE, source);
match result { match result {
Ok(mut pairs) => Ok(pairs.next().unwrap()), Ok(mut pairs) => Ok(Node::from(pairs.next().unwrap())),
Err(pest_error) => Err(ParseError::from(pest_error)), Err(pest_error) => Err(ParseError::from(pest_error)),
} }
} }
}