Merge branch 'master' into lets-invent-a-linter
This commit is contained in:
commit
e5a2bc1291
30 changed files with 329 additions and 451 deletions
|
@ -1,11 +1,16 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ArgumentName<'a> {
|
||||
pub span: Span<'a>,
|
||||
pub name: String,
|
||||
span: Span<'a>,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for ArgumentName<'a> {
|
||||
const RULE: Rule = Rule::argument_keyword;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for ArgumentName<'a> {
|
||||
|
@ -31,13 +36,10 @@ impl<'a> ArgumentName<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn argument_name() {
|
||||
let pair = parse_str("marty_mcfly:", Rule::argument_keyword);
|
||||
let argument_name = ArgumentName::from(pair);
|
||||
|
||||
assert_eq!(argument_name.name, "marty_mcfly");
|
||||
let argument_name = ArgumentName::parse("marty_mcfly:").unwrap();
|
||||
assert_eq!(argument_name.name(), "marty_mcfly");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::expression::Expression;
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -9,6 +10,10 @@ pub struct Array<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::array);
|
||||
|
@ -32,12 +37,10 @@ impl<'a> Array<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn array_of_ints() {
|
||||
let result = parse_str("[1, 2, 3]", Rule::array);
|
||||
let array = Array::from(result);
|
||||
let array = Array::parse("[1, 2, 3]").unwrap();
|
||||
let mut value = 0;
|
||||
for expr in array.values() {
|
||||
value = value + 1;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::into_span::IntoSpan;
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -9,6 +10,10 @@ pub struct Atom<'a> {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Atom<'a> {
|
||||
const RULE: Rule = Rule::atom;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Atom<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
match pair.as_rule() {
|
||||
|
@ -62,12 +67,10 @@ impl<'a> IntoSpan<'a> for Atom<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn atom() {
|
||||
let pair = parse_str(":marty_mcfly", Rule::atom);
|
||||
let atom = Atom::from(pair);
|
||||
let atom = Atom::parse(":marty_mcfly").unwrap();
|
||||
assert_eq!(atom.name(), "marty_mcfly");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::{define_function::DefineFunction, expression::Expression};
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -15,6 +16,10 @@ pub enum Inner<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
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::expression => Inner::Expression(Expression::from(p)),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect();
|
||||
}).collect();
|
||||
|
||||
Block {
|
||||
span: span,
|
||||
|
@ -61,19 +65,16 @@ impl<'a> Block<'a> {
|
|||
#[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);
|
||||
let block = Block::parse("-> end").unwrap();
|
||||
assert!(block.body().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_single() {
|
||||
let pair = parse_str("-> 123 end", Rule::block_test);
|
||||
let block = Block::from(pair);
|
||||
let block = Block::parse("-> 123 end").unwrap();
|
||||
assert_eq!(block.body().len(), 1);
|
||||
assert_eq!(
|
||||
block.body()[0]
|
||||
|
@ -90,15 +91,13 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn block_multi() {
|
||||
let pair = parse_str(
|
||||
let block = Block::parse(
|
||||
"->
|
||||
:marty
|
||||
:doc
|
||||
:einstein
|
||||
end",
|
||||
Rule::block_test,
|
||||
);
|
||||
let block = Block::from(pair);
|
||||
).unwrap();
|
||||
assert_eq!(block.body().len(), 3);
|
||||
assert_eq!(
|
||||
block.body()[0]
|
||||
|
@ -137,8 +136,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn block_with_function_define() {
|
||||
let pair = parse_str("-> def marty? end", Rule::block);
|
||||
let block = Block::from(pair);
|
||||
let block = Block::parse("-> def marty? end").unwrap();
|
||||
assert_eq!(block.body()[0].define_function().unwrap().name(), "marty?");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -8,6 +9,10 @@ pub struct Boolean<'a> {
|
|||
value: bool,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Boolean<'a> {
|
||||
const RULE: Rule = Rule::boolean;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Boolean<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::boolean);
|
||||
|
@ -44,19 +49,16 @@ impl<'a> Boolean<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn boolean_true() {
|
||||
let pair = parse_str("true", Rule::boolean);
|
||||
let b = Boolean::from(pair);
|
||||
let b = Boolean::parse("true").unwrap();
|
||||
assert!(b.value());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_false() {
|
||||
let pair = parse_str("false", Rule::boolean);
|
||||
let b = Boolean::from(pair);
|
||||
let b = Boolean::parse("false").unwrap();
|
||||
assert!(!b.value());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use ast::call::{message::Message, receiver::Receiver};
|
||||
use ast::expression::Expression;
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -12,6 +13,10 @@ pub struct Call<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::call);
|
||||
|
@ -53,13 +58,10 @@ impl<'a> Call<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::{parse_str, Rule};
|
||||
|
||||
#[test]
|
||||
fn call_no_arg() {
|
||||
let result = parse_str("delorean.accelerate()", Rule::call);
|
||||
let call = Call::from(result);
|
||||
|
||||
let call = Call::parse("delorean.accelerate()").unwrap();
|
||||
assert_eq!(call.receiver().name(), "delorean");
|
||||
assert_eq!(call.message().name(), "accelerate");
|
||||
assert_eq!(call.arguments().len(), 0);
|
||||
|
@ -67,10 +69,8 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn call_with_arg() {
|
||||
let result = parse_str("delorean.accelerate(88)", Rule::call);
|
||||
let call = Call::from(result);
|
||||
let call = Call::parse("delorean.accelerate(88)").unwrap();
|
||||
let ref arg = call.arguments[0];
|
||||
|
||||
assert_eq!(call.receiver().name(), "delorean");
|
||||
assert_eq!(call.message().name(), "accelerate");
|
||||
assert_eq!(arg.literal().unwrap().integer().unwrap().value(), 88);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -8,6 +9,10 @@ pub struct Message<'a> {
|
|||
name: String,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Message<'a> {
|
||||
const RULE: Rule = Rule::call_message;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Message<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::call_message);
|
||||
|
@ -31,12 +36,10 @@ impl<'a> Message<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::{parse_str, Rule};
|
||||
|
||||
#[test]
|
||||
fn message() {
|
||||
let result = parse_str("marty_mcfly", Rule::call_message);
|
||||
let node = Message::from(result);
|
||||
let node = Message::parse("marty_mcfly").unwrap();
|
||||
assert_eq!(node.name(), "marty_mcfly");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -8,6 +9,10 @@ pub struct Receiver<'a> {
|
|||
name: String,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Receiver<'a> {
|
||||
const RULE: Rule = Rule::call_receiver;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Receiver<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::call_receiver);
|
||||
|
@ -31,12 +36,10 @@ impl<'a> Receiver<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::{parse_str, Rule};
|
||||
|
||||
#[test]
|
||||
fn receiver() {
|
||||
let result = parse_str("marty_mcfly", Rule::call_receiver);
|
||||
let node = Receiver::from(result);
|
||||
let node = Receiver::parse("marty_mcfly").unwrap();
|
||||
assert_eq!(node.name(), "marty_mcfly");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName};
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -10,6 +11,10 @@ pub struct Constructor<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::constructor);
|
||||
|
@ -48,12 +53,10 @@ impl<'a> Constructor<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn constructor() {
|
||||
let pair = parse_str("Delorean { speed: 88 }", Rule::constructor);
|
||||
let constructor = Constructor::from(pair);
|
||||
let constructor = Constructor::parse("Delorean { speed: 88 }").unwrap();
|
||||
assert_eq!(constructor.type_name().name(), "Delorean");
|
||||
let (ref arg_name, ref arg_value) = constructor.fields()[0];
|
||||
assert_eq!(arg_name.name(), "speed");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName};
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::{Pair, Pairs};
|
||||
use pest::Span;
|
||||
|
||||
|
@ -26,6 +27,10 @@ pub struct FunctionName<'a> {
|
|||
predicate: bool,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for DefineFunction<'a> {
|
||||
const RULE: Rule = Rule::def_function;
|
||||
}
|
||||
|
||||
impl<'a> DefineFunction<'a> {
|
||||
pub fn name(&self) -> &str {
|
||||
&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 value = pairs.next().unwrap();
|
||||
(ArgumentName::from(arg_name), Expression::from(value))
|
||||
})
|
||||
.collect()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for FunctionType {
|
||||
|
@ -143,12 +147,10 @@ impl<'a> From<Pair<'a, Rule>> for FunctionType {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn name_only() {
|
||||
let pair = parse_str("def marty", Rule::def_function);
|
||||
let fun = DefineFunction::from(pair);
|
||||
let fun = DefineFunction::parse("def marty").unwrap();
|
||||
assert!(fun.is_public());
|
||||
assert!(!fun.is_predicate());
|
||||
assert_eq!(fun.name(), "marty");
|
||||
|
@ -156,8 +158,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn name_with_predicate() {
|
||||
let pair = parse_str("def marty?", Rule::def_function);
|
||||
let fun = DefineFunction::from(pair);
|
||||
let fun = DefineFunction::parse("def marty?").unwrap();
|
||||
assert!(fun.is_public());
|
||||
assert!(fun.is_predicate());
|
||||
assert_eq!(fun.name(), "marty?");
|
||||
|
@ -165,8 +166,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn with_return_type() {
|
||||
let pair = parse_str("def <McFly> marty", Rule::def_function);
|
||||
let fun = DefineFunction::from(pair);
|
||||
let fun = DefineFunction::parse("def <McFly> marty").unwrap();
|
||||
assert!(fun.is_public());
|
||||
assert!(!fun.is_predicate());
|
||||
assert_eq!(fun.name(), "marty");
|
||||
|
@ -175,8 +175,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn with_arguments() {
|
||||
let pair = parse_str("def marty family: McFly, car: Delorean", Rule::def_function);
|
||||
let fun = DefineFunction::from(pair);
|
||||
let fun = DefineFunction::parse("def marty family: McFly, car: Delorean").unwrap();
|
||||
assert!(fun.is_public());
|
||||
assert!(!fun.is_predicate());
|
||||
assert_eq!(fun.name(), "marty");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::{argument_name::ArgumentName, expression::Expression, type_name::TypeName};
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::{Pair, Pairs};
|
||||
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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
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 value = pairs.next().unwrap();
|
||||
(ArgumentName::from(arg_name), Expression::from(value))
|
||||
})
|
||||
.collect()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn type_name_only() {
|
||||
let pair = parse_str("deftype Marty", Rule::def_module);
|
||||
let module = DefineModule::from(pair);
|
||||
let module = DefineModule::parse("deftype Marty").unwrap();
|
||||
assert!(module.is_type());
|
||||
assert_eq!(module.type_name().name(), "Marty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trait_name_only() {
|
||||
let pair = parse_str("deftrait Marty", Rule::def_module);
|
||||
let module = DefineModule::from(pair);
|
||||
let module = DefineModule::parse("deftrait Marty").unwrap();
|
||||
assert!(module.is_trait());
|
||||
assert_eq!(module.type_name().name(), "Marty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_name_only() {
|
||||
let pair = parse_str("defimpl Marty", Rule::def_module);
|
||||
let module = DefineModule::from(pair);
|
||||
let module = DefineModule::parse("defimpl Marty").unwrap();
|
||||
assert!(module.is_implementation());
|
||||
assert_eq!(module.type_name().name(), "Marty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_with_fields() {
|
||||
let pair = parse_str("deftype Delorean speed: Integer", Rule::def_module);
|
||||
let module = DefineModule::from(pair);
|
||||
let module = DefineModule::parse("deftype Delorean speed: Integer").unwrap();
|
||||
assert!(module.is_type());
|
||||
assert_eq!(module.type_name().name(), "Delorean");
|
||||
let (ref arg_name, ref arg_value) = module.fields()[0];
|
||||
|
|
|
@ -3,6 +3,7 @@ use ast::{
|
|||
unary::Unary,
|
||||
};
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -21,6 +22,10 @@ pub enum Inner<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::expression);
|
||||
|
@ -159,20 +164,17 @@ impl<'a> Expression<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn block() {
|
||||
let pair = parse_str("-> 123 end", Rule::expression);
|
||||
let expr = Expression::from(pair);
|
||||
let expr = Expression::parse("-> 123 end").unwrap();
|
||||
assert!(expr.is_block());
|
||||
assert_eq!(expr.block().unwrap().body().len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call() {
|
||||
let pair = parse_str("marty.mcfly()", Rule::expression);
|
||||
let expr = Expression::from(pair);
|
||||
let expr = Expression::parse("marty.mcfly()").unwrap();
|
||||
assert!(expr.is_call());
|
||||
assert_eq!(expr.call().unwrap().receiver().name(), "marty");
|
||||
assert_eq!(expr.call().unwrap().message().name(), "mcfly");
|
||||
|
@ -180,8 +182,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn infix() {
|
||||
let pair = parse_str("123 * 234", Rule::expression);
|
||||
let expr = Expression::from(pair);
|
||||
let expr = Expression::parse("123 * 234").unwrap();
|
||||
assert!(expr.is_infix());
|
||||
assert_eq!(
|
||||
expr.infix()
|
||||
|
@ -209,16 +210,14 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn literal() {
|
||||
let pair = parse_str("123", Rule::expression);
|
||||
let expr = Expression::from(pair);
|
||||
let expr = Expression::parse("123").unwrap();
|
||||
assert!(expr.is_literal());
|
||||
assert_eq!(expr.literal().unwrap().integer().unwrap().value(), 123);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unary() {
|
||||
let pair = parse_str("!123", Rule::expression);
|
||||
let expr = Expression::from(pair);
|
||||
let expr = Expression::parse("!123").unwrap();
|
||||
assert!(expr.is_unary());
|
||||
assert!(expr.unary().unwrap().op().is_logical_not());
|
||||
assert_eq!(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::define_module::DefineModule;
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -9,6 +10,10 @@ pub struct File<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::file);
|
||||
|
@ -32,12 +37,10 @@ impl<'a> File<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn file() {
|
||||
let pair = parse_str("deftype Marty", Rule::file);
|
||||
let file = File::from(pair);
|
||||
let file = File::parse("deftype Marty").unwrap();
|
||||
assert_eq!(file.modules().len(), 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
use std::str::FromStr;
|
||||
|
@ -9,6 +10,10 @@ pub struct Float<'a> {
|
|||
value: f64,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Float<'a> {
|
||||
const RULE: Rule = Rule::float;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Float<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::float);
|
||||
|
@ -33,19 +38,16 @@ impl<'a> Float<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn float_zero_zero() {
|
||||
let pair = parse_str("0.0", Rule::float);
|
||||
let flt = Float::from(pair);
|
||||
let flt = Float::parse("0.0").unwrap();
|
||||
assert_eq!(flt.value, 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_123_123() {
|
||||
let pair = parse_str("123.123", Rule::float);
|
||||
let flt = Float::from(pair);
|
||||
let flt = Float::parse("123.123").unwrap();
|
||||
assert_eq!(flt.value, 123.123);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -9,6 +10,10 @@ pub struct Integer<'a> {
|
|||
pub value: u64,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Integer<'a> {
|
||||
const RULE: Rule = Rule::integer;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Integer<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::integer);
|
||||
|
@ -50,44 +55,38 @@ impl<'a> Integer<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn integer_zero() {
|
||||
let pair = parse_str("0", Rule::integer);
|
||||
let int = Integer::from(pair);
|
||||
let int = Integer::parse("0").unwrap();
|
||||
assert_eq!(int.radix, 0);
|
||||
assert_eq!(int.value, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_binary() {
|
||||
let pair = parse_str("0b10101", Rule::integer);
|
||||
let int = Integer::from(pair);
|
||||
let int = Integer::parse("0b10101").unwrap();
|
||||
assert_eq!(int.radix, 2);
|
||||
assert_eq!(int.value, 21);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_octal() {
|
||||
let pair = parse_str("0o76543210", Rule::integer);
|
||||
let int = Integer::from(pair);
|
||||
let int = Integer::parse("0o76543210").unwrap();
|
||||
assert_eq!(int.radix, 8);
|
||||
assert_eq!(int.value, 16434824);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_decimal() {
|
||||
let pair = parse_str("9876543210", Rule::integer);
|
||||
let int = Integer::from(pair);
|
||||
let int = Integer::parse("9876543210").unwrap();
|
||||
assert_eq!(int.radix, 10);
|
||||
assert_eq!(int.value, 9876543210);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_hexadecimal() {
|
||||
let pair = parse_str("0xfEdCbA9876543210", Rule::integer);
|
||||
let int = Integer::from(pair);
|
||||
let int = Integer::parse("0xfEdCbA9876543210").unwrap();
|
||||
assert_eq!(int.radix, 16);
|
||||
assert_eq!(int.value, 18364758544493064720);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use ast::{
|
|||
type_name::TypeName, variable::Variable,
|
||||
};
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -28,6 +29,10 @@ pub enum Inner<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::literal);
|
||||
|
@ -231,92 +236,80 @@ impl<'a> Literal<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn array() {
|
||||
let pair = parse_str("[1, 2, 3]", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("[1, 2, 3]").unwrap();
|
||||
assert!(lit.is_array());
|
||||
assert_eq!(lit.array().unwrap().values().len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map() {
|
||||
let pair = parse_str("{a: 1, b: 2}", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("{a: 1, b: 2}").unwrap();
|
||||
assert!(lit.is_map());
|
||||
assert_eq!(lit.map().unwrap().values().len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn atom() {
|
||||
let pair = parse_str(":marty_mcfly", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse(":marty_mcfly").unwrap();
|
||||
assert!(lit.is_atom());
|
||||
assert_eq!(lit.atom().unwrap().name(), "marty_mcfly");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean() {
|
||||
let pair = parse_str("true", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("true").unwrap();
|
||||
assert!(lit.is_boolean());
|
||||
assert!(lit.boolean().unwrap().is_true());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constructor() {
|
||||
let pair = parse_str("Delorean { speed: 88 }", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("Delorean { speed: 88 }").unwrap();
|
||||
assert!(lit.is_constructor());
|
||||
assert_eq!(lit.constructor().unwrap().type_name().name(), "Delorean");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float() {
|
||||
let pair = parse_str("123.456", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("123.456").unwrap();
|
||||
assert!(lit.is_float());
|
||||
assert_eq!(lit.float().unwrap().value(), 123.456);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer() {
|
||||
let pair = parse_str("123", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("123").unwrap();
|
||||
assert!(lit.is_integer());
|
||||
assert_eq!(lit.integer().unwrap().value(), 123);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn property() {
|
||||
let pair = parse_str("@doc_brown", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("@doc_brown").unwrap();
|
||||
assert!(lit.is_property());
|
||||
assert_eq!(lit.property().unwrap().name(), "doc_brown");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string() {
|
||||
let pair = parse_str("\"Doc \\\"Emmet\\\" Brown\"", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("\"Doc \\\"Emmet\\\" Brown\"").unwrap();
|
||||
assert!(lit.is_string());
|
||||
assert_eq!(lit.string().unwrap().value(), "Doc \"Emmet\" Brown");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_name() {
|
||||
let pair = parse_str("MartyMcFly", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("MartyMcFly").unwrap();
|
||||
assert!(lit.is_type_name());
|
||||
assert_eq!(lit.type_name().unwrap().name(), "MartyMcFly");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variable() {
|
||||
let pair = parse_str("marty_mcfly", Rule::literal);
|
||||
let lit = Literal::from(pair);
|
||||
let lit = Literal::parse("marty_mcfly").unwrap();
|
||||
assert!(lit.is_variable());
|
||||
assert_eq!(lit.variable().unwrap().name(), "marty_mcfly");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::{atom::Atom, expression::Expression, literal::Literal};
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -16,6 +17,10 @@ pub struct MapPair<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::map);
|
||||
|
@ -71,12 +76,10 @@ impl<'a> Map<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn keyword_map() {
|
||||
let pair = parse_str("{a: 1, b: 2}", Rule::map);
|
||||
let map = Map::from(pair);
|
||||
let map = Map::parse("{a: 1, b: 2}").unwrap();
|
||||
|
||||
let map_pair = &map.values()[0];
|
||||
assert_eq!(
|
||||
|
@ -113,8 +116,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn expression_map() {
|
||||
let pair = parse_str("{ 1 : 2, 3 : 4 }", Rule::map);
|
||||
let map = Map::from(pair);
|
||||
let map = Map::parse("{ 1 : 2, 3 : 4 }").unwrap();
|
||||
|
||||
let map_pair = &map.values()[0];
|
||||
assert_eq!(
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Operator<'a> {
|
||||
pub span: Span<'a>,
|
||||
pub op: Op,
|
||||
span: Span<'a>,
|
||||
op: Op,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Operator<'a> {
|
||||
const RULE: Rule = Rule::all_operators;
|
||||
}
|
||||
|
||||
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 {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
match pair.as_rule() {
|
||||
Rule::multiply => Op::Multiply,
|
||||
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::assign => Op::Assign,
|
||||
Rule::bitwise_and => Op::BitwiseAnd,
|
||||
Rule::bitwise_or => Op::BitwiseOr,
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -223,256 +228,131 @@ impl<'a> From<Pair<'a, Rule>> for Op {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::{parse_str, Rule};
|
||||
|
||||
mod operator {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn multiply() {
|
||||
let result = parse_str("*", Rule::all_operators);
|
||||
assert_eq!(Op::Multiply, Operator::from(result).op)
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn bitwise_and() {
|
||||
let result = parse_str("&", Rule::all_operators);
|
||||
assert_eq!(Op::BitwiseAnd, Operator::from(result).op);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitwise_or() {
|
||||
let result = parse_str("|", Rule::all_operators);
|
||||
assert_eq!(Op::BitwiseOr, Operator::from(result).op);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitwise_xor() {
|
||||
let result = parse_str("^", Rule::all_operators);
|
||||
assert_eq!(Op::BitwiseXor, Operator::from(result).op);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign() {
|
||||
let result = parse_str("=", Rule::all_operators);
|
||||
assert_eq!(Op::Assign, Operator::from(result).op);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign() {
|
||||
let op = Operator::parse("=").unwrap();
|
||||
assert!(op.is_assign());
|
||||
}
|
||||
|
||||
mod op {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn bitwise_and() {
|
||||
let op = Operator::parse("&").unwrap();
|
||||
assert!(op.is_bitwise_and());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiply() {
|
||||
let result = parse_str("*", Rule::all_operators);
|
||||
assert_eq!(Op::Multiply, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn bitwise_or() {
|
||||
let op = Operator::parse("|").unwrap();
|
||||
assert!(op.is_bitwise_or());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn divide() {
|
||||
let result = parse_str("/", Rule::all_operators);
|
||||
assert_eq!(Op::Divide, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn bitwise_xor() {
|
||||
let op = Operator::parse("^").unwrap();
|
||||
assert!(op.is_bitwise_xor());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn modulus() {
|
||||
let result = parse_str("%", Rule::all_operators);
|
||||
assert_eq!(Op::Modulo, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn divide() {
|
||||
let op = Operator::parse("/").unwrap();
|
||||
assert!(op.is_divide());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plus() {
|
||||
let result = parse_str("+", Rule::all_operators);
|
||||
assert_eq!(Op::Plus, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn equal() {
|
||||
let op = Operator::parse("==").unwrap();
|
||||
assert!(op.is_equal());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minus() {
|
||||
let result = parse_str("-", Rule::all_operators);
|
||||
assert_eq!(Op::Minus, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn exponent() {
|
||||
let op = Operator::parse("**").unwrap();
|
||||
assert!(op.is_exponent());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shift_left() {
|
||||
let result = parse_str("<<", Rule::all_operators);
|
||||
assert_eq!(Op::ShiftLeft, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn greater_than() {
|
||||
let op = Operator::parse(">").unwrap();
|
||||
assert!(op.is_greater_than());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shift_right() {
|
||||
let result = parse_str(">>", Rule::all_operators);
|
||||
assert_eq!(Op::ShiftRight, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn greater_than_or_equal() {
|
||||
let op = Operator::parse(">=").unwrap();
|
||||
assert!(op.is_greater_than_or_equal());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn less_than() {
|
||||
let result = parse_str("<", Rule::all_operators);
|
||||
assert_eq!(Op::LessThan, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn less_than() {
|
||||
let op = Operator::parse("<").unwrap();
|
||||
assert!(op.is_less_than());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn less_than_or_equal() {
|
||||
let result = parse_str("<=", Rule::all_operators);
|
||||
assert_eq!(Op::LessThanOrEqual, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn less_than_or_equal() {
|
||||
let op = Operator::parse("<=").unwrap();
|
||||
assert!(op.is_less_than_or_equal());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn greater_than() {
|
||||
let result = parse_str(">", Rule::all_operators);
|
||||
assert_eq!(Op::GreaterThan, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn logical_and() {
|
||||
let op = Operator::parse("&&").unwrap();
|
||||
assert!(op.is_logical_and());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn greater_than_or_equal() {
|
||||
let result = parse_str(">=", Rule::all_operators);
|
||||
assert_eq!(Op::GreaterThanOrEqual, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn logical_not() {
|
||||
let op = Operator::parse("!").unwrap();
|
||||
assert!(op.is_logical_not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_equal() {
|
||||
let result = parse_str("!=", Rule::all_operators);
|
||||
assert_eq!(Op::NotEqual, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn logical_or() {
|
||||
let op = Operator::parse("||").unwrap();
|
||||
assert!(op.is_logical_or());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn equal() {
|
||||
let result = parse_str("==", Rule::all_operators);
|
||||
assert_eq!(Op::Equal, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn minus() {
|
||||
let op = Operator::parse("-").unwrap();
|
||||
assert!(op.is_minus());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn logical_and() {
|
||||
let result = parse_str("&&", Rule::all_operators);
|
||||
assert_eq!(Op::LogicalAnd, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn modulus() {
|
||||
let op = Operator::parse("%").unwrap();
|
||||
assert!(op.is_modulo());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn logical_or() {
|
||||
let result = parse_str("||", Rule::all_operators);
|
||||
assert_eq!(Op::LogicalOr, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn multiply() {
|
||||
let op = Operator::parse("*").unwrap();
|
||||
assert!(op.is_multiply());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn logical_not() {
|
||||
let result = parse_str("!", Rule::all_operators);
|
||||
assert_eq!(Op::LogicalNot, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn not_equal() {
|
||||
let op = Operator::parse("!=").unwrap();
|
||||
assert!(op.is_not_equal());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitwise_and() {
|
||||
let result = parse_str("&", Rule::all_operators);
|
||||
assert_eq!(Op::BitwiseAnd, Op::from(result));
|
||||
}
|
||||
#[test]
|
||||
fn plus() {
|
||||
let op = Operator::parse("+").unwrap();
|
||||
assert!(op.is_plus());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitwise_or() {
|
||||
let result = parse_str("|", Rule::all_operators);
|
||||
assert_eq!(Op::BitwiseOr, Op::from(result));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitwise_xor() {
|
||||
let result = parse_str("^", Rule::all_operators);
|
||||
assert_eq!(Op::BitwiseXor, Op::from(result));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign() {
|
||||
let result = parse_str("=", Rule::all_operators);
|
||||
assert_eq!(Op::Assign, Op::from(result));
|
||||
}
|
||||
#[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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,12 +43,11 @@ pub fn climb<'a>(pair: Pair<'a, Rule>) -> Expression<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
use parse::Parse;
|
||||
|
||||
#[test]
|
||||
fn precedence_test() {
|
||||
let result = parse_str("10 * 20 + 30", Rule::expression_test);
|
||||
let expr = Expression::from(result);
|
||||
let expr = Expression::parse("10 * 20 + 30").unwrap();
|
||||
let infix0 = expr.infix().unwrap();
|
||||
assert!(infix0.op().is_plus());
|
||||
assert_eq!(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -8,6 +9,10 @@ pub struct Property<'a> {
|
|||
name: String,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Property<'a> {
|
||||
const RULE: Rule = Rule::property;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Property<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::property);
|
||||
|
@ -37,13 +42,10 @@ impl<'a> Property<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn property() {
|
||||
let pair = parse_str("@marty_mcfly", Rule::property);
|
||||
let property = Property::from(pair);
|
||||
|
||||
let property = Property::parse("@marty_mcfly").unwrap();
|
||||
assert_eq!(property.name(), "marty_mcfly");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
use regex::{Captures, Regex};
|
||||
|
@ -14,6 +15,10 @@ pub struct StringLiteral<'a> {
|
|||
value: String,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for StringLiteral<'a> {
|
||||
const RULE: Rule = Rule::string;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for StringLiteral<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::string);
|
||||
|
@ -60,91 +65,70 @@ impl<'a> StringLiteral<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
let pair = parse_str(r#""hello world""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""hello world""#).unwrap();
|
||||
assert_eq!(value.value(), "hello world");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vartical_tab_escape() {
|
||||
let pair = parse_str(r#""\v""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""\v""#).unwrap();
|
||||
assert_eq!(value.value(), "\u{000b}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tab_escape() {
|
||||
let pair = parse_str(r#""\t""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""\t""#).unwrap();
|
||||
assert_eq!(value.value(), "\t");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn carriage_return_escape() {
|
||||
let pair = parse_str(r#""\r""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""\r""#).unwrap();
|
||||
assert_eq!(value.value(), "\r");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newline_escape() {
|
||||
let pair = parse_str(r#""\n""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""\n""#).unwrap();
|
||||
assert_eq!(value.value(), "\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formfeed_escape() {
|
||||
let pair = parse_str(r#""\f""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""\f""#).unwrap();
|
||||
assert_eq!(value.value(), "\u{000c}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backspace_escape() {
|
||||
let pair = parse_str(r#""\b""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""\b""#).unwrap();
|
||||
assert_eq!(value.value(), "\u{0008}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alert_escape() {
|
||||
let pair = parse_str(r#""\a""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""\a""#).unwrap();
|
||||
assert_eq!(value.value(), "\u{0007}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unicode_escape() {
|
||||
let pair = parse_str(r#""\u26f5""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
|
||||
let value = StringLiteral::parse(r#""\u26f5""#).unwrap();
|
||||
assert_eq!(value.value(), "\u{26f5}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backslash_escape() {
|
||||
let pair = parse_str(r#""\\""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
let value = StringLiteral::parse(r#""\\""#).unwrap();
|
||||
assert_eq!(value.value(), "\\");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doublequote_escape() {
|
||||
let pair = parse_str(r#""\""""#, Rule::string);
|
||||
let value = StringLiteral::from(pair);
|
||||
let value = StringLiteral::parse(r#""\""""#).unwrap();
|
||||
assert_eq!(value.value(), r#"""#);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -8,6 +9,10 @@ pub struct TypeName<'a> {
|
|||
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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::type_name);
|
||||
|
@ -30,12 +35,10 @@ impl<'a> TypeName<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn name() {
|
||||
let pair = parse_str("DocBrown", Rule::type_name);
|
||||
let type_name = TypeName::from(pair);
|
||||
let type_name = TypeName::parse("DocBrown").unwrap();
|
||||
assert_eq!(type_name.name(), "DocBrown");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ast::{expression::Expression, operator::Operator};
|
||||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -10,6 +11,10 @@ pub struct Unary<'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> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::unary);
|
||||
|
@ -41,12 +46,10 @@ impl<'a> Unary<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn unary() {
|
||||
let result = parse_str("!123", Rule::unary);
|
||||
let unary = Unary::from(result);
|
||||
let unary = Unary::parse("!123").unwrap();
|
||||
|
||||
assert!(unary.op().is_logical_not());
|
||||
assert_eq!(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use grammar::Rule;
|
||||
use parse::Parse;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Span;
|
||||
|
||||
|
@ -8,6 +9,10 @@ pub struct Variable<'a> {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Variable<'a> {
|
||||
const RULE: Rule = Rule::variable;
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Variable<'a> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
assert_eq!(pair.as_rule(), Rule::variable);
|
||||
|
@ -30,13 +35,10 @@ impl<'a> Variable<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use grammar::parse_str;
|
||||
|
||||
#[test]
|
||||
fn variable() {
|
||||
let pair = parse_str("marty_mcfly", Rule::variable);
|
||||
let variable = Variable::from(pair);
|
||||
|
||||
let variable = Variable::parse("marty_mcfly").unwrap();
|
||||
assert_eq!(variable.name(), "marty_mcfly");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ boolean_false = @{ keyword_false }
|
|||
boolean_true = @{ keyword_true }
|
||||
braced = !{ "(" ~ newline* ~ expression ~ newline* ~ ")" }
|
||||
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 }
|
||||
unary = ${ unary_operator ~ expression }
|
||||
variable = @{ identifier }
|
||||
|
@ -87,7 +87,7 @@ keyword_false = { "false" }
|
|||
|
||||
identifier_test = _{ soi ~ identifier ~ eoi }
|
||||
identifier = @{ !keyword ~ identifier_head ~ identifier_tail? }
|
||||
identifier_head = @{ 'a'..'z' | "_" }
|
||||
identifier_head = @{ 'A'..'Z' | 'a'..'z' | "_" }
|
||||
identifier_tail = @{ ('a'..'z' | 'A'..'Z' | "_" | '0'..'9')+ }
|
||||
type_name = @{ !keyword ~ type_name_head ~ type_name_tail? }
|
||||
type_name_head = @{ 'A'..'Z' }
|
||||
|
|
|
@ -6,16 +6,3 @@ pub struct Grammar;
|
|||
|
||||
#[cfg(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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use super::assert_parses_expression;
|
||||
use grammar::{Grammar, Rule};
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use grammar::{Grammar, Rule};
|
||||
// use grammar::{Grammar, Rule};
|
||||
|
||||
// #[test]
|
||||
// fn binary_operators() {
|
||||
|
|
|
@ -16,4 +16,8 @@ mod parse;
|
|||
|
||||
pub use ast::*;
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
use ast::File;
|
||||
use error::ParseError;
|
||||
use grammar::{Grammar, Rule};
|
||||
use pest::{iterators::Pair, Parser};
|
||||
|
||||
pub fn parse_file<'a>(source: &'a str) -> Result<File<'a>, ParseError<'a>> {
|
||||
run_parser(source, Rule::file).and_then(|p| Ok(File::from(p)))
|
||||
}
|
||||
pub trait Parse<'a, Node = Self>
|
||||
where
|
||||
Node: From<Pair<'a, Rule>>,
|
||||
{
|
||||
const RULE: Rule;
|
||||
|
||||
fn run_parser<'a>(source: &'a str, rule: Rule) -> Result<Pair<'a, Rule>, ParseError<'a>> {
|
||||
let result = Grammar::parse(rule, source);
|
||||
match result {
|
||||
Ok(mut pairs) => Ok(pairs.next().unwrap()),
|
||||
Err(pest_error) => Err(ParseError::from(pest_error)),
|
||||
fn parse(source: &'a str) -> Result<Node, ParseError<'a>> {
|
||||
let result = Grammar::parse(Self::RULE, source);
|
||||
match result {
|
||||
Ok(mut pairs) => Ok(Node::from(pairs.next().unwrap())),
|
||||
Err(pest_error) => Err(ParseError::from(pest_error)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue