Started porting extant tests to new peg parser
This commit is contained in:
parent
359f274f33
commit
88b39b5561
@ -1,7 +1,9 @@
|
||||
use crate::ast::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
peg::parser! {
|
||||
grammar schala_parser() for str {
|
||||
pub grammar schala_parser() for str {
|
||||
|
||||
pub rule program() -> AST =
|
||||
n:(statement() ** delimiter() ) { AST { id: Default::default(), statements: n.into() } }
|
||||
@ -20,25 +22,94 @@ peg::parser! {
|
||||
primary()
|
||||
|
||||
rule primary() -> ExpressionKind =
|
||||
float_literal() / nat_literal()
|
||||
float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr()
|
||||
|
||||
rule paren_expr() -> ExpressionKind =
|
||||
"(" exprs:(expression() ** ",") ")" {
|
||||
let mut exprs = exprs;
|
||||
match exprs.len() {
|
||||
1 => exprs.pop().unwrap().kind,
|
||||
_ => ExpressionKind::TupleLiteral(exprs),
|
||||
}
|
||||
}
|
||||
|
||||
//TODO string escapes, prefixes
|
||||
rule string_literal() -> ExpressionKind =
|
||||
"\"" items:$([^ '"' ]*) "\"" { ExpressionKind::StringLiteral(Rc::new(items.to_string())) }
|
||||
|
||||
rule bool_literal() -> ExpressionKind =
|
||||
"true" { ExpressionKind::BoolLiteral(true) } / "false" { ExpressionKind::BoolLiteral(false) }
|
||||
|
||||
rule nat_literal() -> ExpressionKind =
|
||||
("0x" / "0b")? digits:digits() { ExpressionKind::NatLiteral(digits.parse().unwrap()) }
|
||||
bin_literal() / hex_literal() / unmarked_literal()
|
||||
|
||||
rule unmarked_literal() -> ExpressionKind =
|
||||
digits:digits() { ExpressionKind::NatLiteral(digits.parse().unwrap()) }
|
||||
|
||||
rule bin_literal() -> ExpressionKind =
|
||||
"0b" digits:bin_digits() { ExpressionKind::NatLiteral(parse_binary(digits)) }
|
||||
|
||||
rule hex_literal() -> ExpressionKind =
|
||||
"0x" digits:hex_digits() { ExpressionKind::NatLiteral(parse_hex(digits)) }
|
||||
|
||||
rule float_literal() -> ExpressionKind =
|
||||
ds:$( digits() "." digits()? / "." digits() ) { ExpressionKind::FloatLiteral(ds.parse().unwrap()) }
|
||||
|
||||
rule digits() -> &'input str =
|
||||
$((digit_group() "_"*)+)
|
||||
rule digits() -> &'input str = $((digit_group() "_"*)+)
|
||||
rule bin_digits() -> &'input str = $((bin_digit_group() "_"*)+)
|
||||
rule hex_digits() -> &'input str = $((hex_digit_group() "_"*)+)
|
||||
|
||||
rule digit_group() -> &'input str = $(['0'..='9']+)
|
||||
rule bin_digit_group() -> &'input str = $(['0' | '1']+)
|
||||
rule hex_digit_group() -> &'input str = $(['0'..='9' | 'a'..='f' | 'A'..='F']+)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_binary(digits: &str/*, tok: Token*/) -> /*ParseResult<u64>*/ u64 {
|
||||
let mut result: u64 = 0;
|
||||
let mut multiplier = 1;
|
||||
for d in digits.chars().rev() {
|
||||
match d {
|
||||
'1' => result += multiplier,
|
||||
'0' => (),
|
||||
'_' => continue,
|
||||
_ => unreachable!()
|
||||
}
|
||||
multiplier = match multiplier.checked_mul(2) {
|
||||
Some(m) => m,
|
||||
None => /*return ParseError::new_with_token("This binary expression will overflow", tok),*/ panic!(),
|
||||
}
|
||||
}
|
||||
//Ok(result)
|
||||
result
|
||||
}
|
||||
|
||||
//TODO fix these two functions
|
||||
fn parse_hex(digits: &str) -> u64 {
|
||||
let mut result: u64 = 0;
|
||||
let mut multiplier: u64 = 1;
|
||||
for d in digits.chars().rev() {
|
||||
if d == '_' {
|
||||
continue;
|
||||
}
|
||||
match d.to_digit(16) {
|
||||
Some(n) => result += n as u64 * multiplier,
|
||||
None => panic!(),
|
||||
}
|
||||
multiplier = match multiplier.checked_mul(16) {
|
||||
Some(m) => m,
|
||||
None => panic!()
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn new_parser() {
|
||||
@ -60,6 +131,50 @@ mod test {
|
||||
|
||||
].into() });
|
||||
|
||||
let parsed = schala_parser::program("1;2\n5\n(1.1,false)");
|
||||
if let Err(ref err) = parsed {
|
||||
println!("{}", err);
|
||||
}
|
||||
assert_eq!(parsed.unwrap(), AST {
|
||||
id: Default::default(), statements: vec![
|
||||
Statement {
|
||||
id: Default::default(),
|
||||
location: Default::default(),
|
||||
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
|
||||
ExpressionKind::NatLiteral(1) })
|
||||
},
|
||||
Statement {
|
||||
id: Default::default(),
|
||||
location: Default::default(),
|
||||
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
|
||||
ExpressionKind::NatLiteral(2) })
|
||||
},
|
||||
Statement {
|
||||
id: Default::default(),
|
||||
location: Default::default(),
|
||||
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
|
||||
ExpressionKind::NatLiteral(5) })
|
||||
},
|
||||
Statement {
|
||||
id: Default::default(),
|
||||
location: Default::default(),
|
||||
kind: StatementKind::Expression(Expression { id: Default::default(), type_anno: None, kind:
|
||||
ExpressionKind::TupleLiteral(vec![Expression{
|
||||
id: Default::default(),
|
||||
type_anno: None,
|
||||
kind: ExpressionKind::FloatLiteral(1.1),
|
||||
},
|
||||
Expression {
|
||||
id: Default::default(),
|
||||
type_anno: None,
|
||||
kind: ExpressionKind::BoolLiteral(false),
|
||||
}]
|
||||
|
||||
) })
|
||||
}
|
||||
|
||||
].into() });
|
||||
|
||||
/*
|
||||
let parsed = schala_parser::expression("quincy");
|
||||
println!("{:?}", parsed.unwrap_err());
|
||||
|
@ -8,6 +8,7 @@ use pretty_assertions::assert_eq;
|
||||
|
||||
use super::{tokenize, ParseResult, Parser};
|
||||
use crate::{ast::*, tokenizing::Location};
|
||||
use super::new::schala_parser;
|
||||
|
||||
fn rc(s: &str) -> Rc<String> {
|
||||
Rc::new(s.to_owned())
|
||||
@ -121,6 +122,12 @@ macro_rules! assert_expr {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_expr2 {
|
||||
($input:expr, $correct:expr) => {
|
||||
assert_eq!(schala_parser::expression($input).unwrap(), $correct);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_fail_expr {
|
||||
($input:expr, $failure:expr) => {
|
||||
let mut parser = make_parser($input);
|
||||
@ -132,16 +139,16 @@ 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!(r#""hello""#, expr(StringLiteral(rc("hello"))));
|
||||
assert_expr2!(".2", expr(FloatLiteral(0.2)));
|
||||
assert_expr2!("8.1", expr(FloatLiteral(8.1)));
|
||||
assert_expr2!("0b010", expr(NatLiteral(2)));
|
||||
assert_expr2!("0b0_1_0", expr(NatLiteral(2)));
|
||||
assert_expr2!("0xff", expr(NatLiteral(255)));
|
||||
assert_expr2!("0x032f", expr(NatLiteral(815)));
|
||||
assert_expr2!("0xf_f_", expr(NatLiteral(255)));
|
||||
assert_expr2!("false", expr(BoolLiteral(false)));
|
||||
assert_expr2!("true", expr(BoolLiteral(true)));
|
||||
assert_expr2!(r#""hello""#, expr(StringLiteral(rc("hello"))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user