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 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>>>;
|
type ParseResult<'a, O> = IResult<Span<'a>, O, VerboseError<Span<'a>>>;
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
@ -108,7 +108,7 @@ fn statement(input: Span) -> ParseResult<Statement> {
|
|||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression(input: Span) -> ParseResult<Expression> {
|
pub fn expression(input: Span) -> ParseResult<Expression> {
|
||||||
let id = fresh_id(&input);
|
let id = fresh_id(&input);
|
||||||
map(pair(expression_kind, opt(type_anno)), move |(kind, maybe_anno)| Expression::new(id, kind))(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> {
|
fn precedence_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
map(pair(prefix_expr, many0(precedence_continuation)),
|
map(
|
||||||
|(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| unimplemented!())(input)
|
pair(prefix_expr, many0(precedence_continuation)),
|
||||||
|
|(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| unimplemented!(),
|
||||||
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn precedence_continuation(input: Span) -> ParseResult<(BinOp, ExpressionKind)> {
|
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> {
|
fn operator(input: Span) -> ParseResult<BinOp> {
|
||||||
tok(
|
tok(map(
|
||||||
map(
|
tuple((not(tag("*/")), recognize(many1(one_of("+-*/%<>=!$&|?^`"))))),
|
||||||
tuple((
|
|(_, sigil_span): ((), Span)| BinOp::from_sigil(sigil_span.fragment()),
|
||||||
not(tag("*/")),
|
))(input)
|
||||||
recognize(many1(one_of("+-*/%<>=!$&|?^`"))),
|
|
||||||
)), |(_, sigil_span): ((), Span)| BinOp::from_sigil(sigil_span.fragment())))(input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefix_op(input: Span) -> ParseResult<PrefixOp> {
|
fn prefix_op(input: Span) -> ParseResult<PrefixOp> {
|
||||||
tok(
|
tok(map(recognize(one_of("+-!")), |sigil: Span| PrefixOp::from_sigil(sigil.fragment())))(input)
|
||||||
map(recognize(one_of("+-!")),
|
|
||||||
|sigil: Span| PrefixOp::from_sigil(sigil.fragment())))(input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefix_expr(input: Span) -> ParseResult<ExpressionKind> {
|
fn prefix_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
let handle = input.extra.clone();
|
let handle = input.extra.clone();
|
||||||
context("prefix-expr",
|
context(
|
||||||
map(
|
"prefix-expr",
|
||||||
pair(opt(prefix_op), extended_expr), move |(prefix, expr)| {
|
map(pair(opt(prefix_op), extended_expr), move |(prefix, expr)| {
|
||||||
if let Some(prefix) = prefix {
|
if let Some(prefix) = prefix {
|
||||||
let expr = Expression::new(fresh_id_rc(&handle), expr);
|
let expr = Expression::new(fresh_id_rc(&handle), expr);
|
||||||
ExpressionKind::PrefixExp(prefix, Box::new(expr))
|
ExpressionKind::PrefixExp(prefix, Box::new(expr))
|
||||||
} else {
|
} else {
|
||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
}))(input)
|
}),
|
||||||
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
|
fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
context("extended-expr",
|
context("extended-expr", primary_expr)(input)
|
||||||
primary_expr)(input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primary_expr(input: Span) -> ParseResult<ExpressionKind> {
|
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> {
|
fn identifier_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
@ -207,6 +205,16 @@ fn bool_literal(input: Span) -> ParseResult<ExpressionKind> {
|
|||||||
)(input)
|
)(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> {
|
fn number_literal(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
map(alt((tok(hex_literal), tok(bin_literal), tok(dec_literal))), ExpressionKind::NatLiteral)(input)
|
map(alt((tok(hex_literal), tok(bin_literal), tok(dec_literal))), ExpressionKind::NatLiteral)(input)
|
||||||
}
|
}
|
||||||
@ -344,7 +352,6 @@ mod test {
|
|||||||
ExpressionKind::Value(qn!(barnaby))
|
ExpressionKind::Value(qn!(barnaby))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
let source = "!4";
|
let source = "!4";
|
||||||
let parsed = span!(expression_kind, source).map_err(|err| match err {
|
let parsed = span!(expression_kind, source).map_err(|err| match err {
|
||||||
Err::Error(err) | Err::Failure(err) => {
|
Err::Error(err) | Err::Failure(err) => {
|
||||||
@ -361,8 +368,13 @@ mod test {
|
|||||||
panic!("parse error desu!");
|
panic!("parse error desu!");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(parsed.unwrap().1, ExpressionKind::PrefixExp(PrefixOp::from_sigil("!"),
|
assert_eq!(
|
||||||
Box::new(Expression::new(Default::default(), ExpressionKind::NatLiteral(4)))));
|
parsed.unwrap().1,
|
||||||
|
ExpressionKind::PrefixExp(
|
||||||
|
PrefixOp::from_sigil("!"),
|
||||||
|
Box::new(Expression::new(Default::default(), ExpressionKind::NatLiteral(4)))
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -31,6 +31,29 @@ impl Parser {
|
|||||||
peg_parser::schala_parser::expression(input, self).map_err(ParseError::from_peg)
|
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)]
|
#[cfg(test)]
|
||||||
fn block(&mut self, input: &str) -> Result<Block, ParseError> {
|
fn block(&mut self, input: &str) -> Result<Block, ParseError> {
|
||||||
peg_parser::schala_parser::block(input, self).map_err(ParseError::from_peg)
|
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 {
|
macro_rules! assert_fail_expr {
|
||||||
($input:expr, $failure:expr) => {
|
($input:expr, $failure:expr) => {
|
||||||
let mut parser = Parser::new();
|
let mut parser = Parser::new();
|
||||||
@ -130,15 +142,15 @@ macro_rules! assert_fail_expr {
|
|||||||
fn basic_literals() {
|
fn basic_literals() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
assert_expr!(".2", expr(FloatLiteral(0.2)));
|
assert_expr_comb!(".2", expr(FloatLiteral(0.2)));
|
||||||
assert_expr!("8.1", expr(FloatLiteral(8.1)));
|
assert_expr_comb!("8.1", expr(FloatLiteral(8.1)));
|
||||||
assert_expr!("0b010", expr(NatLiteral(2)));
|
assert_expr_comb!("0b010", expr(NatLiteral(2)));
|
||||||
assert_expr!("0b0_1_0", expr(NatLiteral(2)));
|
assert_expr_comb!("0b0_1_0", expr(NatLiteral(2)));
|
||||||
assert_expr!("0xff", expr(NatLiteral(255)));
|
assert_expr_comb!("0xff", expr(NatLiteral(255)));
|
||||||
assert_expr!("0x032f", expr(NatLiteral(815)));
|
assert_expr_comb!("0x032f", expr(NatLiteral(815)));
|
||||||
assert_expr!("0xf_f_", expr(NatLiteral(255)));
|
assert_expr_comb!("0xf_f_", expr(NatLiteral(255)));
|
||||||
assert_expr!("false", expr(BoolLiteral(false)));
|
assert_expr_comb!("false", expr(BoolLiteral(false)));
|
||||||
assert_expr!("true", expr(BoolLiteral(true)));
|
assert_expr_comb!("true", expr(BoolLiteral(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user