mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
Thread position information through to more places.
This commit is contained in:
parent
1e3d19755c
commit
4f3cc3dbf6
101
src/ast.rs
101
src/ast.rs
@ -14,6 +14,12 @@
|
||||
use std::collections::HashSet;
|
||||
use std::borrow::Borrow;
|
||||
use std::convert::Into;
|
||||
use std::cmp::Ordering;
|
||||
use std::cmp::PartialOrd;
|
||||
use std::cmp::Eq;
|
||||
use std::cmp::PartialEq;
|
||||
use std::hash::Hasher;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[derive(Debug,PartialEq,Eq,Clone,PartialOrd,Ord,Hash)]
|
||||
pub struct Position {
|
||||
@ -28,15 +34,7 @@ pub struct Token {
|
||||
}
|
||||
|
||||
impl Token {
|
||||
pub fn new(f: &str) -> Self {
|
||||
Self::new_with_pos(f,
|
||||
Position {
|
||||
line: 0,
|
||||
column: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_with_pos(f: &str, pos: Position) -> Self {
|
||||
pub fn new(f: &str, pos: Position) -> Self {
|
||||
Token {
|
||||
fragment: f.to_string(),
|
||||
pos: pos,
|
||||
@ -51,11 +49,8 @@ impl Borrow<str> for Token {
|
||||
}
|
||||
|
||||
macro_rules! value_node {
|
||||
($v:expr) => {
|
||||
LocatedNode::new($v)
|
||||
};
|
||||
($v:expr, $p:expr) => {
|
||||
LocatedNode::new_with_pos($v, $p)
|
||||
LocatedNode::new($v, $p)
|
||||
};
|
||||
}
|
||||
|
||||
@ -64,21 +59,15 @@ pub type SelectorList = Vec<Token>; // str is expected to always be a symbol.
|
||||
|
||||
#[derive(Debug,PartialEq,Clone)]
|
||||
pub struct LocatedNode<T> {
|
||||
pub pos: Option<Position>,
|
||||
// TODO(jwall): Make this non-optional, Should we just use positioned instead?
|
||||
pub pos: Position,
|
||||
pub val: T,
|
||||
}
|
||||
|
||||
impl<T> LocatedNode<T> {
|
||||
pub fn new(v: T) -> Self {
|
||||
pub fn new<P: Into<Position>>(v: T, pos: P) -> Self {
|
||||
Self {
|
||||
pos: None,
|
||||
val: v,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_pos<P: Into<Position>>(v: T, pos: P) -> Self {
|
||||
Self {
|
||||
pos: Some(pos.into()),
|
||||
pos: pos.into(),
|
||||
val: v,
|
||||
}
|
||||
}
|
||||
@ -89,8 +78,9 @@ impl<T> LocatedNode<T> {
|
||||
}
|
||||
|
||||
|
||||
pub fn make_value_node<T>(v: T) -> LocatedNode<T> {
|
||||
LocatedNode::new(v)
|
||||
// TODO(jwall): This should take a line and a column as argumentsn now.
|
||||
pub fn make_value_node<T>(v: T, line: usize, column: usize) -> LocatedNode<T> {
|
||||
LocatedNode::new(v, Position{line: line, column: column})
|
||||
}
|
||||
|
||||
/// Value represents a Value in the UCG parsed AST.
|
||||
@ -141,7 +131,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pos(&self) -> &Option<Position> {
|
||||
pub fn pos(&self) -> &Position {
|
||||
match self {
|
||||
&Value::Int(ref i) => &i.pos,
|
||||
&Value::Float(ref f) => &f.pos,
|
||||
@ -173,7 +163,7 @@ pub struct SelectDef {
|
||||
}
|
||||
|
||||
// TODO(jwall): This should have a way of rendering with position information.
|
||||
#[derive(PartialEq,Debug,Eq,PartialOrd,Ord,Clone,Hash)]
|
||||
#[derive(Debug,Clone)]
|
||||
pub struct Positioned<T> {
|
||||
pub pos: Option<Position>,
|
||||
pub val: T,
|
||||
@ -195,6 +185,33 @@ impl<T> Positioned<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for Positioned<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.val == other.val
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq> Eq for Positioned<T> {
|
||||
}
|
||||
|
||||
impl<T: Ord> Ord for Positioned<T> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.val.cmp(&other.val)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd> PartialOrd for Positioned<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.val.partial_cmp(&other.val)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash> Hash for Positioned<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.val.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Token> for Positioned<String> {
|
||||
fn from(t: &'a Token) -> Positioned<String> {
|
||||
Positioned {
|
||||
@ -207,7 +224,7 @@ impl<'a> From<&'a Token> for Positioned<String> {
|
||||
impl<'a> From<&'a LocatedNode<String>> for Positioned<String> {
|
||||
fn from(t: &LocatedNode<String>) -> Positioned<String> {
|
||||
Positioned {
|
||||
pos: t.pos.clone(),
|
||||
pos: Some(t.pos.clone()),
|
||||
val: t.val.clone(),
|
||||
}
|
||||
}
|
||||
@ -401,10 +418,10 @@ mod ast_test {
|
||||
Positioned::new("foo".to_string())
|
||||
],
|
||||
fields: vec![
|
||||
(Token::new("f1"), Expression::Binary(BinaryOpDef{
|
||||
(Token::new("f1", Position { line: 1, column: 1}), Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Symbol(make_value_node("foo".to_string())),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
left: Value::Symbol(make_value_node("foo".to_string(), 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
pos: None,
|
||||
})),
|
||||
],
|
||||
@ -420,10 +437,10 @@ mod ast_test {
|
||||
Positioned::new("foo".to_string())
|
||||
],
|
||||
fields: vec![
|
||||
(Token::new("f1"), Expression::Binary(BinaryOpDef{
|
||||
(Token::new("f1", Position{line: 1, column: 1}), Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Symbol(make_value_node("bar".to_string())),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
left: Value::Symbol(make_value_node("bar".to_string(), 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
pos: None,
|
||||
})),
|
||||
],
|
||||
@ -441,10 +458,12 @@ mod ast_test {
|
||||
Positioned::new("foo".to_string())
|
||||
],
|
||||
fields: vec![
|
||||
(Token::new("f1"), Expression::Binary(BinaryOpDef{
|
||||
(Token::new("f1", Position{line: 1, column: 1}), Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Selector(make_value_node(vec![Token::new("foo"), Token::new("quux")])),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
left: Value::Selector(make_value_node(vec![
|
||||
Token::new("foo", Position{line: 1, column: 1}),
|
||||
Token::new("quux", Position{line: 1, column: 1})], 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
pos: None,
|
||||
})),
|
||||
],
|
||||
@ -460,10 +479,12 @@ mod ast_test {
|
||||
Positioned::new("foo".to_string()),
|
||||
],
|
||||
fields: vec![
|
||||
(Token::new("f1"), Expression::Binary(BinaryOpDef{
|
||||
(Token::new("f1", Position{line: 1, column: 1}), Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Selector(make_value_node(vec![Token::new("bar"), Token::new("quux")])),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
left: Value::Selector(make_value_node(vec![
|
||||
Token::new("bar", Position{line: 1, column: 1}),
|
||||
Token::new("quux", Position{line: 1, column: 1})], 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
pos: None,
|
||||
})),
|
||||
],
|
||||
|
236
src/build.rs
236
src/build.rs
@ -43,9 +43,9 @@ impl MacroDef {
|
||||
// If the expressions reference Symbols not defined in the MacroDef that is also an error.
|
||||
// TODO(jwall): We should probably enforce that the Expression Symbols must be in argdefs rules
|
||||
// at Macro definition time not evaluation time.
|
||||
let mut scope = HashMap::<String, Rc<Val>>::new();
|
||||
let mut scope = HashMap::<Positioned<String>, Rc<Val>>::new();
|
||||
for (i, arg) in args.drain(0..).enumerate() {
|
||||
scope.entry(self.argdefs[i].val.clone()).or_insert(arg.clone());
|
||||
scope.entry(self.argdefs[i].clone()).or_insert(arg.clone());
|
||||
}
|
||||
let b = Builder::new_with_scope(scope);
|
||||
let mut result: Vec<(Positioned<String>, Rc<Val>)> = Vec::new();
|
||||
@ -217,7 +217,7 @@ impl From<Val> for String {
|
||||
}
|
||||
|
||||
/// ValueMap defines a set of values in a parsed file.
|
||||
type ValueMap = HashMap<String, Rc<Val>>;
|
||||
type ValueMap = HashMap<Positioned<String>, Rc<Val>>;
|
||||
|
||||
/// Builder parses one or more statements into a out Tuple.
|
||||
pub struct Builder {
|
||||
@ -285,7 +285,7 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_scope(scope: HashMap<String, Rc<Val>>) -> Self {
|
||||
pub fn new_with_scope(scope: ValueMap) -> Self {
|
||||
Builder {
|
||||
assets: HashMap::new(),
|
||||
files: HashSet::new(),
|
||||
@ -331,7 +331,7 @@ impl Builder {
|
||||
&Statement::Let { name: ref sym, value: ref expr } => {
|
||||
let val = try!(self.eval_expr(expr));
|
||||
self.last = Some(val.clone());
|
||||
match self.out.entry(sym.fragment.clone()) {
|
||||
match self.out.entry(sym.into()) {
|
||||
Entry::Occupied(e) => {
|
||||
return Err(Box::new(BuildError::DuplicateBinding(format!("Let binding \
|
||||
for {:?} already \
|
||||
@ -346,14 +346,14 @@ impl Builder {
|
||||
&Statement::Import { path: ref val, name: ref sym } => {
|
||||
if !self.files.contains(val) {
|
||||
// Only parse the file once on import.
|
||||
if self.assets.get(&sym.fragment).is_none() {
|
||||
let positioned_sym = sym.into();
|
||||
if self.assets.get(&positioned_sym).is_none() {
|
||||
let mut b = Self::new();
|
||||
try!(b.build_file(&val));
|
||||
let fields: Vec<(Positioned<String>, Rc<Val>)> =
|
||||
b.out.drain().map(|t| (Positioned::new(t.0), t.1))
|
||||
.collect();
|
||||
b.out.drain().collect();
|
||||
let result = Rc::new(Val::Tuple(fields));
|
||||
self.assets.entry(sym.fragment.clone()).or_insert(result.clone());
|
||||
self.assets.entry(positioned_sym).or_insert(result.clone());
|
||||
self.files.insert(val.clone());
|
||||
self.last = Some(result);
|
||||
}
|
||||
@ -367,11 +367,11 @@ impl Builder {
|
||||
}
|
||||
|
||||
fn lookup_sym(&self, sym: &Positioned<String>) -> Option<Rc<Val>> {
|
||||
if self.out.contains_key(&sym.val) {
|
||||
return Some(self.out[&sym.val].clone());
|
||||
if self.out.contains_key(sym) {
|
||||
return Some(self.out[sym].clone());
|
||||
}
|
||||
if self.assets.contains_key(&sym.val) {
|
||||
return Some(self.assets[&sym.val].clone());
|
||||
if self.assets.contains_key(sym) {
|
||||
return Some(self.assets[sym].clone());
|
||||
}
|
||||
None
|
||||
}
|
||||
@ -569,10 +569,10 @@ impl Builder {
|
||||
&Expression::Copy(ref def) => {
|
||||
let v = try!(self.lookup_selector(&def.selector));
|
||||
if let Val::Tuple(ref src_fields) = *v {
|
||||
let mut m = HashMap::<&String, Rc<Val>>::new();
|
||||
// loop through fields and build up a hasmap
|
||||
let mut m = HashMap::<Positioned<String>, Rc<Val>>::new();
|
||||
// loop through fields and build up a hahsmap
|
||||
for &(ref key, ref val) in src_fields.iter() {
|
||||
if let Entry::Vacant(v) = m.entry(&key.val) {
|
||||
if let Entry::Vacant(v) = m.entry(key.clone()) {
|
||||
v.insert(val.clone());
|
||||
} else {
|
||||
return Err(Box::new(BuildError::TypeFail(format!("Duplicate \
|
||||
@ -583,7 +583,7 @@ impl Builder {
|
||||
}
|
||||
for &(ref key, ref val) in def.fields.iter() {
|
||||
let expr_result = try!(self.eval_expr(val));
|
||||
match m.entry(&key.fragment) {
|
||||
match m.entry(key.into()) {
|
||||
Entry::Vacant(v) => {
|
||||
v.insert(expr_result);
|
||||
}
|
||||
@ -601,9 +601,7 @@ impl Builder {
|
||||
}
|
||||
};
|
||||
}
|
||||
let mut new_fields: Vec<(Positioned<String>, Rc<Val>)> = m.drain()
|
||||
.map(|(s, v)| (Positioned::new(s.to_string()), v))
|
||||
.collect();
|
||||
let mut new_fields: Vec<(Positioned<String>, Rc<Val>)> = m.drain().collect();
|
||||
// We want a stable order for the fields to make comparing tuples
|
||||
// easier in later code. So we sort by the field name before constructing a new tuple.
|
||||
new_fields.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
@ -697,16 +695,16 @@ mod test {
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Div,
|
||||
left: Value::Int(make_value_node(2)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))),
|
||||
left: Value::Int(make_value_node(2, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Int(1)),
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Div,
|
||||
left: Value::Float(make_value_node(2.0)),
|
||||
right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0)))),
|
||||
left: Value::Float(make_value_node(2.0, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Float(1.0)),
|
||||
@ -722,8 +720,8 @@ mod test {
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Div,
|
||||
left: Value::Float(make_value_node(2.0)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))),
|
||||
left: Value::Float(make_value_node(2.0, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Float(1.0)),
|
||||
@ -738,16 +736,16 @@ mod test {
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Mul,
|
||||
left: Value::Int(make_value_node(2)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))),
|
||||
left: Value::Int(make_value_node(2, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Int(4)),
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Mul,
|
||||
left: Value::Float(make_value_node(2.0)),
|
||||
right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0)))),
|
||||
left: Value::Float(make_value_node(2.0, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Float(4.0)),
|
||||
@ -763,8 +761,8 @@ mod test {
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Mul,
|
||||
left: Value::Float(make_value_node(2.0)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(20)))),
|
||||
left: Value::Float(make_value_node(2.0, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(20, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Float(1.0)),
|
||||
@ -779,16 +777,16 @@ mod test {
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Sub,
|
||||
left: Value::Int(make_value_node(2)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
left: Value::Int(make_value_node(2, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Int(1)),
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Sub,
|
||||
left: Value::Float(make_value_node(2.0)),
|
||||
right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0)))),
|
||||
left: Value::Float(make_value_node(2.0, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Float(1.0)),
|
||||
@ -804,8 +802,8 @@ mod test {
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Sub,
|
||||
left: Value::Float(make_value_node(2.0)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))),
|
||||
left: Value::Float(make_value_node(2.0, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Float(1.0)),
|
||||
@ -820,24 +818,24 @@ mod test {
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Int(make_value_node(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
left: Value::Int(make_value_node(1, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Int(2)),
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Float(make_value_node(1.0)),
|
||||
right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0)))),
|
||||
left: Value::Float(make_value_node(1.0, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Float(2.0)),
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::String(make_value_node("foo".to_string())),
|
||||
right: Box::new(Expression::Simple(Value::String(make_value_node("bar".to_string())))),
|
||||
left: Value::String(make_value_node("foo".to_string(), 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::String(make_value_node("bar".to_string(), 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::String("foobar".to_string())),
|
||||
@ -852,8 +850,8 @@ mod test {
|
||||
(Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Float(make_value_node(2.0)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))),
|
||||
left: Value::Float(make_value_node(2.0, 1, 1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
|
||||
pos: None,
|
||||
}),
|
||||
Val::Float(1.0)),
|
||||
@ -864,14 +862,14 @@ mod test {
|
||||
#[test]
|
||||
fn test_eval_simple_expr() {
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Simple(Value::Int(make_value_node(1))), Val::Int(1)),
|
||||
(Expression::Simple(Value::Float(make_value_node(2.0))), Val::Float(2.0)),
|
||||
(Expression::Simple(Value::String(make_value_node("foo".to_string()))),
|
||||
(Expression::Simple(Value::Int(make_value_node(1, 1, 1))), Val::Int(1)),
|
||||
(Expression::Simple(Value::Float(make_value_node(2.0, 1, 1))), Val::Float(2.0)),
|
||||
(Expression::Simple(Value::String(make_value_node("foo".to_string(), 1, 1))),
|
||||
Val::String("foo".to_string())),
|
||||
(Expression::Simple(Value::Tuple(make_value_node(vec![
|
||||
(Token::new("bar"), Expression::Simple(Value::Int(make_value_node(1))))
|
||||
]))),
|
||||
Val::Tuple(vec![(Positioned::new_with_pos("bar".to_string(), Position{line: 0, column: 0}),
|
||||
(Token::new("bar", Position{line: 1, column: 1}), Expression::Simple(Value::Int(make_value_node(1, 1, 1))))
|
||||
], 1, 1))),
|
||||
Val::Tuple(vec![(Positioned::new_with_pos("bar".to_string(), Position{line: 1, column: 1}),
|
||||
Rc::new(Val::Int(1)))])),
|
||||
],
|
||||
Builder::new());
|
||||
@ -880,9 +878,9 @@ mod test {
|
||||
#[test]
|
||||
fn test_eval_simple_lookup_expr() {
|
||||
let mut b = Builder::new();
|
||||
b.out.entry("var1".to_string()).or_insert(Rc::new(Val::Int(1)));
|
||||
b.out.entry(Positioned::new("var1".to_string())).or_insert(Rc::new(Val::Int(1)));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Simple(Value::Symbol(make_value_node("var1".to_string()))), Val::Int(1)),
|
||||
(Expression::Simple(Value::Symbol(make_value_node("var1".to_string(), 1, 1))), Val::Int(1)),
|
||||
],
|
||||
b);
|
||||
}
|
||||
@ -890,8 +888,8 @@ mod test {
|
||||
#[test]
|
||||
fn test_eval_simple_lookup_error() {
|
||||
let mut b = Builder::new();
|
||||
b.out.entry("var1".to_string()).or_insert(Rc::new(Val::Int(1)));
|
||||
let expr = Expression::Simple(Value::Symbol(make_value_node("var".to_string())));
|
||||
b.out.entry(Positioned::new("var1".to_string())).or_insert(Rc::new(Val::Int(1)));
|
||||
let expr = Expression::Simple(Value::Symbol(make_value_node("var".to_string(), 1, 1)));
|
||||
assert!(b.eval_expr(&expr).is_err());
|
||||
}
|
||||
|
||||
@ -899,20 +897,20 @@ mod test {
|
||||
fn test_eval_selector_expr() {
|
||||
// TODO(jwall): Tests for this expression.
|
||||
let mut b = Builder::new();
|
||||
b.out.entry("var1".to_string()).or_insert(Rc::new(Val::Tuple(vec![
|
||||
b.out.entry(Positioned::new("var1".to_string())).or_insert(Rc::new(Val::Tuple(vec![
|
||||
(Positioned::new("lvl1".to_string()), Rc::new(Val::Tuple(
|
||||
vec![
|
||||
(Positioned::new("lvl2".to_string()), Rc::new(Val::Int(3))),
|
||||
]
|
||||
))),
|
||||
])));
|
||||
b.out.entry("var2".to_string()).or_insert(Rc::new(Val::Int(2)));
|
||||
b.out.entry(Positioned::new("var2".to_string())).or_insert(Rc::new(Val::Int(2)));
|
||||
b.out
|
||||
.entry("var3".to_string())
|
||||
.entry(Positioned::new("var3".to_string()))
|
||||
.or_insert(Rc::new(Val::Tuple(vec![(Positioned::new("lvl1".to_string()),
|
||||
Rc::new(Val::Int(4)))])));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1")]))), Val::Tuple(
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1", Position{line: 1, column: 1})], 1, 1))), Val::Tuple(
|
||||
vec![
|
||||
(Positioned::new("lvl1".to_string()), Rc::new(Val::Tuple(
|
||||
vec![
|
||||
@ -921,21 +919,21 @@ mod test {
|
||||
))),
|
||||
]
|
||||
)),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1"),
|
||||
Token::new("lvl1")]))),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1", Position{line: 1, column: 1}),
|
||||
Token::new("lvl1", Position{line: 1, column: 1})], 1, 1))),
|
||||
Val::Tuple(
|
||||
vec![
|
||||
(Positioned::new("lvl2".to_string()), Rc::new(Val::Int(3))),
|
||||
]
|
||||
)),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1"),
|
||||
Token::new("lvl1"),
|
||||
Token::new("lvl2")]))),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1", Position{line: 1, column: 1}),
|
||||
Token::new("lvl1", Position{line: 1, column: 1}),
|
||||
Token::new("lvl2", Position{line: 1, column: 1})], 1, 1))),
|
||||
Val::Int(3)),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var2")]))),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var2", Position{line: 1, column: 1})], 1, 1))),
|
||||
Val::Int(2)),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var3"),
|
||||
Token::new("lvl1")]))),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var3", Position{line: 1, column: 1}),
|
||||
Token::new("lvl1", Position{line: 1, column: 1})], 1, 1))),
|
||||
Val::Int(4)),
|
||||
], b);
|
||||
}
|
||||
@ -945,7 +943,7 @@ mod test {
|
||||
fn test_expr_copy_no_such_tuple() {
|
||||
let b = Builder::new();
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Copy(CopyDef{selector: vec![Token::new("tpl1")], fields: Vec::new(), pos: None}),
|
||||
(Expression::Copy(CopyDef{selector: vec![Token::new("tpl1", Position{line: 1, column: 1})], fields: Vec::new(), pos: None}),
|
||||
Val::Tuple(Vec::new())),
|
||||
], b);
|
||||
}
|
||||
@ -954,9 +952,9 @@ mod test {
|
||||
#[should_panic(expected = "Expected Tuple got Integer")]
|
||||
fn test_expr_copy_not_a_tuple() {
|
||||
let mut b = Builder::new();
|
||||
b.out.entry("tpl1".to_string()).or_insert(Rc::new(Val::Int(1)));
|
||||
b.out.entry(Positioned::new("tpl1".to_string())).or_insert(Rc::new(Val::Int(1)));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Copy(CopyDef{selector: vec![Token::new("tpl1")], fields: Vec::new(), pos: None}),
|
||||
(Expression::Copy(CopyDef{selector: vec![Token::new("tpl1", Position{line: 1, column: 1})], fields: Vec::new(), pos: None}),
|
||||
Val::Tuple(Vec::new())),
|
||||
], b);
|
||||
}
|
||||
@ -965,19 +963,19 @@ mod test {
|
||||
#[should_panic(expected = "Expected type Integer for field fld1 but got String")]
|
||||
fn test_expr_copy_field_type_error() {
|
||||
let mut b = Builder::new();
|
||||
b.out.entry("tpl1".to_string()).or_insert(Rc::new(Val::Tuple(vec![
|
||||
b.out.entry(Positioned::new("tpl1".to_string())).or_insert(Rc::new(Val::Tuple(vec![
|
||||
(Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))),
|
||||
])));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Copy(
|
||||
CopyDef{
|
||||
selector: vec![Token::new("tpl1")],
|
||||
fields: vec![(Token::new("fld1"),
|
||||
Expression::Simple(Value::String(make_value_node("2".to_string()))))],
|
||||
selector: vec![Token::new("tpl1", Position{line: 1, column: 1})],
|
||||
fields: vec![(Token::new("fld1", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1))))],
|
||||
pos: None}),
|
||||
Val::Tuple(
|
||||
vec![
|
||||
(Positioned::new("fld1".to_string()), Rc::new(Val::String("2".to_string()))),
|
||||
(Positioned::new_with_pos("fld1".to_string(), Position{line: 1, column: 1}), Rc::new(Val::String("2".to_string()))),
|
||||
],
|
||||
)),
|
||||
], b);
|
||||
@ -989,15 +987,15 @@ mod test {
|
||||
fn test_expr_copy() {
|
||||
// TODO(jwall): Tests for this expression.
|
||||
let mut b = Builder::new();
|
||||
b.out.entry("tpl1".to_string()).or_insert(Rc::new(Val::Tuple(vec![
|
||||
b.out.entry(Positioned::new("tpl1".to_string())).or_insert(Rc::new(Val::Tuple(vec![
|
||||
(Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))),
|
||||
])));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Copy(
|
||||
CopyDef{
|
||||
selector: vec![Token::new("tpl1")],
|
||||
fields: vec![(Token::new("fld2"),
|
||||
Expression::Simple(Value::String(make_value_node("2".to_string()))))],
|
||||
selector: vec![Token::new("tpl1", Position{line: 1, column: 1})],
|
||||
fields: vec![(Token::new("fld2", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1))))],
|
||||
pos: None,
|
||||
}),
|
||||
// Add a new field to the copy
|
||||
@ -1007,18 +1005,18 @@ mod test {
|
||||
// semantics though so at some point we should probably be less restrictive.
|
||||
vec![
|
||||
(Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))),
|
||||
(Positioned::new("fld2".to_string()), Rc::new(Val::String("2".to_string()))),
|
||||
(Positioned::new_with_pos("fld2".to_string(), Position{line: 1, column: 1}), Rc::new(Val::String("2".to_string()))),
|
||||
],
|
||||
)),
|
||||
// Overwrite a field in the copy
|
||||
(Expression::Copy(
|
||||
CopyDef{
|
||||
selector: vec![Token::new("tpl1")],
|
||||
selector: vec![Token::new("tpl1", Position{line: 1, column: 1})],
|
||||
fields: vec![
|
||||
(Token::new("fld1"),
|
||||
Expression::Simple(Value::Int(make_value_node(3)))),
|
||||
(Token::new("fld2"),
|
||||
Expression::Simple(Value::String(make_value_node("2".to_string())))),
|
||||
(Token::new("fld1", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::Int(make_value_node(3, 1, 1)))),
|
||||
(Token::new("fld2", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1)))),
|
||||
],
|
||||
pos: None,
|
||||
}),
|
||||
@ -1029,7 +1027,7 @@ mod test {
|
||||
],
|
||||
)),
|
||||
// The source tuple is still unmodified.
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("tpl1")]))),
|
||||
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("tpl1", Position{line: 1, column: 1})], 1, 1))),
|
||||
Val::Tuple(
|
||||
vec![
|
||||
(Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))),
|
||||
@ -1041,21 +1039,21 @@ mod test {
|
||||
#[test]
|
||||
fn test_macro_call() {
|
||||
let mut b = Builder::new();
|
||||
b.out.entry("tstmac".to_string()).or_insert(Rc::new(Val::Macro(MacroDef{
|
||||
b.out.entry(Positioned::new("tstmac".to_string())).or_insert(Rc::new(Val::Macro(MacroDef{
|
||||
argdefs: vec![Positioned::new("arg1".to_string())],
|
||||
fields: vec![
|
||||
(Token::new("foo"), Expression::Simple(Value::Symbol(make_value_node("arg1".to_string())))),
|
||||
(Token::new("foo", Position{line: 1, column: 1}), Expression::Simple(Value::Symbol(make_value_node("arg1".to_string(), 1, 1)))),
|
||||
],
|
||||
pos: None,
|
||||
})));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Call(CallDef{
|
||||
macroref: vec![Token::new("tstmac")],
|
||||
arglist: vec![Expression::Simple(Value::String(make_value_node("bar".to_string())))],
|
||||
macroref: vec![Token::new("tstmac", Position{line: 1, column: 1})],
|
||||
arglist: vec![Expression::Simple(Value::String(make_value_node("bar".to_string(), 1, 1)))],
|
||||
pos: None,
|
||||
}),
|
||||
Val::Tuple(vec![
|
||||
(Positioned::new_with_pos("foo".to_string(), Position{line: 0, column: 0}),
|
||||
(Positioned::new_with_pos("foo".to_string(), Position{line: 1, column: 1}),
|
||||
Rc::new(Val::String("bar".to_string()))),
|
||||
])),
|
||||
], b);
|
||||
@ -1066,19 +1064,19 @@ mod test {
|
||||
fn test_macro_hermetic() {
|
||||
let mut b = Builder::new();
|
||||
b.out
|
||||
.entry("arg1".to_string())
|
||||
.entry(Positioned::new("arg1".to_string()))
|
||||
.or_insert(Rc::new(Val::String("bar".to_string())));
|
||||
b.out.entry("tstmac".to_string()).or_insert(Rc::new(Val::Macro(MacroDef{
|
||||
b.out.entry(Positioned::new("tstmac".to_string())).or_insert(Rc::new(Val::Macro(MacroDef{
|
||||
argdefs: vec![Positioned::new("arg2".to_string())],
|
||||
fields: vec![
|
||||
(Token::new("foo"), Expression::Simple(Value::Symbol(make_value_node("arg1".to_string())))),
|
||||
(Token::new("foo", Position{line: 1, column: 1}), Expression::Simple(Value::Symbol(make_value_node("arg1".to_string(), 1, 1)))),
|
||||
],
|
||||
pos: None,
|
||||
})));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Call(CallDef{
|
||||
macroref: vec![Token::new("tstmac")],
|
||||
arglist: vec![Expression::Simple(Value::String(make_value_node("bar".to_string())))],
|
||||
macroref: vec![Token::new("tstmac", Position{line: 1, column: 1})],
|
||||
arglist: vec![Expression::Simple(Value::String(make_value_node("bar".to_string(), 1, 1)))],
|
||||
pos: None,
|
||||
}),
|
||||
Val::Tuple(vec![
|
||||
@ -1091,28 +1089,28 @@ mod test {
|
||||
fn test_select_expr() {
|
||||
let mut b = Builder::new();
|
||||
b.out
|
||||
.entry("foo".to_string())
|
||||
.entry(Positioned::new("foo".to_string()))
|
||||
.or_insert(Rc::new(Val::String("bar".to_string())));
|
||||
b.out
|
||||
.entry("baz".to_string())
|
||||
.entry(Positioned::new("baz".to_string()))
|
||||
.or_insert(Rc::new(Val::String("boo".to_string())));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Select(SelectDef{
|
||||
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("foo".to_string())))),
|
||||
default: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("foo".to_string(), 1, 1)))),
|
||||
default: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
tuple: vec![
|
||||
(Token::new("foo"), Expression::Simple(Value::String(make_value_node("2".to_string())))),
|
||||
(Token::new("bar"), Expression::Simple(Value::Int(make_value_node(2)))),
|
||||
(Token::new("foo", Position{line: 1, column: 1}), Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1)))),
|
||||
(Token::new("bar", Position{line: 1, column: 1}), Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
|
||||
],
|
||||
pos: None,
|
||||
}),
|
||||
Val::Int(2)),
|
||||
(Expression::Select(SelectDef{
|
||||
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("baz".to_string())))),
|
||||
default: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("baz".to_string(), 1, 1)))),
|
||||
default: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
tuple: vec![
|
||||
(Token::new("bar"), Expression::Simple(Value::Int(make_value_node(2)))),
|
||||
(Token::new("quux"), Expression::Simple(Value::String(make_value_node("2".to_string())))),
|
||||
(Token::new("bar", Position{line: 1, column: 1}), Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
|
||||
(Token::new("quux", Position{line: 1, column: 1}), Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1)))),
|
||||
],
|
||||
pos: None,
|
||||
}),
|
||||
@ -1125,14 +1123,14 @@ mod test {
|
||||
#[should_panic(expected ="Expected String but got Integer in Select expression")]
|
||||
fn test_select_expr_not_a_string() {
|
||||
let mut b = Builder::new();
|
||||
b.out.entry("foo".to_string()).or_insert(Rc::new(Val::Int(4)));
|
||||
b.out.entry(Positioned::new("foo".to_string())).or_insert(Rc::new(Val::Int(4)));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Select(SelectDef{
|
||||
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("foo".to_string())))),
|
||||
default: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
|
||||
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("foo".to_string(), 1, 1)))),
|
||||
default: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
|
||||
tuple: vec![
|
||||
(Token::new("bar"), Expression::Simple(Value::Int(make_value_node(2)))),
|
||||
(Token::new("quux"), Expression::Simple(Value::String(make_value_node("2".to_string())))),
|
||||
(Token::new("bar", Position{line: 1, column: 1}), Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
|
||||
(Token::new("quux", Position{line: 1, column: 1}), Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1)))),
|
||||
],
|
||||
pos: None,
|
||||
}),
|
||||
@ -1144,12 +1142,12 @@ mod test {
|
||||
fn test_let_statement() {
|
||||
let mut b = Builder::new();
|
||||
let stmt = Statement::Let {
|
||||
name: Token::new("foo"),
|
||||
value: Expression::Simple(Value::String(make_value_node("bar".to_string()))),
|
||||
name: Token::new("foo", Position{line: 1, column: 1}),
|
||||
value: Expression::Simple(Value::String(make_value_node("bar".to_string(), 1, 1))),
|
||||
};
|
||||
b.build_stmt(&stmt).unwrap();
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Simple(Value::Symbol(make_value_node("foo".to_string()))),
|
||||
(Expression::Simple(Value::Symbol(make_value_node("foo".to_string(), 1, 1))),
|
||||
Val::String("bar".to_string())),
|
||||
],
|
||||
b);
|
||||
@ -1159,20 +1157,20 @@ mod test {
|
||||
fn test_build_file_string() {
|
||||
let mut b = Builder::new();
|
||||
b.build_file_string("foo.ucg", "let foo = 1;".to_string()).unwrap();
|
||||
let key = "foo";
|
||||
assert!(b.out.contains_key(key));
|
||||
let key = Positioned::new("foo".to_string());
|
||||
assert!(b.out.contains_key(&key));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_asset_symbol_lookups() {
|
||||
let mut b = Builder::new();
|
||||
b.assets.entry("foo".to_string()).or_insert(Rc::new(Val::Tuple(vec![
|
||||
b.assets.entry(Positioned::new("foo".to_string())).or_insert(Rc::new(Val::Tuple(vec![
|
||||
(Positioned::new("bar".to_string()), Rc::new(Val::Tuple(vec![
|
||||
(Positioned::new("quux".to_string()), Rc::new(Val::Int(1))),
|
||||
]))),
|
||||
])));
|
||||
test_expr_to_val(vec![
|
||||
(Expression::Simple(Value::Symbol(make_value_node("foo".to_string()))),
|
||||
(Expression::Simple(Value::Symbol(make_value_node("foo".to_string(), 1, 1))),
|
||||
Val::Tuple(vec![
|
||||
(Positioned::new("bar".to_string()), Rc::new(Val::Tuple(vec![
|
||||
(Positioned::new("quux".to_string()), Rc::new(Val::Int(1))),
|
||||
|
355
src/parse.rs
355
src/parse.rs
@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
use std::str::FromStr;
|
||||
use std::error::Error;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use ast::*;
|
||||
use tokenizer::*;
|
||||
@ -32,20 +33,19 @@ quick_error! {
|
||||
}
|
||||
|
||||
|
||||
// TODO(jwall): Convert to tokenizer steps followed by parser steps.
|
||||
// TODO(jwall): Error Reporting with Line and Column information.
|
||||
|
||||
type ParseResult<O> = Result<O, Box<Error>>;
|
||||
|
||||
fn symbol_to_value(s: Token) -> ParseResult<Value> {
|
||||
Ok(Value::Symbol(value_node!(s.fragment.to_string())))
|
||||
Ok(Value::Symbol(value_node!(s.fragment.to_string(), s.pos)))
|
||||
}
|
||||
|
||||
// symbol is a bare unquoted field.
|
||||
named!(symbol( Span ) -> Value, map_res!(barewordtok, symbol_to_value));
|
||||
|
||||
fn str_to_value(s: Token) -> ParseResult<Value> {
|
||||
Ok(Value::String(value_node!(s.fragment.to_string())))
|
||||
Ok(Value::String(value_node!(s.fragment.to_string(), s.pos)))
|
||||
}
|
||||
|
||||
// quoted_value is a quoted string.
|
||||
@ -55,15 +55,19 @@ named!(quoted_value( Span ) -> Value,
|
||||
|
||||
// Helper function to make the return types work for down below.
|
||||
fn triple_to_number(v: (Option<Token>, Option<Token>, Option<Token>)) -> ParseResult<Value> {
|
||||
let pref = match v.0 {
|
||||
None => "",
|
||||
Some(ref bs) => &bs.fragment,
|
||||
let (pref, mut pref_pos) = match v.0 {
|
||||
None => ("", Position{line: 0, column: 0}),
|
||||
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() {
|
||||
return Ok(Value::Int(value_node!(try!(FromStr::from_str(pref)))));
|
||||
return Ok(Value::Int(value_node!(try!(FromStr::from_str(pref)), pref_pos)));
|
||||
}
|
||||
|
||||
if v.0.is_none() && has_dot {
|
||||
pref_pos = v.1.unwrap().pos;
|
||||
}
|
||||
|
||||
let suf = match v.2 {
|
||||
@ -72,8 +76,9 @@ fn triple_to_number(v: (Option<Token>, Option<Token>, Option<Token>)) -> ParseRe
|
||||
};
|
||||
|
||||
let to_parse = pref.to_string() + "." + suf;
|
||||
// TODO(jwall): if there is an error we should report where that error occured.
|
||||
let f = try!(FromStr::from_str(&to_parse));
|
||||
return Ok(Value::Float(value_node!(f)));
|
||||
return Ok(Value::Float(value_node!(f, pref_pos)));
|
||||
}
|
||||
|
||||
// NOTE(jwall): HERE THERE BE DRAGONS. The order for these matters
|
||||
@ -130,8 +135,8 @@ named!(
|
||||
);
|
||||
|
||||
// Helper function to make the return types work for down below.
|
||||
fn vec_to_tuple(v: FieldList) -> ParseResult<Value> {
|
||||
Ok(Value::Tuple(value_node!(v)))
|
||||
fn vec_to_tuple(t: (Span, FieldList)) -> ParseResult<Value> {
|
||||
Ok(Value::Tuple(value_node!(t.1, Position{line: t.0.line as usize, column: t.0.offset as usize})))
|
||||
}
|
||||
|
||||
named!(field_list( Span ) -> FieldList,
|
||||
@ -141,9 +146,13 @@ named!(
|
||||
#[doc="Capture a tuple of named fields with values. {<field>=<value>,...}"],
|
||||
tuple( Span ) -> Value,
|
||||
map_res!(
|
||||
delimited!(lbracetok,
|
||||
do_parse!(
|
||||
pos: position!() >>
|
||||
v: delimited!(lbracetok,
|
||||
ws!(field_list),
|
||||
rbracetok),
|
||||
rbracetok) >>
|
||||
(pos, v)
|
||||
),
|
||||
vec_to_tuple
|
||||
)
|
||||
);
|
||||
@ -161,12 +170,12 @@ named!(simple_expression( Span ) -> Expression,
|
||||
)
|
||||
);
|
||||
|
||||
fn tuple_to_binary_expression(tpl: (BinaryExprType, Value, Expression)) -> ParseResult<Expression> {
|
||||
fn tuple_to_binary_expression(tpl: (Span, BinaryExprType, Value, Expression)) -> ParseResult<Expression> {
|
||||
Ok(Expression::Binary(BinaryOpDef {
|
||||
kind: tpl.0,
|
||||
left: tpl.1,
|
||||
right: Box::new(tpl.2),
|
||||
pos: None,
|
||||
kind: tpl.1,
|
||||
left: tpl.2,
|
||||
right: Box::new(tpl.3),
|
||||
pos: Some(Position{line: tpl.0.line as usize, column: tpl.0.offset as usize}),
|
||||
}))
|
||||
}
|
||||
|
||||
@ -178,10 +187,11 @@ macro_rules! do_binary_expr {
|
||||
// particularly like this but I'm living with it for now.
|
||||
map_res!(
|
||||
$i, do_parse!(
|
||||
pos: position!() >>
|
||||
left: value >>
|
||||
ws!($fn) >>
|
||||
right: expression >>
|
||||
($typ, left, right)
|
||||
(pos, $typ, left, right)
|
||||
),
|
||||
tuple_to_binary_expression
|
||||
)
|
||||
@ -222,7 +232,6 @@ fn assert_nonempty_list<T>(v: Vec<T>) -> ParseResult<Vec<T>> {
|
||||
return Ok(v);
|
||||
}
|
||||
|
||||
// TODO(jwall): We should assert that this is a nonempty list that comes out of here.
|
||||
named!(selector_list( Span ) -> SelectorList,
|
||||
map_res!(
|
||||
separated_list!(dottok, barewordtok),
|
||||
@ -230,43 +239,43 @@ named!(selector_list( Span ) -> SelectorList,
|
||||
)
|
||||
);
|
||||
|
||||
fn tuple_to_copy(t: (SelectorList, FieldList)) -> ParseResult<Expression> {
|
||||
fn tuple_to_copy(t: (Span, SelectorList, FieldList)) -> ParseResult<Expression> {
|
||||
Ok(Expression::Copy(CopyDef {
|
||||
selector: t.0,
|
||||
fields: t.1,
|
||||
pos: None,
|
||||
selector: t.1,
|
||||
fields: t.2,
|
||||
pos: Some(Position{line: t.0.line as usize, column: t.0.offset as usize}),
|
||||
}))
|
||||
}
|
||||
|
||||
named!(copy_expression( Span ) -> Expression,
|
||||
map_res!(
|
||||
do_parse!(
|
||||
pos: position!() >>
|
||||
selector: selector_list >>
|
||||
lbracetok >>
|
||||
fields: ws!(field_list) >>
|
||||
rbracetok >>
|
||||
(selector, fields)
|
||||
(pos, selector, fields)
|
||||
),
|
||||
tuple_to_copy
|
||||
)
|
||||
);
|
||||
|
||||
fn tuple_to_macro(mut t: (Vec<Value>, Value)) -> ParseResult<Expression> {
|
||||
match t.1 {
|
||||
fn tuple_to_macro(mut t: (Span, Vec<Value>, Value)) -> ParseResult<Expression> {
|
||||
match t.2 {
|
||||
Value::Tuple(v) => {
|
||||
Ok(Expression::Macro(MacroDef {
|
||||
// TODO(jwall): The position information here is not as accurate as we might want.
|
||||
argdefs: t.0
|
||||
argdefs: t.1
|
||||
.drain(0..)
|
||||
.map(|s| {
|
||||
Positioned {
|
||||
pos: v.pos.clone(),
|
||||
pos: Some(s.pos().clone()),
|
||||
val: s.to_string(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
fields: v.val,
|
||||
pos: v.pos,
|
||||
pos: Some(Position{line: t.0.line as usize, column: t.0.offset as usize}),
|
||||
}))
|
||||
}
|
||||
// TODO(jwall): Show a better version of the unexpected parsed value.
|
||||
@ -281,26 +290,27 @@ named!(arglist( Span ) -> Vec<Value>, separated_list!(ws!(commatok), symbol));
|
||||
named!(macro_expression( Span ) -> Expression,
|
||||
map_res!(
|
||||
do_parse!(
|
||||
pos: position!() >>
|
||||
macrotok >>
|
||||
ws!(lparentok) >>
|
||||
arglist: ws!(arglist) >>
|
||||
rparentok >>
|
||||
ws!(fatcommatok) >>
|
||||
map: tuple >>
|
||||
(arglist, map)
|
||||
(pos, arglist, map)
|
||||
),
|
||||
tuple_to_macro
|
||||
)
|
||||
);
|
||||
|
||||
fn tuple_to_select(t: (Expression, Expression, Value)) -> ParseResult<Expression> {
|
||||
match t.2 {
|
||||
fn tuple_to_select(t: (Span, Expression, Expression, Value)) -> ParseResult<Expression> {
|
||||
match t.3 {
|
||||
Value::Tuple(v) => {
|
||||
Ok(Expression::Select(SelectDef {
|
||||
val: Box::new(t.0),
|
||||
default: Box::new(t.1),
|
||||
val: Box::new(t.1),
|
||||
default: Box::new(t.2),
|
||||
tuple: v.val,
|
||||
pos: None,
|
||||
pos: Some(Position{line: t.0.line as usize, column: t.0.offset as usize}),
|
||||
}))
|
||||
}
|
||||
// TODO(jwall): Show a better version of the unexpected parsed value.
|
||||
@ -313,11 +323,12 @@ fn tuple_to_select(t: (Expression, Expression, Value)) -> ParseResult<Expression
|
||||
named!(select_expression( Span ) -> Expression,
|
||||
map_res!(
|
||||
do_parse!(
|
||||
pos: position!() >>
|
||||
selecttok >>
|
||||
val: ws!(terminated!(expression, commatok)) >>
|
||||
default: ws!(terminated!(expression, commatok)) >>
|
||||
map: ws!(tuple) >>
|
||||
(val, default, map)
|
||||
(pos, val, default, map)
|
||||
),
|
||||
tuple_to_select
|
||||
)
|
||||
@ -345,25 +356,29 @@ named!(format_expression( Span ) -> Expression,
|
||||
)
|
||||
);
|
||||
|
||||
fn tuple_to_call(t: (Value, Vec<Expression>)) -> ParseResult<Expression> {
|
||||
if let Value::Selector(sl) = t.0 {
|
||||
fn tuple_to_call(t: (Span, Value, Vec<Expression>)) -> ParseResult<Expression> {
|
||||
if let Value::Selector(sl) = t.1 {
|
||||
Ok(Expression::Call(CallDef {
|
||||
macroref: sl.val,
|
||||
arglist: t.1,
|
||||
pos: None,
|
||||
arglist: t.2,
|
||||
pos: Some(Position{line: t.0.line as usize, column: t.0.offset as usize}),
|
||||
}))
|
||||
} else {
|
||||
Err(Box::new(ParseError::UnexpectedToken("Selector".to_string(), format!("{:?}", t.0))))
|
||||
}
|
||||
}
|
||||
|
||||
fn vec_to_selector_value(v: SelectorList) -> ParseResult<Value> {
|
||||
Ok(Value::Selector(value_node!(v)))
|
||||
fn vec_to_selector_value(t: (Span, SelectorList)) -> ParseResult<Value> {
|
||||
Ok(Value::Selector(value_node!(t.1, Position{line: t.0.line as usize, column: t.0.offset as usize})))
|
||||
}
|
||||
|
||||
named!(selector_value( Span ) -> Value,
|
||||
map_res!(
|
||||
ws!(selector_list),
|
||||
do_parse!(
|
||||
pos: position!() >>
|
||||
sl: ws!(selector_list) >>
|
||||
(pos, sl)
|
||||
),
|
||||
vec_to_selector_value
|
||||
)
|
||||
);
|
||||
@ -371,11 +386,12 @@ named!(selector_value( Span ) -> Value,
|
||||
named!(call_expression( Span ) -> Expression,
|
||||
map_res!(
|
||||
do_parse!(
|
||||
pos: position!() >>
|
||||
macroname: selector_value >>
|
||||
lparentok >>
|
||||
args: ws!(separated_list!(ws!(commatok), expression)) >>
|
||||
rparentok >>
|
||||
(macroname, args)
|
||||
(pos, macroname, args)
|
||||
),
|
||||
tuple_to_call
|
||||
)
|
||||
@ -468,8 +484,6 @@ named!(statement( Span ) -> Statement,
|
||||
|
||||
named!(pub parse( Span ) -> Vec<Statement>, many1!(ws!(statement)));
|
||||
|
||||
// TODO(jwall): Full Statement parsing tests.
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Statement, Expression, Value, MacroDef, SelectDef, CallDef};
|
||||
@ -525,7 +539,7 @@ mod test {
|
||||
column: 5,
|
||||
},
|
||||
},
|
||||
value: Expression::Simple(Value::Float(value_node!(1.0)))
|
||||
value: Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 11})))
|
||||
}));
|
||||
stmt = "1.0;";
|
||||
let input = LocatedSpan::new(stmt);
|
||||
@ -537,7 +551,7 @@ mod test {
|
||||
fragment: "",
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::Float(value_node!(1.0))))));
|
||||
Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 1}))))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -593,7 +607,7 @@ mod test {
|
||||
column: 5,
|
||||
},
|
||||
},
|
||||
value: Expression::Simple(Value::Float(value_node!(1.0)))
|
||||
value: Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 11})))
|
||||
}));
|
||||
|
||||
let_stmt = "let foo= 1.0;";
|
||||
@ -610,7 +624,7 @@ mod test {
|
||||
column: 5,
|
||||
}
|
||||
},
|
||||
value: Expression::Simple(Value::Float(value_node!(1.0)))}));
|
||||
value: Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 10})))}));
|
||||
let_stmt = "let foo =1.0;";
|
||||
assert_eq!(let_statement(LocatedSpan::new(let_stmt)),
|
||||
IResult::Done(LocatedSpan{
|
||||
@ -625,7 +639,7 @@ mod test {
|
||||
column: 5,
|
||||
}
|
||||
},
|
||||
value: Expression::Simple(Value::Float(value_node!(1.0)))}));
|
||||
value: Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 10})))}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -638,7 +652,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::Float(value_node!(1.0))))));
|
||||
Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 1}))))));
|
||||
assert_eq!(expression_statement(LocatedSpan::new("1.0 ;")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -646,7 +660,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::Float(value_node!(1.0))))));
|
||||
Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 1}))))));
|
||||
assert_eq!(expression_statement(LocatedSpan::new(" 1.0;")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -654,7 +668,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::Float(value_node!(1.0))))));
|
||||
Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 2}))))));
|
||||
assert_eq!(expression_statement(LocatedSpan::new("foo;")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -662,7 +676,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::Symbol(value_node!("foo".to_string()))))));
|
||||
Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 1}))))));
|
||||
assert_eq!(expression_statement(LocatedSpan::new("foo ;")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -670,7 +684,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::Symbol(value_node!("foo".to_string()))))));
|
||||
Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 1}))))));
|
||||
assert_eq!(expression_statement(LocatedSpan::new(" foo;")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -678,7 +692,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::Symbol(value_node!("foo".to_string()))))));
|
||||
Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 2}))))));
|
||||
assert_eq!(expression_statement(LocatedSpan::new("\"foo\";")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -686,7 +700,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string()))))));
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 1}))))));
|
||||
assert_eq!(expression_statement(LocatedSpan::new("\"foo\" ;")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -694,7 +708,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string()))))));
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 1}))))));
|
||||
assert_eq!(expression_statement(LocatedSpan::new(" \"foo\";")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -702,7 +716,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string()))))));
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 2}))))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -713,14 +727,14 @@ mod test {
|
||||
offset: 1,
|
||||
line: 1,
|
||||
},
|
||||
Expression::Simple(Value::Int(value_node!(1)))));
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 1})))));
|
||||
assert_eq!(expression(LocatedSpan::new("foo")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
offset: 3,
|
||||
line: 1,
|
||||
},
|
||||
Expression::Simple(Value::Symbol(value_node!("foo".to_string())))));
|
||||
Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 1})))));
|
||||
assert_eq!(expression(LocatedSpan::new("1 + 1")),
|
||||
IResult::Done(LocatedSpan {
|
||||
fragment: "",
|
||||
@ -729,9 +743,9 @@ mod test {
|
||||
},
|
||||
Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 5})))),
|
||||
pos: Some(Position { line: 1, column: 0 }),
|
||||
})));
|
||||
assert_eq!(expression(LocatedSpan::new("1 - 1")),
|
||||
IResult::Done(LocatedSpan {
|
||||
@ -741,9 +755,9 @@ mod test {
|
||||
},
|
||||
Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Sub,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 5})))),
|
||||
pos: Some(Position { line: 1, column: 0 }),
|
||||
})));
|
||||
assert_eq!(expression(LocatedSpan::new("1 * 1")),
|
||||
IResult::Done(LocatedSpan {
|
||||
@ -753,9 +767,9 @@ mod test {
|
||||
},
|
||||
Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Mul,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 5})))),
|
||||
pos: Some(Position { line: 1, column: 0 }),
|
||||
})));
|
||||
assert_eq!(expression(LocatedSpan::new("1 / 1")),
|
||||
IResult::Done(LocatedSpan {
|
||||
@ -765,9 +779,9 @@ mod test {
|
||||
},
|
||||
Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Div,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 5})))),
|
||||
pos: Some(Position { line: 1, column: 0 }),
|
||||
})));
|
||||
|
||||
assert_eq!(expression(LocatedSpan::new("1+1")),
|
||||
@ -778,9 +792,9 @@ mod test {
|
||||
},
|
||||
Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 3})))),
|
||||
pos: Some(Position { line: 1, column: 0 }),
|
||||
})));
|
||||
assert_eq!(expression(LocatedSpan::new("1-1")),
|
||||
IResult::Done(LocatedSpan {
|
||||
@ -790,9 +804,9 @@ mod test {
|
||||
},
|
||||
Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Sub,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 3})))),
|
||||
pos: Some(Position { line: 1, column: 0 }),
|
||||
})));
|
||||
assert_eq!(expression(LocatedSpan::new("1*1")),
|
||||
IResult::Done(LocatedSpan {
|
||||
@ -802,9 +816,9 @@ mod test {
|
||||
},
|
||||
Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Mul,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 3})))),
|
||||
pos: Some(Position { line: 1, column: 0 }),
|
||||
})));
|
||||
assert_eq!(expression(LocatedSpan::new("1/1")),
|
||||
IResult::Done(LocatedSpan {
|
||||
@ -814,9 +828,9 @@ mod test {
|
||||
},
|
||||
Expression::Binary(BinaryOpDef{
|
||||
kind: BinaryExprType::Div,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 3})))),
|
||||
pos: Some(Position { line: 1, column: 0 }),
|
||||
})));
|
||||
let macro_expr = "macro (arg1, arg2) => { foo = arg1 }";
|
||||
assert_eq!(expression(LocatedSpan::new(macro_expr)),
|
||||
@ -827,14 +841,15 @@ mod test {
|
||||
},
|
||||
Expression::Macro(MacroDef{
|
||||
argdefs: vec![
|
||||
Positioned::new("arg1".to_string()),
|
||||
Positioned::new("arg2".to_string()),
|
||||
Positioned::new_with_pos("arg1".to_string(), Position{line: 1, column: 8}),
|
||||
Positioned::new_with_pos("arg2".to_string(), Position{line: 1, column: 14}),
|
||||
],
|
||||
fields: vec![
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 25}),
|
||||
Expression::Simple(Value::Symbol(value_node!("arg1".to_string())))),
|
||||
(Token::new("foo", Position{line: 1, column: 25}),
|
||||
Expression::Simple(Value::Symbol(value_node!("arg1".to_string(), Position{line: 1, column: 31})))),
|
||||
],
|
||||
pos: None,
|
||||
// FIXME(jwall): I think this is incorrect.
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -846,13 +861,13 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Expression::Select(SelectDef{
|
||||
val: Box::new(Expression::Simple(Value::Symbol(value_node!("foo".to_string())))),
|
||||
default: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
val: Box::new(Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 8})))),
|
||||
default: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 13})))),
|
||||
tuple: vec![
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 18}),
|
||||
Expression::Simple(Value::Int(value_node!(2))))
|
||||
(Token::new("foo", Position{line: 1, column: 18}),
|
||||
Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 24}))))
|
||||
],
|
||||
pos: None,
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -864,13 +879,13 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Expression::Call(CallDef{
|
||||
macroref: vec![Token::new_with_pos("foo", Position{line:1,column: 1}),
|
||||
Token::new_with_pos("bar", Position{line:1,column: 5})],
|
||||
macroref: vec![Token::new("foo", Position{line:1,column: 1}),
|
||||
Token::new("bar", Position{line:1,column: 5})],
|
||||
arglist: vec![
|
||||
Expression::Simple(Value::Int(value_node!(1))),
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string()))),
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 10}))),
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 13}))),
|
||||
],
|
||||
pos: None,
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -885,9 +900,9 @@ mod test {
|
||||
Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 2})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 6})))),
|
||||
pos: Some(Position { line: 1, column: 1 }),
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -913,8 +928,8 @@ mod test {
|
||||
Expression::Format(
|
||||
FormatDef{
|
||||
template: "foo @ @".to_string(),
|
||||
args: vec![Expression::Simple(Value::Int(value_node!(1))),
|
||||
Expression::Simple(Value::Int(value_node!(2)))],
|
||||
args: vec![Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 14}))),
|
||||
Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 17})))],
|
||||
pos: Some(Position{line: 1, column: 1}),
|
||||
}
|
||||
)
|
||||
@ -931,8 +946,8 @@ mod test {
|
||||
Expression::Format(
|
||||
FormatDef{
|
||||
template: "foo @ @".to_string(),
|
||||
args: vec![Expression::Simple(Value::Int(value_node!(1))),
|
||||
Expression::Simple(Value::Int(value_node!(2)))],
|
||||
args: vec![Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 12}))),
|
||||
Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 15})))],
|
||||
pos: Some(Position { line: 1, column: 1 }),
|
||||
}
|
||||
)
|
||||
@ -957,12 +972,12 @@ mod test {
|
||||
offset: copy_expr.len(),
|
||||
},
|
||||
Expression::Call(CallDef{
|
||||
macroref: vec![Token::new_with_pos("foo", Position{line:1, column: 1})],
|
||||
macroref: vec![Token::new("foo", Position{line:1, column: 1})],
|
||||
arglist: vec![
|
||||
Expression::Simple(Value::Int(value_node!(1))),
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string()))),
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 6}))),
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 9}))),
|
||||
],
|
||||
pos: None,
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -976,13 +991,13 @@ mod test {
|
||||
offset: copy_expr.len(),
|
||||
},
|
||||
Expression::Call(CallDef{
|
||||
macroref: vec![Token::new_with_pos("foo", Position{line: 1, column: 1}),
|
||||
Token::new_with_pos("bar", Position{line: 1, column: 5})],
|
||||
macroref: vec![Token::new("foo", Position{line: 1, column: 1}),
|
||||
Token::new("bar", Position{line: 1, column: 5})],
|
||||
arglist: vec![
|
||||
Expression::Simple(Value::Int(value_node!(1))),
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string()))),
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 10}))),
|
||||
Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 13}))),
|
||||
],
|
||||
pos: None,
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -1003,12 +1018,12 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Expression::Select(SelectDef{
|
||||
val: Box::new(Expression::Simple(Value::Symbol(value_node!("foo".to_string())))),
|
||||
default: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
val: Box::new(Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 8})))),
|
||||
default: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 13})))),
|
||||
tuple: vec![
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 18}), Expression::Simple(Value::Int(value_node!(2))))
|
||||
(Token::new("foo", Position{line: 1, column: 18}), Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 24}))))
|
||||
],
|
||||
pos: None,
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -1037,12 +1052,12 @@ mod test {
|
||||
line: 1
|
||||
},
|
||||
Expression::Macro(MacroDef{
|
||||
argdefs: vec![Positioned::new("arg1".to_string()),
|
||||
Positioned::new("arg2".to_string())],
|
||||
fields: vec![(Token::new_with_pos("foo", Position{line: 1, column: 24}), Expression::Simple(Value::Int(value_node!(1)))),
|
||||
(Token::new_with_pos("bar", Position{line: 1, column: 30}), Expression::Simple(Value::Int(value_node!(2))))
|
||||
argdefs: vec![Positioned::new_with_pos("arg1".to_string(), Position{line: 1, column: 8}),
|
||||
Positioned::new_with_pos("arg2".to_string(), Position{line: 1, column: 14})],
|
||||
fields: vec![(Token::new("foo", Position{line: 1, column: 24}), Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 28})))),
|
||||
(Token::new("bar", Position{line: 1, column: 30}), Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 34}))))
|
||||
],
|
||||
pos: None,
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -1063,9 +1078,9 @@ mod test {
|
||||
line: 1
|
||||
},
|
||||
Expression::Copy(CopyDef{
|
||||
selector: vec![Token::new_with_pos("foo", Position{line: 1, column: 1})],
|
||||
selector: vec![Token::new("foo", Position{line: 1, column: 1})],
|
||||
fields: Vec::new(),
|
||||
pos: None,
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -1079,10 +1094,10 @@ mod test {
|
||||
line: 1
|
||||
},
|
||||
Expression::Copy(CopyDef{
|
||||
selector: vec![Token::new_with_pos("foo", Position{line: 1, column: 1})],
|
||||
fields: vec![(Token::new_with_pos("bar", Position{line: 1, column: 5}),
|
||||
Expression::Simple(Value::Int(value_node!(1))))],
|
||||
pos: None,
|
||||
selector: vec![Token::new("foo", Position{line: 1, column: 1})],
|
||||
fields: vec![(Token::new("bar", Position{line: 1, column: 5}),
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 9}))))],
|
||||
pos: Some(Position{line: 1, column: 0}),
|
||||
})
|
||||
)
|
||||
);
|
||||
@ -1097,7 +1112,7 @@ mod test {
|
||||
Expression::Grouped(
|
||||
Box::new(
|
||||
Expression::Simple(
|
||||
Value::Symbol(value_node!("foo".to_string()))))))
|
||||
Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 2}))))))
|
||||
);
|
||||
assert_eq!(grouped_expression(LocatedSpan::new("(1 + 1)")),
|
||||
IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1},
|
||||
@ -1106,10 +1121,10 @@ mod test {
|
||||
Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Int(value_node!(1)),
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 2})),
|
||||
right: Box::new(Expression::Simple(
|
||||
Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
Value::Int(value_node!(1, Position{line: 1, column: 6})))),
|
||||
pos: Some(Position { line: 1, column: 1 }),
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -1135,7 +1150,7 @@ mod test {
|
||||
line: 1,
|
||||
},
|
||||
Value::Tuple(
|
||||
value_node!(vec![]))));
|
||||
value_node!(vec![], Position{line: 1, column: 0}))));
|
||||
|
||||
tuple_expr = "{ foo = 1 }";
|
||||
assert_eq!(tuple(LocatedSpan::new(tuple_expr)),
|
||||
@ -1146,9 +1161,9 @@ mod test {
|
||||
},
|
||||
Value::Tuple(
|
||||
value_node!(vec![
|
||||
(Token::new_with_pos("foo", Position{line:1, column: 3}),
|
||||
Expression::Simple(Value::Int(value_node!(1))))
|
||||
]))));
|
||||
(Token::new("foo", Position{line:1, column: 3}),
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 9}))))
|
||||
], Position{line: 1, column: 0}))));
|
||||
|
||||
tuple_expr = "{ foo = 1, bar = \"1\" }";
|
||||
assert_eq!(tuple(LocatedSpan::new(tuple_expr)),
|
||||
@ -1159,11 +1174,11 @@ mod test {
|
||||
},
|
||||
Value::Tuple(
|
||||
value_node!(vec![
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 3}),
|
||||
Expression::Simple(Value::Int(value_node!(1)))),
|
||||
(Token::new_with_pos("bar", Position{line: 1, column: 12}),
|
||||
Expression::Simple(Value::String(value_node!("1".to_string()))))
|
||||
]))));
|
||||
(Token::new("foo", Position{line: 1, column: 3}),
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 9})))),
|
||||
(Token::new("bar", Position{line: 1, column: 12}),
|
||||
Expression::Simple(Value::String(value_node!("1".to_string(), Position{line: 1, column: 18}))))
|
||||
], Position{line: 1, column: 0}))));
|
||||
tuple_expr = "{ foo = 1, bar = {} }";
|
||||
assert_eq!(tuple(LocatedSpan::new(tuple_expr)),
|
||||
IResult::Done(LocatedSpan {
|
||||
@ -1173,11 +1188,11 @@ mod test {
|
||||
},
|
||||
Value::Tuple(
|
||||
value_node!(vec![
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 3}),
|
||||
Expression::Simple(Value::Int(value_node!(1)))),
|
||||
(Token::new_with_pos("bar", Position{line: 1, column: 12}),
|
||||
Expression::Simple(Value::Tuple(value_node!(Vec::new()))))
|
||||
]))));
|
||||
(Token::new("foo", Position{line: 1, column: 3}),
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 9})))),
|
||||
(Token::new("bar", Position{line: 1, column: 12}),
|
||||
Expression::Simple(Value::Tuple(value_node!(Vec::new(), Position{line: 1, column: 17}))))
|
||||
], Position{line: 1, column: 0}))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1187,20 +1202,20 @@ mod test {
|
||||
|
||||
assert_eq!(field_value(LocatedSpan::new("foo = 1")),
|
||||
IResult::Done(LocatedSpan { offset: 7, line: 1, fragment: "" },
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::Int(value_node!(1))))) );
|
||||
(Token::new("foo", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 7}))))) );
|
||||
assert_eq!(field_value(LocatedSpan::new("foo = \"1\"")),
|
||||
IResult::Done(LocatedSpan { offset: 9, line: 1, fragment: "" },
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::String(value_node!("1".to_string()))))) );
|
||||
(Token::new("foo", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::String(value_node!("1".to_string(), Position{line: 1, column: 7}))))) );
|
||||
assert_eq!(field_value(LocatedSpan::new("foo = bar")),
|
||||
IResult::Done(LocatedSpan { offset: 9, line: 1, fragment: "" },
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::Symbol(value_node!("bar".to_string()))))) );
|
||||
(Token::new("foo", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::Symbol(value_node!("bar".to_string(), Position{line: 1, column: 7}))))) );
|
||||
assert_eq!(field_value(LocatedSpan::new("foo = bar ")),
|
||||
IResult::Done(LocatedSpan { offset: 10, line: 1, fragment: "" },
|
||||
(Token::new_with_pos("foo", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::Symbol(value_node!("bar".to_string()))))) );
|
||||
(Token::new("foo", Position{line: 1, column: 1}),
|
||||
Expression::Simple(Value::Symbol(value_node!("bar".to_string(), Position{line: 1, column: 7}))))) );
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1209,29 +1224,29 @@ mod test {
|
||||
assert!(number(LocatedSpan::new(". ")).is_err() );
|
||||
assert_eq!(number(LocatedSpan::new("1.0")),
|
||||
IResult::Done(LocatedSpan{fragment: "", offset: 3, line: 1},
|
||||
Value::Float(value_node!(1.0))) );
|
||||
Value::Float(value_node!(1.0, Position{line: 1, column: 1}))) );
|
||||
assert_eq!(number(LocatedSpan::new("1.")),
|
||||
IResult::Done(LocatedSpan{fragment: "", offset: 2, line: 1},
|
||||
Value::Float(value_node!(1.0))) );
|
||||
Value::Float(value_node!(1.0, Position{line: 1, column: 1}))) );
|
||||
assert_eq!(number(LocatedSpan::new("1")),
|
||||
IResult::Done(LocatedSpan{fragment: "", offset: 1, line: 1},
|
||||
Value::Int(value_node!(1))) );
|
||||
Value::Int(value_node!(1, Position{line: 1, column: 1}))) );
|
||||
assert_eq!(number(LocatedSpan::new(".1")),
|
||||
IResult::Done(LocatedSpan{fragment: "", offset: 2, line: 1},
|
||||
Value::Float(value_node!(0.1))) );
|
||||
Value::Float(value_node!(0.1, Position{line: 1, column: 1}))) );
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_symbol_parsing() {
|
||||
assert_eq!(symbol(LocatedSpan::new("foo")),
|
||||
IResult::Done(LocatedSpan{fragment: "", offset: 3, line: 1},
|
||||
Value::Symbol(value_node!("foo".to_string()))) );
|
||||
Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 1}))) );
|
||||
assert_eq!(symbol(LocatedSpan::new("foo-bar")),
|
||||
IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1},
|
||||
Value::Symbol(value_node!("foo-bar".to_string()))) );
|
||||
Value::Symbol(value_node!("foo-bar".to_string(), Position{line: 1, column: 1}))) );
|
||||
assert_eq!(symbol(LocatedSpan::new("foo_bar")),
|
||||
IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1},
|
||||
Value::Symbol(value_node!("foo_bar".to_string()))) );
|
||||
Value::Symbol(value_node!("foo_bar".to_string(), Position{line: 1, column: 1}))) );
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1267,15 +1282,15 @@ mod test {
|
||||
column: 27,
|
||||
}
|
||||
},
|
||||
value: Expression::Simple(Value::Int(value_node!(1)))
|
||||
value: Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 33})))
|
||||
},
|
||||
Statement::Expression(
|
||||
Expression::Binary(
|
||||
BinaryOpDef{
|
||||
kind: BinaryExprType::Add,
|
||||
left: Value::Int(value_node!(1)),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))),
|
||||
pos: None,
|
||||
left: Value::Int(value_node!(1, Position{line: 1, column: 35})),
|
||||
right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 37})))),
|
||||
pos: Some(Position { line: 1, column: 34 }),
|
||||
})
|
||||
)
|
||||
]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user