2021-11-03 16:27:42 -07:00
|
|
|
use crate::ast::*;
|
2021-11-03 20:19:55 -07:00
|
|
|
use std::rc::Rc;
|
|
|
|
|
2021-11-03 23:57:22 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct BinopSequence {
|
|
|
|
first: ExpressionKind,
|
|
|
|
next: Vec<(BinOp, ExpressionKind)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BinopSequence {
|
|
|
|
fn do_precedence(self) -> ExpressionKind {
|
|
|
|
fn helper(precedence: i32, lhs: ExpressionKind, rest: &mut Vec<(BinOp, ExpressionKind)>) -> Expression {
|
|
|
|
let mut lhs = Expression::new(Default::default(), lhs);
|
|
|
|
loop {
|
|
|
|
let (next_op, next_rhs) = match rest.pop() {
|
|
|
|
Some((a, b)) => (a, b),
|
|
|
|
None => break,
|
|
|
|
};
|
|
|
|
let new_precedence = next_op.get_precedence();
|
|
|
|
if precedence >= new_precedence {
|
|
|
|
rest.push((next_op, next_rhs));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
let rhs = helper(new_precedence, next_rhs, rest);
|
|
|
|
lhs = Expression::new(Default::default(),
|
|
|
|
ExpressionKind::BinExp(next_op, Box::new(lhs), Box::new(rhs))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
lhs
|
|
|
|
}
|
|
|
|
let mut as_stack = self.next.into_iter().rev().collect();
|
|
|
|
helper(BinOp::min_precedence(), self.first, &mut as_stack).kind
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-03 16:27:42 -07:00
|
|
|
peg::parser! {
|
2021-11-03 20:19:55 -07:00
|
|
|
pub grammar schala_parser() for str {
|
2021-11-03 18:01:23 -07:00
|
|
|
|
2021-11-03 23:57:22 -07:00
|
|
|
rule whitespace() = [' ' | '\t']*
|
|
|
|
|
|
|
|
rule _ = quiet!{ whitespace() }
|
|
|
|
|
2021-11-03 18:01:23 -07:00
|
|
|
pub rule program() -> AST =
|
|
|
|
n:(statement() ** delimiter() ) { AST { id: Default::default(), statements: n.into() } }
|
|
|
|
|
|
|
|
rule delimiter() = ";" / "\n"
|
|
|
|
|
|
|
|
rule statement() -> Statement =
|
|
|
|
expr:expression() { Statement {
|
|
|
|
id: Default::default(), location: Default::default(), kind: StatementKind::Expression(expr) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub rule expression() -> Expression =
|
|
|
|
kind:expression_kind() { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
|
|
|
|
|
|
|
rule expression_kind() -> ExpressionKind =
|
2021-11-03 23:57:22 -07:00
|
|
|
precedence_expr()
|
|
|
|
|
|
|
|
rule precedence_expr() -> ExpressionKind =
|
|
|
|
first:primary() _ next:(precedence_continuation())* {
|
|
|
|
let next = next.into_iter().map(|(sigil, expr)| (BinOp::from_sigil(sigil), expr)).collect();
|
|
|
|
BinopSequence { first, next }.do_precedence()
|
|
|
|
}
|
|
|
|
|
|
|
|
rule precedence_continuation() -> (&'input str, ExpressionKind) =
|
|
|
|
op:operator() _ expr:primary() _ { (op, expr) }
|
2021-11-03 18:01:23 -07:00
|
|
|
|
2021-11-03 22:27:14 -07:00
|
|
|
//TODO maybe make this more complex
|
|
|
|
rule operator() -> &'input str =
|
|
|
|
$( ['+' | '-' | '*' | '/' | '%' | '<' | '>' | '=' | '!' | '$' | '&' | '?' | '^' | '`']+ )
|
|
|
|
|
2021-11-03 18:01:23 -07:00
|
|
|
rule primary() -> ExpressionKind =
|
2021-11-03 20:31:46 -07:00
|
|
|
float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() /
|
|
|
|
list_expr()
|
|
|
|
|
|
|
|
rule list_expr() -> ExpressionKind =
|
|
|
|
"[" exprs:(expression() ** ",") "]" {
|
|
|
|
let mut exprs = exprs;
|
|
|
|
ExpressionKind::ListLiteral(exprs)
|
|
|
|
}
|
2021-11-03 20:19:55 -07:00
|
|
|
|
|
|
|
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) }
|
2021-11-03 18:01:23 -07:00
|
|
|
|
|
|
|
rule nat_literal() -> ExpressionKind =
|
2021-11-03 20:19:55 -07:00
|
|
|
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)) }
|
2021-11-03 18:01:23 -07:00
|
|
|
|
|
|
|
rule float_literal() -> ExpressionKind =
|
|
|
|
ds:$( digits() "." digits()? / "." digits() ) { ExpressionKind::FloatLiteral(ds.parse().unwrap()) }
|
|
|
|
|
2021-11-03 20:19:55 -07:00
|
|
|
rule digits() -> &'input str = $((digit_group() "_"*)+)
|
|
|
|
rule bin_digits() -> &'input str = $((bin_digit_group() "_"*)+)
|
|
|
|
rule hex_digits() -> &'input str = $((hex_digit_group() "_"*)+)
|
2021-11-03 18:01:23 -07:00
|
|
|
|
|
|
|
rule digit_group() -> &'input str = $(['0'..='9']+)
|
2021-11-03 20:19:55 -07:00
|
|
|
rule bin_digit_group() -> &'input str = $(['0' | '1']+)
|
|
|
|
rule hex_digit_group() -> &'input str = $(['0'..='9' | 'a'..='f' | 'A'..='F']+)
|
2021-11-03 16:27:42 -07:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2021-11-03 18:01:23 -07:00
|
|
|
|
2021-11-03 20:19:55 -07:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-03 18:01:23 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
2021-11-03 20:19:55 -07:00
|
|
|
use pretty_assertions::assert_eq;
|
2021-11-03 18:01:23 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn new_parser() {
|
|
|
|
let parsed = schala_parser::expression("4");
|
|
|
|
assert_eq!(parsed.unwrap(), Expression { id: Default::default(), type_anno: None, kind: ExpressionKind::NatLiteral(4) });
|
|
|
|
|
|
|
|
let parsed = schala_parser::program("56.1");
|
|
|
|
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::FloatLiteral(56.1) })
|
|
|
|
}
|
|
|
|
|
|
|
|
].into() });
|
|
|
|
|
2021-11-03 20:19:55 -07:00
|
|
|
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() });
|
|
|
|
|
2021-11-03 18:01:23 -07:00
|
|
|
/*
|
|
|
|
let parsed = schala_parser::expression("quincy");
|
|
|
|
println!("{:?}", parsed.unwrap_err());
|
|
|
|
|
|
|
|
assert_eq!(1, 2);
|
|
|
|
*/
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|