2018-05-22 18:02:44 -05:00
|
|
|
// Copyright 2017 Jeremy Wall <jeremy@marzhillstudios.com>
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
//! The Parsing stage of the ucg compiler.
|
2018-11-05 21:34:12 -06:00
|
|
|
use std;
|
2018-05-22 18:02:44 -05:00
|
|
|
use std::borrow::Borrow;
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
use abortable_parser;
|
|
|
|
use abortable_parser::combinators::eoi;
|
|
|
|
use abortable_parser::iter::SliceIter;
|
|
|
|
use abortable_parser::{Error, Peekable, Result};
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-07-04 12:30:29 -05:00
|
|
|
use self::precedence::op_expression;
|
2018-12-06 12:23:52 -06:00
|
|
|
use crate::ast::*;
|
|
|
|
use crate::error::StackPrinter;
|
|
|
|
use crate::iter::OffsetStrIter;
|
|
|
|
use crate::tokenizer::*;
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
// TODO(jwall): Rename this to something better.
|
|
|
|
type NomResult<'a, O> = Result<SliceIter<'a, Token>, O>;
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-07-02 18:30:17 -05:00
|
|
|
#[cfg(feature = "tracing")]
|
|
|
|
const ENABLE_TRACE: bool = true;
|
|
|
|
#[cfg(not(feature = "tracing"))]
|
|
|
|
const ENABLE_TRACE: bool = false;
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
type ParseResult<'a, O> = std::result::Result<O, abortable_parser::Error<SliceIter<'a, Token>>>;
|
2018-08-30 21:00:28 -05:00
|
|
|
|
2018-07-02 18:30:17 -05:00
|
|
|
macro_rules! trace_nom {
|
|
|
|
($i:expr, $rule:ident!( $($args:tt)* )) => {
|
|
|
|
{
|
2018-12-06 12:23:52 -06:00
|
|
|
use crate::parse::ENABLE_TRACE;
|
2018-07-02 18:30:17 -05:00
|
|
|
if ENABLE_TRACE {
|
|
|
|
eprintln!("Entering Rule: {:?} {:?}", stringify!($rule), $i);
|
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
let result = $rule!($i, $($args)* );
|
2018-07-02 18:30:17 -05:00
|
|
|
if ENABLE_TRACE {
|
2018-08-21 23:05:06 -05:00
|
|
|
eprintln!("Exiting Rule: {:?} with {:?}", stringify!($rule), result);
|
2018-07-02 18:30:17 -05:00
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|
|
|
|
};
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-07-02 18:30:17 -05:00
|
|
|
($i:expr, $rule:ident) => {
|
|
|
|
{
|
2018-12-06 12:23:52 -06:00
|
|
|
use crate::parse::ENABLE_TRACE;
|
2018-07-02 18:30:17 -05:00
|
|
|
if ENABLE_TRACE {
|
|
|
|
eprintln!("Entering Rule: {:?} {:?}", stringify!($rule), $i);
|
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
let result = run!($i, $rule);
|
2018-07-02 18:30:17 -05:00
|
|
|
if ENABLE_TRACE {
|
2018-08-21 23:05:06 -05:00
|
|
|
eprintln!("Exiting Rule: {:?} with {:?}", stringify!($rule), result);
|
2018-07-02 18:30:17 -05:00
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2018-07-14 22:56:47 -05:00
|
|
|
|
2018-05-22 18:02:44 -05:00
|
|
|
fn symbol_to_value(s: &Token) -> ParseResult<Value> {
|
|
|
|
Ok(Value::Symbol(value_node!(
|
|
|
|
s.fragment.to_string(),
|
|
|
|
s.pos.clone()
|
|
|
|
)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// symbol is a bare unquoted field.
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
symbol<SliceIter<Token>, Value>,
|
2018-05-22 18:02:44 -05:00
|
|
|
match_type!(BAREWORD => symbol_to_value)
|
|
|
|
);
|
|
|
|
|
|
|
|
fn str_to_value(s: &Token) -> ParseResult<Value> {
|
2018-06-10 14:13:08 -05:00
|
|
|
Ok(Value::Str(value_node!(
|
2018-05-22 18:02:44 -05:00
|
|
|
s.fragment.to_string(),
|
|
|
|
s.pos.clone()
|
|
|
|
)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// quoted_value is a quoted string.
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
quoted_value<SliceIter<Token>, Value>,
|
|
|
|
match_type!(STR => str_to_value)
|
2018-05-22 18:02:44 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
// Helper function to make the return types work for down below.
|
2018-11-05 21:34:12 -06:00
|
|
|
fn triple_to_number<'a>(
|
|
|
|
input: SliceIter<'a, Token>,
|
|
|
|
v: (Option<Token>, Option<Token>, Option<Token>),
|
|
|
|
) -> ParseResult<'a, Value> {
|
2018-05-22 18:02:44 -05:00
|
|
|
let (pref, mut pref_pos) = match v.0 {
|
2018-11-05 21:34:12 -06:00
|
|
|
None => ("", Position::new(0, 0, 0)),
|
2018-05-22 18:02:44 -05:00
|
|
|
Some(ref bs) => (bs.fragment.borrow(), bs.pos.clone()),
|
|
|
|
};
|
|
|
|
|
|
|
|
let has_dot = v.1.is_some();
|
|
|
|
|
|
|
|
if v.0.is_some() && !has_dot && v.2.is_none() {
|
|
|
|
let i = match FromStr::from_str(pref) {
|
|
|
|
Ok(i) => i,
|
|
|
|
Err(_) => {
|
2018-11-05 21:34:12 -06:00
|
|
|
return Err(Error::new(
|
2018-05-22 18:02:44 -05:00
|
|
|
format!("Not an integer! {}", pref),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(input.clone()),
|
|
|
|
));
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
return Ok(Value::Int(value_node!(i, pref_pos)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if v.0.is_none() && has_dot {
|
|
|
|
pref_pos = v.1.unwrap().pos;
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
let suf = match v.2 {
|
|
|
|
None => "".to_string(),
|
|
|
|
Some(bs) => bs.fragment,
|
2018-05-22 18:02:44 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
let to_parse = pref.to_string() + "." + &suf;
|
|
|
|
let f = match FromStr::from_str(&to_parse) {
|
|
|
|
Ok(f) => f,
|
|
|
|
Err(_) => {
|
2018-11-05 21:34:12 -06:00
|
|
|
return Err(Error::new(
|
2018-05-22 18:02:44 -05:00
|
|
|
format!("Not a float! {}", to_parse),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(input.clone()),
|
2018-08-17 10:31:45 -05:00
|
|
|
));
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
return Ok(Value::Float(value_node!(f, pref_pos)));
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
// FIXME(jwall): This should actually be unnecessary now.
|
|
|
|
|
2018-07-14 22:56:47 -05:00
|
|
|
/// alt_peek conditionally runs a combinator if a lookahead combinator matches.
|
2018-06-04 20:48:56 -05:00
|
|
|
macro_rules! alt_peek {
|
|
|
|
(__inner $i:expr, $peekrule:ident!( $($peekargs:tt)* ) => $parserule:ident | $($rest:tt)* ) => (
|
2018-11-05 21:34:12 -06:00
|
|
|
alt_peek!(__inner $i, $peekrule!($($peekargs)*) => run!($parserule) | $($rest)* )
|
2018-06-04 20:48:56 -05:00
|
|
|
);
|
2018-06-20 17:20:30 -04:00
|
|
|
|
2018-06-04 20:48:56 -05:00
|
|
|
(__inner $i:expr, $peekrule:ident => $($rest:tt)* ) => (
|
2018-11-05 21:34:12 -06:00
|
|
|
alt_peek!(__inner $i, run!($peekrule) => $($rest)* )
|
2018-06-04 20:48:56 -05:00
|
|
|
);
|
2018-06-20 17:20:30 -04:00
|
|
|
|
2018-06-04 20:48:56 -05:00
|
|
|
(__inner $i:expr, $peekrule:ident!( $($peekargs:tt)* ) => $parserule:ident!( $($parseargs:tt)* ) | $($rest:tt)* ) => (
|
|
|
|
{
|
|
|
|
let _i = $i.clone();
|
|
|
|
let pre_res = peek!(_i, $peekrule!($($peekargs)*));
|
|
|
|
match pre_res {
|
|
|
|
// if the peek was incomplete then it might still match so return incomplete.
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Incomplete(i) => Result::Incomplete(i),
|
2018-06-04 20:48:56 -05:00
|
|
|
// If the peek was in error then try the next peek => parse pair.
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Fail(_) => {
|
2018-06-20 17:20:30 -04:00
|
|
|
alt_peek!(__inner $i, $($rest)*)
|
2018-06-04 20:48:56 -05:00
|
|
|
},
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Abort(e) => Result::Abort(e),
|
2018-06-04 20:48:56 -05:00
|
|
|
// If the peek was successful then return the result of the parserule
|
|
|
|
// regardless of it's result.
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Complete(_i, _) => {
|
2018-06-04 20:48:56 -05:00
|
|
|
$parserule!(_i, $($parseargs)*)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2018-06-06 20:38:23 -05:00
|
|
|
|
2018-06-10 13:51:19 -05:00
|
|
|
// These are our no fallback termination cases.
|
|
|
|
(__inner $i:expr, $peekrule:ident!( $($peekargs:tt)* ) => $parserule:ident, __end ) => (
|
|
|
|
alt_peek!(__inner $i, $peekrule!($($peekargs)*) => call!($parserule), __end )
|
|
|
|
);
|
2018-06-20 17:20:30 -04:00
|
|
|
|
2018-06-10 13:51:19 -05:00
|
|
|
(__inner $i:expr, $peekrule:ident!( $($peekargs:tt)* ) => $parserule:ident!( $($parseargs:tt)* ), __end ) => (
|
|
|
|
{
|
|
|
|
let _i = $i.clone();
|
|
|
|
let pre_res = peek!(_i, $peekrule!($($peekargs)*));
|
|
|
|
match pre_res {
|
|
|
|
// if the peek was incomplete then it might still match so return incomplete.
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Incomplete(i) => Result::Incomplete(i),
|
2018-06-10 13:51:19 -05:00
|
|
|
// If the peek was in error then try the next peek => parse pair.
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Fail(_) => {
|
2018-06-20 17:20:30 -04:00
|
|
|
alt_peek!(__inner $i, __end)
|
2018-06-10 13:51:19 -05:00
|
|
|
},
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Abort(e) => Result::Abort(e),
|
2018-06-10 13:51:19 -05:00
|
|
|
// If the peek was successful then return the result of the parserule
|
|
|
|
// regardless of it's result.
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Complete(_i, _) => {
|
2018-06-10 13:51:19 -05:00
|
|
|
$parserule!(_i, $($parseargs)*)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2018-06-04 20:48:56 -05:00
|
|
|
// These are our fallback termination cases.
|
|
|
|
(__inner $i:expr, $fallback:ident, __end) => (
|
|
|
|
{
|
|
|
|
let _i = $i.clone();
|
2018-11-05 21:34:12 -06:00
|
|
|
run!(_i, $fallback)
|
2018-06-04 20:48:56 -05:00
|
|
|
}
|
|
|
|
);
|
|
|
|
// In the case of a fallback rule with no peek we just return whatever
|
|
|
|
// the fallback rule returns.
|
|
|
|
(__inner $i:expr, $fallback:ident!( $($args:tt)* ), __end) => (
|
|
|
|
{
|
|
|
|
let _i = $i.clone();
|
2018-06-25 15:30:02 -04:00
|
|
|
$fallback!(_i, $($args)*)
|
2018-06-04 20:48:56 -05:00
|
|
|
}
|
|
|
|
);
|
2018-06-06 20:38:23 -05:00
|
|
|
|
2018-06-04 20:48:56 -05:00
|
|
|
// This is our default termination case.
|
|
|
|
// If there is no fallback then we return an Error.
|
|
|
|
(__inner $i:expr, __end) => {
|
2018-11-05 21:34:12 -06:00
|
|
|
compile_error!("alt_peek! requirs a fallback case");
|
2018-06-04 20:48:56 -05:00
|
|
|
};
|
2018-06-06 20:38:23 -05:00
|
|
|
|
2018-06-04 20:48:56 -05:00
|
|
|
// alt_peek entry_point.
|
|
|
|
($i:expr, $($rest:tt)*) => {
|
|
|
|
// We use __end to define the termination token the recursive rule should consume.
|
|
|
|
alt_peek!(__inner $i, $($rest)*, __end)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-05-22 18:02:44 -05:00
|
|
|
// trace_macros!(true);
|
|
|
|
|
|
|
|
// NOTE(jwall): HERE THERE BE DRAGONS. The order for these matters
|
|
|
|
// alot. We need to process alternatives in order of decreasing
|
|
|
|
// specificity. Unfortunately this means we are required to go in a
|
2018-11-05 21:34:12 -06:00
|
|
|
// decreasing size order which messes with either!'s completion logic. To
|
2018-05-22 18:02:44 -05:00
|
|
|
// work around this we have to force Incomplete to be Error so that
|
2018-11-05 21:34:12 -06:00
|
|
|
// either! will try the next in the series instead of aborting.
|
2018-05-22 18:02:44 -05:00
|
|
|
//
|
|
|
|
// *IMPORTANT*
|
|
|
|
// It also means this combinator is risky when used with partial
|
|
|
|
// inputs. So handle with care.
|
2018-11-05 21:34:12 -06:00
|
|
|
fn number(input: SliceIter<Token>) -> Result<SliceIter<Token>, Value> {
|
|
|
|
let parsed = do_each!(input,
|
2018-12-10 21:27:44 -06:00
|
|
|
num => either!(
|
|
|
|
complete!(
|
|
|
|
"Not a float",
|
|
|
|
do_each!( // 1.0
|
|
|
|
prefix => match_type!(DIGIT),
|
|
|
|
has_dot => punct!("."),
|
|
|
|
suffix => match_type!(DIGIT),
|
|
|
|
(Some(prefix.clone()), Some(has_dot.clone()), Some(suffix.clone()))
|
|
|
|
)),
|
|
|
|
complete!(
|
|
|
|
"Not a float",
|
|
|
|
do_each!( // 1.
|
|
|
|
prefix => match_type!(DIGIT),
|
|
|
|
has_dot => punct!("."),
|
|
|
|
(Some(prefix.clone()), Some(has_dot.clone()), None)
|
|
|
|
)),
|
|
|
|
complete!(
|
|
|
|
"Not a float",
|
|
|
|
do_each!( // .1
|
|
|
|
has_dot => punct!("."),
|
|
|
|
suffix => match_type!(DIGIT),
|
|
|
|
(None, Some(has_dot.clone()), Some(suffix.clone()))
|
|
|
|
)),
|
|
|
|
do_each!( // 1
|
|
|
|
prefix => match_type!(DIGIT),
|
|
|
|
(Some(prefix.clone()), None, None)
|
|
|
|
)),
|
|
|
|
(num)
|
|
|
|
);
|
2018-11-05 21:34:12 -06:00
|
|
|
match parsed {
|
|
|
|
Result::Abort(e) => Result::Abort(e),
|
|
|
|
Result::Fail(e) => Result::Fail(e),
|
|
|
|
Result::Incomplete(offset) => Result::Incomplete(offset),
|
|
|
|
Result::Complete(rest, triple) => {
|
|
|
|
let num = triple_to_number(rest.clone(), triple);
|
|
|
|
match num {
|
|
|
|
Ok(val) => Result::Complete(rest, val),
|
|
|
|
Err(e) => Result::Fail(e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-22 18:02:44 -05:00
|
|
|
// trace_macros!(false);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
boolean_value<SliceIter<Token>, Value>,
|
|
|
|
do_each!(
|
|
|
|
b => match_type!(BOOLEAN),
|
|
|
|
(Value::Boolean(PositionedItem{
|
2018-05-22 18:02:44 -05:00
|
|
|
val: b.fragment == "true",
|
|
|
|
pos: b.pos,
|
|
|
|
}))
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
field_value<SliceIter<Token>, (Token, Expression)>,
|
|
|
|
do_each!(
|
2018-11-26 23:03:11 -06:00
|
|
|
field => wrap_err!(either!(match_type!(BOOLEAN), match_type!(BAREWORD), match_type!(STR)),
|
2018-11-05 21:34:12 -06:00
|
|
|
"Field names must be a bareword or a string."),
|
|
|
|
_ => punct!("="),
|
|
|
|
value => expression,
|
2018-05-22 18:02:44 -05:00
|
|
|
(field, value)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
// Helper function to make the return types work for down below.
|
2018-11-05 21:34:12 -06:00
|
|
|
fn vec_to_tuple(pos: Position, fields: Option<FieldList>) -> Value {
|
|
|
|
Value::Tuple(value_node!(fields.unwrap_or(Vec::new()), pos))
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
field_list<SliceIter<Token>, FieldList>,
|
|
|
|
separated!(punct!(","), field_value)
|
2018-05-22 18:02:44 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
tuple<SliceIter<Token>, Value>,
|
|
|
|
do_each!(
|
|
|
|
pos => pos,
|
|
|
|
_ => punct!("{"),
|
|
|
|
v => optional!(field_list),
|
|
|
|
_ => optional!(punct!(",")),
|
|
|
|
_ => punct!("}"),
|
|
|
|
(vec_to_tuple(pos, v))
|
2018-05-22 18:02:44 -05:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-11-21 20:41:54 -06:00
|
|
|
fn tuple_to_list<Sp: Into<Position>>(pos: Sp, elems: Option<Vec<Expression>>) -> Value {
|
2018-11-05 21:34:12 -06:00
|
|
|
Value::List(ListDef {
|
2018-11-21 20:41:54 -06:00
|
|
|
elems: elems.unwrap_or_else(|| Vec::new()),
|
2018-11-05 21:34:12 -06:00
|
|
|
pos: pos.into(),
|
|
|
|
})
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
list_value<SliceIter<Token>, Value>,
|
|
|
|
do_each!(
|
|
|
|
start => punct!("["),
|
2018-11-21 20:41:54 -06:00
|
|
|
elements => optional!(separated!(punct!(","), expression)),
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => optional!(punct!(",")), // nom's opt! macro doesn't preserve error types properly but this one does.
|
|
|
|
_ => punct!("]"),
|
|
|
|
(tuple_to_list(start.pos, elements))
|
|
|
|
)
|
2018-05-22 18:02:44 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
empty_value<SliceIter<Token>, Value>,
|
|
|
|
do_each!(
|
|
|
|
pos => pos,
|
|
|
|
_ => match_type!(EMPTY),
|
|
|
|
(Value::Empty(pos.into()))
|
2018-05-22 18:02:44 -05:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
compound_value<SliceIter<Token>, Value>,
|
|
|
|
either!(trace_nom!(list_value), trace_nom!(tuple))
|
2018-05-27 14:46:39 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
value<SliceIter<Token>, Value>,
|
2018-08-30 21:00:28 -05:00
|
|
|
alt_peek!(
|
|
|
|
symbol_or_expression => trace_nom!(selector_value)
|
2018-11-05 21:34:12 -06:00
|
|
|
| either!(punct!("["), punct!("{")) => trace_nom!(compound_value)
|
2018-08-30 21:00:28 -05:00
|
|
|
| match_type!(BOOLEAN) => trace_nom!(boolean_value)
|
|
|
|
| match_type!(EMPTY) => trace_nom!(empty_value)
|
2018-11-05 21:34:12 -06:00
|
|
|
| either!(match_type!(DIGIT), punct!(".")) => trace_nom!(number)
|
2018-08-30 21:00:28 -05:00
|
|
|
| trace_nom!(quoted_value)
|
2018-05-27 14:46:39 -05:00
|
|
|
)
|
2018-11-05 21:34:12 -06:00
|
|
|
);
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn value_to_expression(v: Value) -> Expression {
|
|
|
|
Expression::Simple(v)
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
simple_expression<SliceIter<Token>, Expression>,
|
|
|
|
do_each!(
|
|
|
|
val => trace_nom!(value),
|
|
|
|
(value_to_expression(val))
|
|
|
|
)
|
2018-05-22 18:02:44 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn expression_to_grouped_expression(e: Expression) -> Expression {
|
|
|
|
Expression::Grouped(Box::new(e))
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
grouped_expression<SliceIter<Token>, Expression>,
|
|
|
|
do_each!(
|
|
|
|
_ => punct!("("),
|
|
|
|
expr => do_each!(
|
|
|
|
expr => trace_nom!(expression),
|
|
|
|
_ => punct!(")"),
|
|
|
|
(expr)
|
|
|
|
),
|
|
|
|
(expression_to_grouped_expression(expr))
|
|
|
|
)
|
2018-05-22 18:02:44 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn symbol_or_expression(input: SliceIter<Token>) -> NomResult<Expression> {
|
|
|
|
let _i = input.clone();
|
|
|
|
let scalar_head = do_each!(input,
|
|
|
|
sym => either!(symbol, compound_value),
|
|
|
|
(sym)
|
|
|
|
);
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-05-27 14:46:39 -05:00
|
|
|
match scalar_head {
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Incomplete(offset) => Result::Incomplete(offset),
|
|
|
|
Result::Fail(_) => grouped_expression(_i),
|
|
|
|
Result::Abort(e) => Result::Abort(e),
|
|
|
|
Result::Complete(rest, val) => {
|
2018-05-27 14:46:39 -05:00
|
|
|
let res = peek!(rest.clone(), punct!("."));
|
|
|
|
match val {
|
|
|
|
Value::Tuple(_) => {
|
2018-11-05 21:34:12 -06:00
|
|
|
if res.is_complete() {
|
|
|
|
Result::Complete(rest, Expression::Simple(val))
|
2018-05-27 14:46:39 -05:00
|
|
|
} else {
|
2018-11-05 21:34:12 -06:00
|
|
|
return Result::Fail(Error::new(
|
2018-05-27 14:46:39 -05:00
|
|
|
"Expected (.) but no dot found".to_string(),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(rest.clone()),
|
|
|
|
));
|
2018-05-27 14:46:39 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Value::List(_) => {
|
2018-11-05 21:34:12 -06:00
|
|
|
if res.is_complete() {
|
|
|
|
Result::Complete(rest, Expression::Simple(val))
|
2018-05-27 14:46:39 -05:00
|
|
|
} else {
|
2018-11-05 21:34:12 -06:00
|
|
|
return Result::Fail(Error::new(
|
2018-05-27 14:46:39 -05:00
|
|
|
"Expected (.) but no dot found".to_string(),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(rest.clone()),
|
|
|
|
));
|
2018-05-27 14:46:39 -05:00
|
|
|
}
|
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => Result::Complete(rest, Expression::Simple(val)),
|
2018-05-27 14:46:39 -05:00
|
|
|
}
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn selector_list(input: SliceIter<Token>) -> NomResult<SelectorList> {
|
2018-05-22 18:02:44 -05:00
|
|
|
let (rest, head) = match symbol_or_expression(input) {
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Complete(rest, val) => (rest, val),
|
|
|
|
Result::Fail(e) => {
|
|
|
|
return Result::Fail(e);
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Incomplete(i) => {
|
|
|
|
return Result::Incomplete(i);
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Abort(e) => return Result::Abort(e),
|
2018-05-22 18:02:44 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
let (rest, is_dot) = match punct!(rest, ".") {
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Complete(rest, tok) => (rest, Some(tok)),
|
|
|
|
Result::Incomplete(i) => {
|
|
|
|
return Result::Incomplete(i);
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Fail(_) => (rest, None),
|
|
|
|
Result::Abort(e) => return Result::Abort(e),
|
2018-05-22 18:02:44 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
let (rest, list) = if is_dot.is_some() {
|
2018-11-05 21:34:12 -06:00
|
|
|
let (rest, list) = match separated!(
|
2018-05-22 18:02:44 -05:00
|
|
|
rest,
|
|
|
|
punct!("."),
|
2018-11-05 21:34:12 -06:00
|
|
|
either!(match_type!(BAREWORD), match_type!(DIGIT), match_type!(STR))
|
2018-05-22 18:02:44 -05:00
|
|
|
) {
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Complete(rest, val) => (rest, val),
|
|
|
|
Result::Incomplete(i) => return Result::Incomplete(i),
|
|
|
|
Result::Fail(e) => return Result::Fail(e),
|
|
|
|
Result::Abort(e) => return Result::Abort(e),
|
2018-05-22 18:02:44 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
if list.is_empty() {
|
2018-11-05 21:34:12 -06:00
|
|
|
return Result::Fail(Error::new(
|
2018-05-22 18:02:44 -05:00
|
|
|
"(.) with no selector fields after".to_string(),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(rest.clone()),
|
|
|
|
));
|
2018-05-22 18:02:44 -05:00
|
|
|
} else {
|
|
|
|
(rest, Some(list))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
(rest, None)
|
|
|
|
};
|
|
|
|
|
|
|
|
let sel_list = SelectorList {
|
|
|
|
head: Box::new(head),
|
|
|
|
tail: list,
|
|
|
|
};
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
return Result::Complete(rest, sel_list);
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn tuple_to_copy(def: SelectorDef, fields: Option<FieldList>) -> Expression {
|
|
|
|
let pos = def.pos.clone();
|
|
|
|
let fields = match fields {
|
|
|
|
Some(fields) => fields,
|
|
|
|
None => Vec::new(),
|
|
|
|
};
|
|
|
|
Expression::Copy(CopyDef {
|
|
|
|
selector: def,
|
|
|
|
fields: fields,
|
2018-05-22 18:02:44 -05:00
|
|
|
pos: pos,
|
2018-11-05 21:34:12 -06:00
|
|
|
})
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
copy_expression<SliceIter<Token>, Expression>,
|
|
|
|
do_each!(
|
|
|
|
pos => pos,
|
|
|
|
selector => trace_nom!(selector_list),
|
|
|
|
_ => punct!("{"),
|
|
|
|
fields => optional!(trace_nom!(field_list)),
|
|
|
|
_ => optional!(punct!(",")), // noms opt! macro does not preserve error types properly but this one does.
|
|
|
|
_ => punct!("}"),
|
|
|
|
(tuple_to_copy(SelectorDef::new(selector, pos), fields))
|
2018-05-22 18:02:44 -05:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn tuple_to_macro<'a>(
|
|
|
|
input: SliceIter<'a, Token>,
|
|
|
|
pos: Position,
|
|
|
|
vals: Option<Vec<Value>>,
|
|
|
|
val: Value,
|
|
|
|
) -> ParseResult<'a, Expression> {
|
|
|
|
let mut default_args = match vals {
|
|
|
|
None => Vec::new(),
|
|
|
|
Some(vals) => vals,
|
|
|
|
};
|
|
|
|
let arglist = default_args
|
|
|
|
.drain(0..)
|
|
|
|
.map(|s| PositionedItem {
|
|
|
|
pos: s.pos().clone(),
|
|
|
|
val: s.to_string(),
|
2018-12-10 21:27:44 -06:00
|
|
|
})
|
|
|
|
.collect();
|
2018-11-05 21:34:12 -06:00
|
|
|
match val {
|
2018-05-22 18:02:44 -05:00
|
|
|
Value::Tuple(v) => Ok(Expression::Macro(MacroDef {
|
2018-11-05 21:34:12 -06:00
|
|
|
argdefs: arglist,
|
2018-05-22 18:02:44 -05:00
|
|
|
fields: v.val,
|
2018-11-05 21:34:12 -06:00
|
|
|
pos: pos,
|
2018-05-22 18:02:44 -05:00
|
|
|
})),
|
2018-11-05 21:34:12 -06:00
|
|
|
val => Err(Error::new(
|
2018-05-22 18:02:44 -05:00
|
|
|
format!("Expected Tuple Got {:?}", val),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(input.clone()),
|
2018-05-22 18:02:44 -05:00
|
|
|
)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
arglist<SliceIter<Token>, Vec<Value>>,
|
|
|
|
separated!(punct!(","), symbol)
|
2018-05-22 18:02:44 -05:00
|
|
|
);
|
|
|
|
|
2018-11-23 12:50:47 -06:00
|
|
|
fn module_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
|
|
|
let parsed = do_each!(input,
|
|
|
|
pos => pos,
|
|
|
|
_ => word!("module"),
|
|
|
|
_ => punct!("{"),
|
|
|
|
arglist => trace_nom!(optional!(field_list)),
|
|
|
|
_ => optional!(punct!(",")),
|
|
|
|
_ => punct!("}"),
|
|
|
|
_ => punct!("=>"),
|
|
|
|
_ => punct!("{"),
|
|
|
|
stmt_list => trace_nom!(repeat!(statement)),
|
|
|
|
_ => punct!("}"),
|
|
|
|
(pos, arglist, stmt_list)
|
|
|
|
);
|
|
|
|
match parsed {
|
|
|
|
Result::Abort(e) => Result::Abort(e),
|
|
|
|
Result::Fail(e) => Result::Fail(e),
|
|
|
|
Result::Incomplete(offset) => Result::Incomplete(offset),
|
|
|
|
Result::Complete(rest, (pos, arglist, stmt_list)) => {
|
|
|
|
let def = ModuleDef::new(arglist.unwrap_or_else(|| Vec::new()), stmt_list, pos);
|
|
|
|
//eprintln!(
|
|
|
|
// "module def at: {:?} arg_typle len {} stmts len {}",
|
|
|
|
// def.pos,
|
|
|
|
// def.arg_set.len(),
|
|
|
|
// def.statements.len()
|
|
|
|
//);
|
|
|
|
Result::Complete(rest, Expression::Module(def))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn macro_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
|
|
|
let parsed = do_each!(input,
|
|
|
|
pos => pos,
|
|
|
|
_ => word!("macro"),
|
|
|
|
_ => punct!("("),
|
|
|
|
arglist => trace_nom!(optional!(arglist)),
|
|
|
|
_ => punct!(")"),
|
|
|
|
_ => punct!("=>"),
|
|
|
|
map => trace_nom!(tuple),
|
|
|
|
(pos, arglist, map)
|
|
|
|
);
|
|
|
|
match parsed {
|
|
|
|
Result::Abort(e) => Result::Abort(e),
|
|
|
|
Result::Fail(e) => Result::Fail(e),
|
|
|
|
Result::Incomplete(offset) => Result::Incomplete(offset),
|
|
|
|
Result::Complete(rest, (pos, arglist, map)) => {
|
|
|
|
match tuple_to_macro(rest.clone(), pos, arglist, map) {
|
|
|
|
Ok(expr) => Result::Complete(rest, expr),
|
|
|
|
Err(e) => Result::Fail(Error::caused_by(
|
|
|
|
"Invalid Macro syntax",
|
|
|
|
Box::new(e),
|
|
|
|
Box::new(rest.clone()),
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tuple_to_select<'a>(
|
|
|
|
input: SliceIter<'a, Token>,
|
|
|
|
e1: Expression,
|
|
|
|
e2: Expression,
|
|
|
|
val: Value,
|
|
|
|
) -> ParseResult<'a, Expression> {
|
|
|
|
match val {
|
2018-05-22 18:02:44 -05:00
|
|
|
Value::Tuple(v) => Ok(Expression::Select(SelectDef {
|
2018-11-05 21:34:12 -06:00
|
|
|
val: Box::new(e1),
|
|
|
|
default: Box::new(e2),
|
2018-05-22 18:02:44 -05:00
|
|
|
tuple: v.val,
|
2018-11-05 21:34:12 -06:00
|
|
|
pos: (&input).into(),
|
2018-05-22 18:02:44 -05:00
|
|
|
})),
|
2018-11-05 21:34:12 -06:00
|
|
|
val => Err(Error::new(
|
2018-05-22 18:02:44 -05:00
|
|
|
format!("Expected Tuple Got {:?}", val),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(input.clone()),
|
2018-05-22 18:02:44 -05:00
|
|
|
)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn select_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
|
|
|
let parsed = do_each!(input,
|
|
|
|
_ => word!("select"),
|
|
|
|
val => do_each!(
|
|
|
|
expr => trace_nom!(expression),
|
|
|
|
_ => punct!(","),
|
|
|
|
(expr)
|
|
|
|
),
|
|
|
|
default => do_each!(
|
|
|
|
expr => trace_nom!(expression),
|
|
|
|
_ => punct!(","),
|
|
|
|
(expr)
|
|
|
|
),
|
|
|
|
map => trace_nom!(tuple),
|
|
|
|
(val, default, map)
|
|
|
|
);
|
|
|
|
match parsed {
|
|
|
|
Result::Abort(e) => Result::Abort(e),
|
|
|
|
Result::Fail(e) => Result::Fail(e),
|
|
|
|
Result::Incomplete(offset) => Result::Incomplete(offset),
|
|
|
|
Result::Complete(rest, (val, default, map)) => {
|
|
|
|
match tuple_to_select(input.clone(), val, default, map) {
|
|
|
|
Ok(expr) => Result::Complete(rest, expr),
|
|
|
|
Err(e) => Result::Fail(Error::caused_by(
|
|
|
|
"Invalid Select Expression",
|
|
|
|
Box::new(e),
|
|
|
|
Box::new(rest.clone()),
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn tuple_to_format(tok: Token, exprs: Vec<Expression>) -> Expression {
|
|
|
|
Expression::Format(FormatDef {
|
|
|
|
template: tok.fragment.to_string(),
|
|
|
|
args: exprs,
|
|
|
|
pos: tok.pos,
|
|
|
|
})
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
format_expression<SliceIter<Token>, Expression>,
|
|
|
|
do_each!(
|
|
|
|
tmpl => match_type!(STR),
|
|
|
|
_ => punct!("%"),
|
|
|
|
_ => punct!("("),
|
|
|
|
args => separated!(punct!(","), trace_nom!(expression)),
|
|
|
|
_ => punct!(")"),
|
|
|
|
(tuple_to_format(tmpl, args))
|
|
|
|
)
|
2018-05-22 18:02:44 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn tuple_to_call<'a>(
|
|
|
|
input: SliceIter<'a, Token>,
|
|
|
|
val: Value,
|
2018-11-20 17:42:39 -06:00
|
|
|
exprs: Option<Vec<Expression>>,
|
2018-11-05 21:34:12 -06:00
|
|
|
) -> ParseResult<'a, Expression> {
|
|
|
|
if let Value::Selector(def) = val {
|
2018-05-22 18:02:44 -05:00
|
|
|
Ok(Expression::Call(CallDef {
|
|
|
|
macroref: def,
|
2018-11-20 17:42:39 -06:00
|
|
|
arglist: exprs.unwrap_or_else(|| Vec::new()),
|
2018-11-05 21:34:12 -06:00
|
|
|
pos: (&input).into(),
|
2018-05-22 18:02:44 -05:00
|
|
|
}))
|
|
|
|
} else {
|
2018-11-05 21:34:12 -06:00
|
|
|
Err(Error::new(
|
|
|
|
format!("Expected Selector Got {:?}", val),
|
|
|
|
Box::new(input.clone()),
|
2018-05-22 18:02:44 -05:00
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn vec_to_selector_value(pos: Position, list: SelectorList) -> Value {
|
|
|
|
Value::Selector(SelectorDef::new(list, pos))
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
selector_value<SliceIter<Token>, Value>,
|
|
|
|
do_each!(
|
|
|
|
sl => trace_nom!(selector_list),
|
|
|
|
(vec_to_selector_value(sl.head.pos().clone(), sl))
|
|
|
|
)
|
2018-05-22 18:02:44 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn call_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
|
|
|
let parsed = do_each!(input.clone(),
|
2018-11-23 12:50:47 -06:00
|
|
|
callee_name => trace_nom!(selector_value),
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => punct!("("),
|
2018-11-20 17:42:39 -06:00
|
|
|
args => optional!(separated!(punct!(","), trace_nom!(expression))),
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => punct!(")"),
|
2018-11-23 12:50:47 -06:00
|
|
|
(callee_name, args)
|
2018-11-05 21:34:12 -06:00
|
|
|
);
|
|
|
|
match parsed {
|
|
|
|
Result::Abort(e) => Result::Abort(e),
|
|
|
|
Result::Fail(e) => Result::Fail(e),
|
|
|
|
Result::Incomplete(offset) => Result::Incomplete(offset),
|
|
|
|
Result::Complete(rest, (name, args)) => match tuple_to_call(input.clone(), name, args) {
|
|
|
|
Ok(expr) => Result::Complete(rest, expr),
|
|
|
|
Err(e) => Result::Fail(Error::caused_by(
|
|
|
|
"Invalid Call Syntax",
|
|
|
|
Box::new(e),
|
|
|
|
Box::new(rest),
|
|
|
|
)),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn tuple_to_list_op<'a>(
|
|
|
|
input: &'a SliceIter<Token>,
|
|
|
|
kind: ListOpType,
|
|
|
|
macroname: Value,
|
|
|
|
list: Expression,
|
|
|
|
) -> ParseResult<'a, Expression> {
|
2018-05-22 18:02:44 -05:00
|
|
|
if let Value::Selector(mut def) = macroname {
|
|
|
|
// First of all we need to assert that this is a selector of at least
|
|
|
|
// two sections.
|
|
|
|
let fieldname: String = match &mut def.sel.tail {
|
|
|
|
&mut None => {
|
2018-08-21 23:05:06 -05:00
|
|
|
if ENABLE_TRACE {
|
|
|
|
eprintln!(
|
|
|
|
"tuple_to_list_op had error {}",
|
|
|
|
"Missing a result field for the macro"
|
|
|
|
);
|
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
return Err(Error::new(
|
2018-05-22 18:02:44 -05:00
|
|
|
format!("Missing a result field for the macro"),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(input.clone()),
|
2018-05-22 18:02:44 -05:00
|
|
|
));
|
|
|
|
}
|
|
|
|
&mut Some(ref mut tl) => {
|
|
|
|
if tl.len() < 1 {
|
2018-08-21 23:05:06 -05:00
|
|
|
if ENABLE_TRACE {
|
|
|
|
eprintln!(
|
|
|
|
"tuple_to_list_op had error {}",
|
|
|
|
"Missing a result field for the macro"
|
|
|
|
);
|
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
return Err(Error::new(
|
2018-05-22 18:02:44 -05:00
|
|
|
format!("Missing a result field for the macro"),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(input.clone()),
|
2018-05-22 18:02:44 -05:00
|
|
|
));
|
|
|
|
}
|
|
|
|
let fname = tl.pop();
|
|
|
|
fname.unwrap().fragment
|
|
|
|
}
|
|
|
|
};
|
2018-08-21 23:05:06 -05:00
|
|
|
return Ok(Expression::ListOp(ListOpDef {
|
2018-11-05 21:34:12 -06:00
|
|
|
typ: kind,
|
2018-08-21 23:05:06 -05:00
|
|
|
mac: def,
|
|
|
|
field: fieldname,
|
|
|
|
target: Box::new(list),
|
2018-11-05 21:34:12 -06:00
|
|
|
pos: input.into(),
|
2018-08-21 23:05:06 -05:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
if ENABLE_TRACE {
|
|
|
|
eprintln!(
|
|
|
|
"tuple_to_list_op had error {}",
|
|
|
|
format!("Expected a selector but got {}", macroname.type_name())
|
|
|
|
);
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
return Err(Error::new(
|
2018-05-27 21:00:49 -05:00
|
|
|
format!("Expected a selector but got {}", macroname.type_name()),
|
2018-11-05 21:34:12 -06:00
|
|
|
Box::new(input.clone()),
|
2018-05-22 18:02:44 -05:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
list_op_expression<SliceIter<Token>, Expression>,
|
|
|
|
do_each!(
|
|
|
|
input => input!(),
|
|
|
|
optype => either!(
|
|
|
|
do_each!(_ => word!("map"), (ListOpType::Map)),
|
|
|
|
do_each!(_ => word!("filter"), (ListOpType::Filter))
|
2018-05-22 18:02:44 -05:00
|
|
|
),
|
2018-11-05 21:34:12 -06:00
|
|
|
macroname => trace_nom!(selector_value),
|
|
|
|
list => trace_nom!(non_op_expression),
|
|
|
|
(tuple_to_list_op(&input, optype, macroname, list).unwrap())
|
2018-05-22 18:02:44 -05:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn unprefixed_expression(input: SliceIter<Token>) -> NomResult<Expression> {
|
2018-08-30 21:00:28 -05:00
|
|
|
let _input = input.clone();
|
2018-11-05 21:34:12 -06:00
|
|
|
let attempt = either!(
|
|
|
|
input,
|
|
|
|
trace_nom!(call_expression),
|
|
|
|
trace_nom!(copy_expression),
|
|
|
|
trace_nom!(format_expression)
|
|
|
|
);
|
|
|
|
match attempt {
|
|
|
|
Result::Incomplete(i) => Result::Incomplete(i),
|
|
|
|
Result::Complete(rest, expr) => Result::Complete(rest, expr),
|
|
|
|
Result::Fail(_) => trace_nom!(_input, simple_expression),
|
|
|
|
Result::Abort(e) => Result::Abort(e),
|
|
|
|
}
|
2018-08-30 21:00:28 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
non_op_expression<SliceIter<Token>, Expression>,
|
2018-08-30 21:00:28 -05:00
|
|
|
alt_peek!(
|
2018-11-05 21:34:12 -06:00
|
|
|
either!(word!("map"), word!("filter")) => trace_nom!(list_op_expression) |
|
2018-08-30 21:00:28 -05:00
|
|
|
word!("macro") => trace_nom!(macro_expression) |
|
2018-11-23 12:50:47 -06:00
|
|
|
word!("module") => trace_nom!(module_expression) |
|
2018-08-30 21:00:28 -05:00
|
|
|
word!("select") => trace_nom!(select_expression) |
|
|
|
|
punct!("(") => trace_nom!(grouped_expression) |
|
|
|
|
trace_nom!(unprefixed_expression))
|
2018-05-26 09:12:00 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn expression(input: SliceIter<Token>) -> NomResult<Expression> {
|
2018-08-30 21:00:28 -05:00
|
|
|
let _input = input.clone();
|
|
|
|
match trace_nom!(_input, op_expression) {
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Incomplete(i) => Result::Incomplete(i),
|
|
|
|
Result::Fail(_) => trace_nom!(input, non_op_expression),
|
|
|
|
Result::Abort(e) => Result::Abort(e),
|
|
|
|
Result::Complete(rest, expr) => Result::Complete(rest, expr),
|
2018-08-30 21:00:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
expression_statement<SliceIter<Token>, Statement>,
|
|
|
|
do_each!(
|
|
|
|
e => do_each!(
|
|
|
|
expr => trace_nom!(expression),
|
|
|
|
_ => punct!(";"),
|
|
|
|
(expr)
|
|
|
|
),
|
|
|
|
(Statement::Expression(e))
|
2018-05-22 18:02:44 -05:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn tuple_to_let(tok: Token, expr: Expression) -> Statement {
|
|
|
|
Statement::Let(LetDef {
|
|
|
|
name: tok,
|
|
|
|
value: expr,
|
|
|
|
})
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
let_stmt_body<SliceIter<Token>, Statement>,
|
|
|
|
do_each!(
|
2018-11-06 19:40:56 -06:00
|
|
|
name => wrap_err!(match_type!(BAREWORD), "Expected name for binding"),
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => punct!("="),
|
2018-11-06 19:40:56 -06:00
|
|
|
// TODO(jwall): Wrap this error with an appropriate abortable_parser::Error
|
2018-11-23 12:50:47 -06:00
|
|
|
val => wrap_err!(trace_nom!(expression), "Expected Expression"),
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => punct!(";"),
|
|
|
|
(tuple_to_let(name, val))
|
2018-05-22 18:02:44 -05:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
let_statement<SliceIter<Token>, Statement>,
|
|
|
|
do_each!(
|
|
|
|
_ => word!("let"),
|
|
|
|
stmt => trace_nom!(must!(let_stmt_body)),
|
2018-05-22 19:05:40 -05:00
|
|
|
(stmt)
|
2018-11-05 21:34:12 -06:00
|
|
|
)
|
2018-05-22 19:05:40 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
fn tuple_to_import(tok: Token, tok2: Token) -> Statement {
|
|
|
|
Statement::Import(ImportDef {
|
|
|
|
path: tok,
|
|
|
|
name: tok2,
|
|
|
|
})
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
import_stmt_body<SliceIter<Token>, Statement>,
|
|
|
|
do_each!(
|
2018-11-06 19:40:56 -06:00
|
|
|
path => wrap_err!(match_type!(STR), "Expected import path"),
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => word!("as"),
|
2018-11-06 19:40:56 -06:00
|
|
|
name => wrap_err!(match_type!(BAREWORD), "Expected import name"),
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => punct!(";"),
|
|
|
|
(tuple_to_import(path, name))
|
2018-05-22 18:02:44 -05:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
import_statement<SliceIter<Token>, Statement>,
|
|
|
|
do_each!(
|
|
|
|
_ => word!("import"),
|
2018-05-22 19:05:40 -05:00
|
|
|
// past this point we know this is supposed to be an import statement.
|
2018-11-05 21:34:12 -06:00
|
|
|
stmt => trace_nom!(must!(import_stmt_body)),
|
2018-05-22 19:05:40 -05:00
|
|
|
(stmt)
|
2018-11-05 21:34:12 -06:00
|
|
|
)
|
2018-05-22 19:05:40 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
assert_statement<SliceIter<Token>, Statement>,
|
|
|
|
do_each!(
|
|
|
|
_ => word!("assert"),
|
|
|
|
tok => must!(match_type!(PIPEQUOTE)),
|
|
|
|
_ => must!(punct!(";")),
|
|
|
|
(Statement::Assert(tok.clone()))
|
|
|
|
)
|
2018-05-30 23:00:50 -05:00
|
|
|
);
|
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
make_fn!(
|
|
|
|
out_statement<SliceIter<Token>, Statement>,
|
|
|
|
do_each!(
|
|
|
|
_ => word!("out"),
|
2018-11-06 19:40:56 -06:00
|
|
|
typ => wrap_err!(must!(match_type!(BAREWORD)), "Expected converter name"),
|
2018-11-23 12:50:47 -06:00
|
|
|
expr => wrap_err!(must!(expression), "Expected Expression to export"),
|
2018-11-05 21:34:12 -06:00
|
|
|
_ => must!(punct!(";")),
|
2018-08-13 20:37:58 -05:00
|
|
|
(Statement::Output(typ.clone(), expr.clone()))
|
2018-11-05 21:34:12 -06:00
|
|
|
)
|
2018-08-13 20:37:58 -05:00
|
|
|
);
|
|
|
|
|
2018-06-04 20:48:56 -05:00
|
|
|
//trace_macros!(true);
|
2018-11-05 21:34:12 -06:00
|
|
|
fn statement(i: SliceIter<Token>) -> Result<SliceIter<Token>, Statement> {
|
2018-06-04 20:48:56 -05:00
|
|
|
return alt_peek!(i,
|
2018-12-10 21:27:44 -06:00
|
|
|
word!("assert") => trace_nom!(assert_statement) |
|
|
|
|
word!("import") => trace_nom!(import_statement) |
|
|
|
|
word!("let") => trace_nom!(let_statement) |
|
|
|
|
word!("out") => trace_nom!(out_statement) |
|
|
|
|
trace_nom!(expression_statement)
|
|
|
|
);
|
2018-06-04 20:48:56 -05:00
|
|
|
}
|
|
|
|
//trace_macros!(false);
|
2018-05-22 18:02:44 -05:00
|
|
|
|
2018-11-05 21:34:12 -06:00
|
|
|
/// Parses a LocatedSpan into a list of Statements or an `error::Error`.
|
|
|
|
pub fn parse<'a>(input: OffsetStrIter<'a>) -> std::result::Result<Vec<Statement>, String> {
|
|
|
|
match tokenize(input.clone()) {
|
2018-05-22 18:02:44 -05:00
|
|
|
Ok(tokenized) => {
|
|
|
|
let mut out = Vec::new();
|
2018-11-05 21:34:12 -06:00
|
|
|
let mut i_ = SliceIter::new(&tokenized);
|
2018-05-22 18:02:44 -05:00
|
|
|
loop {
|
|
|
|
let i = i_.clone();
|
2018-11-05 21:34:12 -06:00
|
|
|
if let Some(tok) = i.peek_next() {
|
|
|
|
if tok.typ == TokenType::END {
|
|
|
|
break;
|
|
|
|
}
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
match statement(i.clone()) {
|
|
|
|
Result::Abort(e) => {
|
2018-11-07 18:24:44 -06:00
|
|
|
let ctx_err = StackPrinter { err: e };
|
2018-11-05 21:34:12 -06:00
|
|
|
return Err(format!("{}", ctx_err));
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Fail(e) => {
|
2018-11-07 18:24:44 -06:00
|
|
|
let ctx_err = StackPrinter { err: e };
|
2018-11-05 21:34:12 -06:00
|
|
|
return Err(format!("{}", ctx_err));
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Incomplete(_ei) => {
|
|
|
|
let err = abortable_parser::Error::new(
|
|
|
|
"Unexpected end of parse input",
|
|
|
|
Box::new(i.clone()),
|
|
|
|
);
|
|
|
|
let ctx_err = StackPrinter { err: err };
|
|
|
|
return Err(format!("{}", ctx_err));
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
2018-11-05 21:34:12 -06:00
|
|
|
Result::Complete(rest, stmt) => {
|
2018-05-22 18:02:44 -05:00
|
|
|
out.push(stmt);
|
|
|
|
i_ = rest;
|
2018-11-05 21:34:12 -06:00
|
|
|
if eoi(i).is_complete() {
|
2018-05-22 18:02:44 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Ok(out);
|
|
|
|
}
|
|
|
|
Err(e) => {
|
2018-11-05 21:34:12 -06:00
|
|
|
return Err(e);
|
2018-05-22 18:02:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 12:30:29 -05:00
|
|
|
pub mod precedence;
|
|
|
|
|
2018-05-22 18:02:44 -05:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test;
|