Parse all namespaced identifiers
This commit is contained in:
parent
ef0fb0efc2
commit
6669460326
55
axc/foo.axs
55
axc/foo.axs
|
@ -1,8 +1,49 @@
|
||||||
// AlexScript
|
// AlexScript test
|
||||||
def double x = x * 2;
|
|
||||||
def tuple = (atan2 x y + z, thing);
|
|
||||||
|
|
||||||
def unary = -2;
|
extern def core::intrinsic::negate_u32 : U32 -> U32;
|
||||||
def minus = 2 - 2;
|
extern def core::intrinsic::pow_u32 : U32 -> U32 -> U32;
|
||||||
def unary_app = 2 (- 2);
|
extern def core::intrinsic::mul_u32 : U32 -> U32 -> U32;
|
||||||
def unary_double = 2 - - 2;
|
extern def core::intrinsic::div_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::mod_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::plus_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::minus_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::equal_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::notEqual_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::lessThan_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::lessThanEq_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::greaterThan_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::greaterThanEq_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::and_u32 : U32 -> U32 -> U32;
|
||||||
|
extern def core::intrinsic::or_u32 : U32 -> U32 -> U32;
|
||||||
|
|
||||||
|
extern data U32;
|
||||||
|
|
||||||
|
class Group n {
|
||||||
|
def plus : n -> n -> n;
|
||||||
|
def zero : n;
|
||||||
|
def negate : n -> n;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Group n => Ring n {
|
||||||
|
def mul : n -> n -> n;
|
||||||
|
def one : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance Group U32 {
|
||||||
|
def plus = core::intrinsic::plus_u32;
|
||||||
|
def zero = 0;
|
||||||
|
def negate = core::intrinsic::negate_u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance Ring U32 {
|
||||||
|
def mul = core::intrinsics::mul_u32;
|
||||||
|
def one = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern def print_u32 : U32 -> ();
|
||||||
|
|
||||||
|
// Impurity expliot to chain together actions.
|
||||||
|
def progn (l: ()) (r: ()) : () = ();
|
||||||
|
|
||||||
|
def main : () =
|
||||||
|
print_u32 (2 + 2);
|
||||||
|
|
|
@ -10,7 +10,7 @@ use chumsky::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::syntax::{
|
use crate::syntax::{
|
||||||
ClassMember, Expr, Literal, Pattern, Statement, SyntaxTree, Type, TypeConstructor,
|
ClassMember, Expr, Identifier, Literal, Pattern, Statement, SyntaxTree, Type, TypeConstructor,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Adapter to make `chumsky`'s parser errors usable as standard Rust errors.
|
/// Adapter to make `chumsky`'s parser errors usable as standard Rust errors.
|
||||||
|
@ -50,6 +50,9 @@ struct OperatorDef {
|
||||||
/// The associativity; if this is Left, then a X b X c is (a X b) X c; for Right, it is a X (b X
|
/// The associativity; if this is Left, then a X b X c is (a X b) X c; for Right, it is a X (b X
|
||||||
/// c); for None, it is a syntax error.
|
/// c); for None, it is a syntax error.
|
||||||
assoc: Option<Associativity>,
|
assoc: Option<Associativity>,
|
||||||
|
|
||||||
|
/// Function call that the binary operator gets translated to.
|
||||||
|
translation: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The possible associativity directions of an operator.
|
/// The possible associativity directions of an operator.
|
||||||
|
@ -70,11 +73,13 @@ impl Default for ParserMeta {
|
||||||
name: "^".to_string(),
|
name: "^".to_string(),
|
||||||
precedence: 8,
|
precedence: 8,
|
||||||
assoc: Some(Right),
|
assoc: Some(Right),
|
||||||
|
translation: "pow".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: "*".to_string(),
|
name: "*".to_string(),
|
||||||
precedence: 7,
|
precedence: 7,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "mul".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Division, which always returns an exact result and does not round to an
|
// Division, which always returns an exact result and does not round to an
|
||||||
|
@ -82,131 +87,146 @@ impl Default for ParserMeta {
|
||||||
name: "/".to_string(),
|
name: "/".to_string(),
|
||||||
precedence: 7,
|
precedence: 7,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "div".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Modulo, defined as Euclidean remainder.
|
// Modulo, defined as Euclidean remainder.
|
||||||
name: "%".to_string(),
|
name: "%".to_string(),
|
||||||
precedence: 7,
|
precedence: 7,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "mod".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: "+".to_string(),
|
name: "+".to_string(),
|
||||||
precedence: 6,
|
precedence: 6,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "plus".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: "-".to_string(),
|
name: "-".to_string(),
|
||||||
precedence: 6,
|
precedence: 6,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
},
|
translation: "minus".to_string(),
|
||||||
OperatorDef {
|
|
||||||
// Append to head of list. This might get removed since it's inefficient,
|
|
||||||
// depending.
|
|
||||||
name: "::".to_string(),
|
|
||||||
precedence: 5,
|
|
||||||
assoc: Some(Right),
|
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Append lists.
|
// Append lists.
|
||||||
name: "++".to_string(),
|
name: "++".to_string(),
|
||||||
precedence: 5,
|
precedence: 5,
|
||||||
assoc: Some(Right),
|
assoc: Some(Right),
|
||||||
|
translation: "append".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: "==".to_string(),
|
name: "==".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: None,
|
assoc: None,
|
||||||
|
translation: "equal".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: "!=".to_string(),
|
name: "!=".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: None,
|
assoc: None,
|
||||||
|
translation: "notEqual".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: "<".to_string(),
|
name: "<".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: None,
|
assoc: None,
|
||||||
|
translation: "lessThan".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: "<=".to_string(),
|
name: "<=".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: None,
|
assoc: None,
|
||||||
|
translation: "lessThanEq".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: ">".to_string(),
|
name: ">".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: None,
|
assoc: None,
|
||||||
|
translation: "greaterThan".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
name: ">=".to_string(),
|
name: ">=".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: None,
|
assoc: None,
|
||||||
|
translation: "greaterThanEq".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Functor map.
|
// Functor map.
|
||||||
name: "<$>".to_string(),
|
name: "<$>".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "fmap".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Functor map to constant.
|
// Functor map to constant.
|
||||||
name: "<$".to_string(),
|
name: "<$".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "fmapConst".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Flipped `<$`.
|
// Flipped `<$`.
|
||||||
name: "$>".to_string(),
|
name: "$>".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "fmapConstFlip".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Sequential application of applicative actions.
|
// Sequential application of applicative actions.
|
||||||
name: "<*>".to_string(),
|
name: "<*>".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "seqApp".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Sequence applicative actions, discarding the left value.
|
// Sequence applicative actions, discarding the left value.
|
||||||
name: "*>".to_string(),
|
name: "*>".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "seqAppRight".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Sequence applicative actions, discarding the right value.
|
// Sequence applicative actions, discarding the right value.
|
||||||
name: "<*".to_string(),
|
name: "<*".to_string(),
|
||||||
precedence: 4,
|
precedence: 4,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "seqAppLeft".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Binary and boolean `and`.
|
// Binary and boolean `and`.
|
||||||
name: "&".to_string(),
|
name: "&".to_string(),
|
||||||
precedence: 3,
|
precedence: 3,
|
||||||
assoc: Some(Right),
|
assoc: Some(Right),
|
||||||
|
translation: "and".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Binary and boolean `or`.
|
// Binary and boolean `or`.
|
||||||
name: "|".to_string(),
|
name: "|".to_string(),
|
||||||
precedence: 2,
|
precedence: 2,
|
||||||
assoc: Some(Right),
|
assoc: Some(Right),
|
||||||
|
translation: "or".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Monad sequence.
|
// Monad sequence.
|
||||||
name: ">>".to_string(),
|
name: ">>".to_string(),
|
||||||
precedence: 1,
|
precedence: 1,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "monadSeq".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Monad bind.
|
// Monad bind.
|
||||||
name: ">>=".to_string(),
|
name: ">>=".to_string(),
|
||||||
precedence: 1,
|
precedence: 1,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "monadBind".to_string(),
|
||||||
},
|
},
|
||||||
OperatorDef {
|
OperatorDef {
|
||||||
// Function application.
|
// Function application.
|
||||||
name: "$".to_string(),
|
name: "$".to_string(),
|
||||||
precedence: 1,
|
precedence: 1,
|
||||||
assoc: Some(Left),
|
assoc: Some(Left),
|
||||||
|
translation: "apply".to_string(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -272,7 +292,7 @@ fn parse_instance_def<'a>(
|
||||||
m: &'a ParserMeta,
|
m: &'a ParserMeta,
|
||||||
) -> impl Parser<char, Statement, Error = Simple<char>> + 'a {
|
) -> impl Parser<char, Statement, Error = Simple<char>> + 'a {
|
||||||
pad(keyword("instance"))
|
pad(keyword("instance"))
|
||||||
.ignore_then(pad(ident()))
|
.ignore_then(parse_identifier(m))
|
||||||
.then(parse_type(m))
|
.then(parse_type(m))
|
||||||
.then(
|
.then(
|
||||||
parse_class_member(m)
|
parse_class_member(m)
|
||||||
|
@ -302,7 +322,7 @@ fn parse_func_decl<'a>(
|
||||||
m: &'a ParserMeta,
|
m: &'a ParserMeta,
|
||||||
) -> impl Parser<char, ClassMember, Error = Simple<char>> + 'a {
|
) -> impl Parser<char, ClassMember, Error = Simple<char>> + 'a {
|
||||||
pad(keyword("def"))
|
pad(keyword("def"))
|
||||||
.ignore_then(pad(ident()))
|
.ignore_then(parse_identifier(m))
|
||||||
.then(parse_pattern(m).repeated())
|
.then(parse_pattern(m).repeated())
|
||||||
.then(pad(just('=')).ignore_then(parse_expression(m)).or_not())
|
.then(pad(just('=')).ignore_then(parse_expression(m)).or_not())
|
||||||
.then_ignore(pad(just(';')))
|
.then_ignore(pad(just(';')))
|
||||||
|
@ -325,7 +345,7 @@ fn parse_class_def<'a>(
|
||||||
m: &'a ParserMeta,
|
m: &'a ParserMeta,
|
||||||
) -> impl Parser<char, Statement, Error = Simple<char>> + 'a {
|
) -> impl Parser<char, Statement, Error = Simple<char>> + 'a {
|
||||||
pad(keyword("class"))
|
pad(keyword("class"))
|
||||||
.ignore_then(pad(ident()))
|
.ignore_then(parse_identifier(m))
|
||||||
.then(pad(ident()))
|
.then(pad(ident()))
|
||||||
.then(
|
.then(
|
||||||
parse_class_member(m)
|
parse_class_member(m)
|
||||||
|
@ -382,6 +402,7 @@ fn parse_unary(
|
||||||
ops.into_iter().fold(exp, |exp, op| Expr::UnaryOp {
|
ops.into_iter().fold(exp, |exp, op| Expr::UnaryOp {
|
||||||
kind: op.to_string(),
|
kind: op.to_string(),
|
||||||
val: Box::new(exp),
|
val: Box::new(exp),
|
||||||
|
translation: "negate".to_string(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -395,7 +416,7 @@ fn parse_binary<'a>(
|
||||||
let op_parsers = op_defs.map(|def| {
|
let op_parsers = op_defs.map(|def| {
|
||||||
pad(just(def.name.to_string()))
|
pad(just(def.name.to_string()))
|
||||||
.ignore_then(base.clone())
|
.ignore_then(base.clone())
|
||||||
.map(|e| (&def.name, &def.assoc, e))
|
.map(|e| (&def.name, &def.assoc, &def.translation, e))
|
||||||
});
|
});
|
||||||
|
|
||||||
let zero = one_of([]).map(|_| unreachable!()).boxed();
|
let zero = one_of([]).map(|_| unreachable!()).boxed();
|
||||||
|
@ -403,7 +424,7 @@ fn parse_binary<'a>(
|
||||||
let ops = any_op.repeated();
|
let ops = any_op.repeated();
|
||||||
|
|
||||||
base.then(ops).map(|(first, others)| {
|
base.then(ops).map(|(first, others)| {
|
||||||
let mut assocs = others.iter().map(|(_, assoc, _)| assoc);
|
let mut assocs = others.iter().map(|(_, assoc, _, _)| assoc);
|
||||||
let first_assoc = assocs.next();
|
let first_assoc = assocs.next();
|
||||||
if !first_assoc.map_or(true, |first| assocs.all(|a| a == first)) {
|
if !first_assoc.map_or(true, |first| assocs.all(|a| a == first)) {
|
||||||
// TODO: Crash the parser properly here, with error recovery etc.
|
// TODO: Crash the parser properly here, with error recovery etc.
|
||||||
|
@ -420,10 +441,13 @@ fn parse_binary<'a>(
|
||||||
None | Some(Associativity::Left) => {
|
None | Some(Associativity::Left) => {
|
||||||
others
|
others
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.fold(first, |left, (op_name, _assoc, right)| Expr::BinaryOp {
|
.fold(first, |left, (op_name, _assoc, translation, right)| {
|
||||||
|
Expr::BinaryOp {
|
||||||
kind: op_name.to_owned(),
|
kind: op_name.to_owned(),
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
right: Box::new(right),
|
right: Box::new(right),
|
||||||
|
translation: translation.to_string(),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some(Associativity::Right) => {
|
Some(Associativity::Right) => {
|
||||||
|
@ -443,23 +467,32 @@ fn parse_binary<'a>(
|
||||||
// . last
|
// . last
|
||||||
// others_l
|
// others_l
|
||||||
let others_l = std::iter::once(&first)
|
let others_l = std::iter::once(&first)
|
||||||
.chain(others.iter().map(|(_name, _assoc, expr)| expr))
|
.chain(
|
||||||
.zip(others.iter().map(|(name, _assoc, _expr)| name))
|
others
|
||||||
|
.iter()
|
||||||
|
.map(|(_name, _assoc, _translation, expr)| expr),
|
||||||
|
)
|
||||||
|
.zip(
|
||||||
|
others
|
||||||
|
.iter()
|
||||||
|
.map(|(name, _assoc, trans, _expr)| (name, trans)),
|
||||||
|
)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let last = others
|
let last = others
|
||||||
.iter()
|
.iter()
|
||||||
.last()
|
.last()
|
||||||
.map(|(_name, _assoc, expr)| expr)
|
.map(|(_name, _assoc, _translation, expr)| expr)
|
||||||
.unwrap_or(&first);
|
.unwrap_or(&first);
|
||||||
|
|
||||||
// And then we can fold as with left-associative operators.
|
// And then we can fold as with left-associative operators.
|
||||||
others_l
|
others_l
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.rev()
|
.rev()
|
||||||
.fold(last.to_owned(), |r, (l, op)| Expr::BinaryOp {
|
.fold(last.to_owned(), |r, (l, (op, trans))| Expr::BinaryOp {
|
||||||
kind: op.to_string(),
|
kind: op.to_string(),
|
||||||
left: Box::new(l.to_owned()),
|
left: Box::new(l.to_owned()),
|
||||||
right: Box::new(r),
|
right: Box::new(r),
|
||||||
|
translation: trans.to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -546,8 +579,7 @@ fn parse_subscript_expr(
|
||||||
pad(just('.'))
|
pad(just('.'))
|
||||||
.ignore_then(base)
|
.ignore_then(base)
|
||||||
.map(|e| (SubscriptKind::Dot, e)),
|
.map(|e| (SubscriptKind::Dot, e)),
|
||||||
rec
|
rec.delimited_by(pad(just('[')), pad(just(']')))
|
||||||
.delimited_by(pad(just('[')), pad(just(']')))
|
|
||||||
.map(|e| (SubscriptKind::Bracket, e)),
|
.map(|e| (SubscriptKind::Bracket, e)),
|
||||||
))
|
))
|
||||||
.repeated(),
|
.repeated(),
|
||||||
|
@ -581,11 +613,8 @@ fn parse_tuple_expr(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_var_ref_expr(_m: &ParserMeta) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
|
fn parse_var_ref_expr(m: &ParserMeta) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
|
||||||
pad(ident())
|
parse_identifier(m).map(Expr::VariableReference)
|
||||||
.separated_by(pad(just("::")))
|
|
||||||
.at_least(1)
|
|
||||||
.map(Expr::VariableReference)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_literal(_m: &ParserMeta) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
|
fn parse_literal(_m: &ParserMeta) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
|
||||||
|
@ -633,6 +662,15 @@ fn parse_literal(_m: &ParserMeta) -> impl Parser<char, Expr, Error = Simple<char
|
||||||
pad(choice((int, float, string))).map(Expr::Literal)
|
pad(choice((int, float, string))).map(Expr::Literal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_identifier(
|
||||||
|
_m: &ParserMeta,
|
||||||
|
) -> impl Parser<char, Identifier, Error = Simple<char>> + Clone {
|
||||||
|
pad(ident())
|
||||||
|
.separated_by(pad(just("::")))
|
||||||
|
.at_least(1)
|
||||||
|
.map(|elems| Identifier { elems })
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_type(m: &ParserMeta) -> impl Parser<char, Type, Error = Simple<char>> {
|
fn parse_type(m: &ParserMeta) -> impl Parser<char, Type, Error = Simple<char>> {
|
||||||
recursive(|rec| {
|
recursive(|rec| {
|
||||||
choice((
|
choice((
|
||||||
|
@ -654,8 +692,8 @@ fn parse_type(m: &ParserMeta) -> impl Parser<char, Type, Error = Simple<char>> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_named_type(_m: &ParserMeta) -> impl Parser<char, Type, Error = Simple<char>> {
|
fn parse_named_type(m: &ParserMeta) -> impl Parser<char, Type, Error = Simple<char>> {
|
||||||
pad(ident()).map(Type::Named)
|
parse_identifier(m).map(Type::Named)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_tuple_type(
|
fn parse_tuple_type(
|
||||||
|
@ -861,6 +899,13 @@ mod tests {
|
||||||
.is_ok())
|
.is_ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_char_binary() {
|
||||||
|
assert!(parser(&ParserMeta::default())
|
||||||
|
.parse("def x = 2 >= 3;")
|
||||||
|
.is_ok())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn app() {
|
fn app() {
|
||||||
assert!(parser(&ParserMeta::default())
|
assert!(parser(&ParserMeta::default())
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub enum Statement {
|
||||||
/// Declaration that a type implements a type class.
|
/// Declaration that a type implements a type class.
|
||||||
InstanceDefinition {
|
InstanceDefinition {
|
||||||
/// The name of the type class.
|
/// The name of the type class.
|
||||||
class_name: String,
|
class_name: Identifier,
|
||||||
|
|
||||||
/// The type that conforms to the type class.
|
/// The type that conforms to the type class.
|
||||||
typ: Type,
|
typ: Type,
|
||||||
|
@ -36,7 +36,7 @@ pub enum Statement {
|
||||||
/// Declaration of a type class.
|
/// Declaration of a type class.
|
||||||
ClassDefinition {
|
ClassDefinition {
|
||||||
/// The name of the class.
|
/// The name of the class.
|
||||||
name: String,
|
name: Identifier,
|
||||||
|
|
||||||
/// The type variable representing a type conforming to the class.
|
/// The type variable representing a type conforming to the class.
|
||||||
var: String,
|
var: String,
|
||||||
|
@ -58,7 +58,7 @@ pub enum ClassMember {
|
||||||
/// Declaration of a function or constant.
|
/// Declaration of a function or constant.
|
||||||
Function {
|
Function {
|
||||||
/// Name of the function.
|
/// Name of the function.
|
||||||
name: String,
|
name: Identifier,
|
||||||
|
|
||||||
/// The function arguments.
|
/// The function arguments.
|
||||||
arguments: Vec<Pattern>,
|
arguments: Vec<Pattern>,
|
||||||
|
@ -97,6 +97,9 @@ pub enum Expr {
|
||||||
|
|
||||||
/// The value being operated upon.
|
/// The value being operated upon.
|
||||||
val: Box<Expr>,
|
val: Box<Expr>,
|
||||||
|
|
||||||
|
/// The function that the unary operator translates to.
|
||||||
|
translation: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Binary operators, e.g., `5 + 5`.
|
/// Binary operators, e.g., `5 + 5`.
|
||||||
|
@ -109,6 +112,9 @@ pub enum Expr {
|
||||||
|
|
||||||
/// The right side of the operator.
|
/// The right side of the operator.
|
||||||
right: Box<Expr>,
|
right: Box<Expr>,
|
||||||
|
|
||||||
|
/// The function that the binary operator translates to.
|
||||||
|
translation: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Function application, e.g., `sin x`.
|
/// Function application, e.g., `sin x`.
|
||||||
|
@ -177,7 +183,7 @@ pub enum Expr {
|
||||||
Tuple(Vec<Expr>),
|
Tuple(Vec<Expr>),
|
||||||
|
|
||||||
/// Variable references, possibly namespaced, e.g., `foo::bar::baz`.
|
/// Variable references, possibly namespaced, e.g., `foo::bar::baz`.
|
||||||
VariableReference(Vec<String>),
|
VariableReference(Identifier),
|
||||||
|
|
||||||
/// Literal tokens, e.g., strings and numbers.
|
/// Literal tokens, e.g., strings and numbers.
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
|
@ -187,7 +193,7 @@ pub enum Expr {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
/// `Foo`
|
/// `Foo`
|
||||||
Named(String),
|
Named(Identifier),
|
||||||
|
|
||||||
/// `List Int`
|
/// `List Int`
|
||||||
Application {
|
Application {
|
||||||
|
@ -245,6 +251,13 @@ pub enum Pattern {
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Namespaced identifiers.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Identifier {
|
||||||
|
/// The elements of the identifier; there must be at least one of these.
|
||||||
|
pub elems: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Literal values included in source code.
|
/// Literal values included in source code.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
|
|
Loading…
Reference in a new issue