Add the Parse trait and make AST nodes know how to parse themselves.

This commit is contained in:
James Harton 2018-09-15 17:23:34 +12:00
parent 4b77a2438e
commit 35be079513
30 changed files with 329 additions and 451 deletions

View file

@ -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");
}
}

View file

@ -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;

View file

@ -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");
}
}

View file

@ -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?");
}
}

View file

@ -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());
}

View file

@ -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);

View file

@ -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");
}
}

View file

@ -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");
}
}

View file

@ -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");

View file

@ -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");

View file

@ -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];

View file

@ -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!(

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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");
}

View file

@ -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!(

View file

@ -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);
fn assign() {
let op = Operator::parse("=").unwrap();
assert!(op.is_assign());
}
#[test]
fn bitwise_and() {
let result = parse_str("&", Rule::all_operators);
assert_eq!(Op::BitwiseAnd, Operator::from(result).op);
let op = Operator::parse("&").unwrap();
assert!(op.is_bitwise_and());
}
#[test]
fn bitwise_or() {
let result = parse_str("|", Rule::all_operators);
assert_eq!(Op::BitwiseOr, Operator::from(result).op);
let op = Operator::parse("|").unwrap();
assert!(op.is_bitwise_or());
}
#[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);
}
}
mod op {
use super::*;
#[test]
fn multiply() {
let result = parse_str("*", Rule::all_operators);
assert_eq!(Op::Multiply, Op::from(result));
let op = Operator::parse("^").unwrap();
assert!(op.is_bitwise_xor());
}
#[test]
fn divide() {
let result = parse_str("/", Rule::all_operators);
assert_eq!(Op::Divide, Op::from(result));
}
#[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));
let op = Operator::parse("/").unwrap();
assert!(op.is_divide());
}
#[test]
fn equal() {
let result = parse_str("==", Rule::all_operators);
assert_eq!(Op::Equal, Op::from(result));
let op = Operator::parse("==").unwrap();
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]
fn logical_and() {
let result = parse_str("&&", Rule::all_operators);
assert_eq!(Op::LogicalAnd, Op::from(result));
}
#[test]
fn logical_or() {
let result = parse_str("||", Rule::all_operators);
assert_eq!(Op::LogicalOr, Op::from(result));
let op = Operator::parse("&&").unwrap();
assert!(op.is_logical_and());
}
#[test]
fn logical_not() {
let result = parse_str("!", Rule::all_operators);
assert_eq!(Op::LogicalNot, Op::from(result));
let op = Operator::parse("!").unwrap();
assert!(op.is_logical_not());
}
#[test]
fn bitwise_and() {
let result = parse_str("&", Rule::all_operators);
assert_eq!(Op::BitwiseAnd, Op::from(result));
fn logical_or() {
let op = Operator::parse("||").unwrap();
assert!(op.is_logical_or());
}
#[test]
fn bitwise_or() {
let result = parse_str("|", Rule::all_operators);
assert_eq!(Op::BitwiseOr, Op::from(result));
fn minus() {
let op = Operator::parse("-").unwrap();
assert!(op.is_minus());
}
#[test]
fn bitwise_xor() {
let result = parse_str("^", Rule::all_operators);
assert_eq!(Op::BitwiseXor, Op::from(result));
fn modulus() {
let op = Operator::parse("%").unwrap();
assert!(op.is_modulo());
}
#[test]
fn assign() {
let result = parse_str("=", Rule::all_operators);
assert_eq!(Op::Assign, Op::from(result));
}
fn multiply() {
let op = Operator::parse("*").unwrap();
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)]
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!(

View file

@ -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");
}
}

View file

@ -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#"""#);
}
}

View file

@ -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");
}
}

View file

@ -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!(

View file

@ -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");
}
}

View file

@ -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' }

View file

@ -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()
}
}

View file

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

View file

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

View file

@ -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)
}

View file

@ -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);
fn parse(source: &'a str) -> Result<Node, ParseError<'a>> {
let result = Grammar::parse(Self::RULE, source);
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)),
}
}
}