Start hooking up comb to tests
This commit is contained in:
parent
c1e6bc8c4c
commit
8ace37c5cf
@ -19,7 +19,7 @@ use crate::identifier::{Id, IdStore};
|
||||
|
||||
type StoreRef = Rc<RefCell<IdStore<ASTItem>>>;
|
||||
|
||||
type Span<'a> = LocatedSpan<&'a str, StoreRef>;
|
||||
pub type Span<'a> = LocatedSpan<&'a str, StoreRef>;
|
||||
type ParseResult<'a, O> = IResult<Span<'a>, O, VerboseError<Span<'a>>>;
|
||||
|
||||
use crate::ast::*;
|
||||
@ -108,7 +108,7 @@ fn statement(input: Span) -> ParseResult<Statement> {
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn expression(input: Span) -> ParseResult<Expression> {
|
||||
pub fn expression(input: Span) -> ParseResult<Expression> {
|
||||
let id = fresh_id(&input);
|
||||
map(pair(expression_kind, opt(type_anno)), move |(kind, maybe_anno)| Expression::new(id, kind))(input)
|
||||
}
|
||||
@ -136,8 +136,10 @@ pub fn expression_kind(input: Span) -> ParseResult<ExpressionKind> {
|
||||
}
|
||||
|
||||
fn precedence_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||
map(pair(prefix_expr, many0(precedence_continuation)),
|
||||
|(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| unimplemented!())(input)
|
||||
map(
|
||||
pair(prefix_expr, many0(precedence_continuation)),
|
||||
|(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| unimplemented!(),
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn precedence_continuation(input: Span) -> ParseResult<(BinOp, ExpressionKind)> {
|
||||
@ -145,41 +147,37 @@ fn precedence_continuation(input: Span) -> ParseResult<(BinOp, ExpressionKind)>
|
||||
}
|
||||
|
||||
fn operator(input: Span) -> ParseResult<BinOp> {
|
||||
tok(
|
||||
map(
|
||||
tuple((
|
||||
not(tag("*/")),
|
||||
recognize(many1(one_of("+-*/%<>=!$&|?^`"))),
|
||||
)), |(_, sigil_span): ((), Span)| BinOp::from_sigil(sigil_span.fragment())))(input)
|
||||
tok(map(
|
||||
tuple((not(tag("*/")), recognize(many1(one_of("+-*/%<>=!$&|?^`"))))),
|
||||
|(_, sigil_span): ((), Span)| BinOp::from_sigil(sigil_span.fragment()),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn prefix_op(input: Span) -> ParseResult<PrefixOp> {
|
||||
tok(
|
||||
map(recognize(one_of("+-!")),
|
||||
|sigil: Span| PrefixOp::from_sigil(sigil.fragment())))(input)
|
||||
tok(map(recognize(one_of("+-!")), |sigil: Span| PrefixOp::from_sigil(sigil.fragment())))(input)
|
||||
}
|
||||
|
||||
fn prefix_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||
let handle = input.extra.clone();
|
||||
context("prefix-expr",
|
||||
map(
|
||||
pair(opt(prefix_op), extended_expr), move |(prefix, expr)| {
|
||||
if let Some(prefix) = prefix {
|
||||
let expr = Expression::new(fresh_id_rc(&handle), expr);
|
||||
ExpressionKind::PrefixExp(prefix, Box::new(expr))
|
||||
} else {
|
||||
expr
|
||||
}
|
||||
}))(input)
|
||||
context(
|
||||
"prefix-expr",
|
||||
map(pair(opt(prefix_op), extended_expr), move |(prefix, expr)| {
|
||||
if let Some(prefix) = prefix {
|
||||
let expr = Expression::new(fresh_id_rc(&handle), expr);
|
||||
ExpressionKind::PrefixExp(prefix, Box::new(expr))
|
||||
} else {
|
||||
expr
|
||||
}
|
||||
}),
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||
context("extended-expr",
|
||||
primary_expr)(input)
|
||||
context("extended-expr", primary_expr)(input)
|
||||
}
|
||||
|
||||
fn primary_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||
context("primary-expr", alt((number_literal, bool_literal, identifier_expr)))(input)
|
||||
context("primary-expr", alt((float_literal, number_literal, bool_literal, identifier_expr)))(input)
|
||||
}
|
||||
|
||||
fn identifier_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||
@ -207,6 +205,16 @@ fn bool_literal(input: Span) -> ParseResult<ExpressionKind> {
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn float_literal(input: Span) -> ParseResult<ExpressionKind> {
|
||||
tok(map(
|
||||
alt((
|
||||
recognize(tuple((digits(digit_group_dec), char('.'), opt(digits(digit_group_dec))))),
|
||||
recognize(tuple((char('.'), digits(digit_group_dec)))),
|
||||
)),
|
||||
|ds| ExpressionKind::FloatLiteral(ds.fragment().parse().unwrap()),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn number_literal(input: Span) -> ParseResult<ExpressionKind> {
|
||||
map(alt((tok(hex_literal), tok(bin_literal), tok(dec_literal))), ExpressionKind::NatLiteral)(input)
|
||||
}
|
||||
@ -344,7 +352,6 @@ mod test {
|
||||
ExpressionKind::Value(qn!(barnaby))
|
||||
);
|
||||
|
||||
|
||||
let source = "!4";
|
||||
let parsed = span!(expression_kind, source).map_err(|err| match err {
|
||||
Err::Error(err) | Err::Failure(err) => {
|
||||
@ -361,8 +368,13 @@ mod test {
|
||||
panic!("parse error desu!");
|
||||
}
|
||||
|
||||
assert_eq!(parsed.unwrap().1, ExpressionKind::PrefixExp(PrefixOp::from_sigil("!"),
|
||||
Box::new(Expression::new(Default::default(), ExpressionKind::NatLiteral(4)))));
|
||||
assert_eq!(
|
||||
parsed.unwrap().1,
|
||||
ExpressionKind::PrefixExp(
|
||||
PrefixOp::from_sigil("!"),
|
||||
Box::new(Expression::new(Default::default(), ExpressionKind::NatLiteral(4)))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -31,6 +31,29 @@ impl Parser {
|
||||
peg_parser::schala_parser::expression(input, self).map_err(ParseError::from_peg)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn expression_comb(&mut self, input: &str) -> Result<Expression, ParseError> {
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use combinator::Span;
|
||||
use nom::{error::VerboseError, Err};
|
||||
|
||||
let id_store: IdStore<ASTItem> = IdStore::new();
|
||||
let span = Span::new_extra(input, Rc::new(RefCell::new(id_store)));
|
||||
combinator::expression(span)
|
||||
.map_err(|err| match err {
|
||||
Err::Error(err) | Err::Failure(err) => {
|
||||
let err = VerboseError {
|
||||
errors: err.errors.into_iter().map(|(sp, kind)| (*sp.fragment(), kind)).collect(),
|
||||
};
|
||||
let msg = nom::error::convert_error(input, err);
|
||||
ParseError { msg, location: (0).into() }
|
||||
}
|
||||
_ => panic!(),
|
||||
})
|
||||
.map(|(_, output)| output)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn block(&mut self, input: &str) -> Result<Block, ParseError> {
|
||||
peg_parser::schala_parser::block(input, self).map_err(ParseError::from_peg)
|
||||
|
@ -118,6 +118,18 @@ macro_rules! assert_expr {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_expr_comb {
|
||||
($input:expr, $correct:expr) => {
|
||||
let mut parser = Parser::new();
|
||||
let expr = parser.expression_comb($input);
|
||||
if expr.is_err() {
|
||||
println!("Expression parse error: {}", expr.unwrap_err().msg);
|
||||
panic!();
|
||||
}
|
||||
assert_eq!(expr.unwrap(), $correct);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_fail_expr {
|
||||
($input:expr, $failure:expr) => {
|
||||
let mut parser = Parser::new();
|
||||
@ -130,15 +142,15 @@ macro_rules! assert_fail_expr {
|
||||
fn basic_literals() {
|
||||
use ExpressionKind::*;
|
||||
|
||||
assert_expr!(".2", expr(FloatLiteral(0.2)));
|
||||
assert_expr!("8.1", expr(FloatLiteral(8.1)));
|
||||
assert_expr!("0b010", expr(NatLiteral(2)));
|
||||
assert_expr!("0b0_1_0", expr(NatLiteral(2)));
|
||||
assert_expr!("0xff", expr(NatLiteral(255)));
|
||||
assert_expr!("0x032f", expr(NatLiteral(815)));
|
||||
assert_expr!("0xf_f_", expr(NatLiteral(255)));
|
||||
assert_expr!("false", expr(BoolLiteral(false)));
|
||||
assert_expr!("true", expr(BoolLiteral(true)));
|
||||
assert_expr_comb!(".2", expr(FloatLiteral(0.2)));
|
||||
assert_expr_comb!("8.1", expr(FloatLiteral(8.1)));
|
||||
assert_expr_comb!("0b010", expr(NatLiteral(2)));
|
||||
assert_expr_comb!("0b0_1_0", expr(NatLiteral(2)));
|
||||
assert_expr_comb!("0xff", expr(NatLiteral(255)));
|
||||
assert_expr_comb!("0x032f", expr(NatLiteral(815)));
|
||||
assert_expr_comb!("0xf_f_", expr(NatLiteral(255)));
|
||||
assert_expr_comb!("false", expr(BoolLiteral(false)));
|
||||
assert_expr_comb!("true", expr(BoolLiteral(true)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user