Precedence
This commit is contained in:
parent
54eb8252a9
commit
8e19b7c39d
@ -47,6 +47,10 @@ impl BinOp {
|
||||
let s = token_kind_to_sigil(op_tok)?;
|
||||
Some(binop_precedences(s))
|
||||
}
|
||||
|
||||
pub fn get_precedence(&self) -> i32 {
|
||||
binop_precedences(self.sigil.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
fn token_kind_to_sigil(tok: &TokenKind) -> Option<&str> {
|
||||
|
@ -1,9 +1,45 @@
|
||||
use crate::ast::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
||||
peg::parser! {
|
||||
pub grammar schala_parser() for str {
|
||||
|
||||
rule whitespace() = [' ' | '\t']*
|
||||
|
||||
rule _ = quiet!{ whitespace() }
|
||||
|
||||
pub rule program() -> AST =
|
||||
n:(statement() ** delimiter() ) { AST { id: Default::default(), statements: n.into() } }
|
||||
|
||||
@ -18,7 +54,16 @@ peg::parser! {
|
||||
kind:expression_kind() { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
||||
|
||||
rule expression_kind() -> ExpressionKind =
|
||||
primary()
|
||||
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) }
|
||||
|
||||
//TODO maybe make this more complex
|
||||
rule operator() -> &'input str =
|
||||
|
@ -172,7 +172,7 @@ fn binexps() {
|
||||
use ExpressionKind::*;
|
||||
use StatementKind::Expression;
|
||||
|
||||
assert_expr!("0xf_f_+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
|
||||
assert_expr2!("0xf_f_+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
|
||||
assert_eq!(
|
||||
parse("3; 4; 4.3").unwrap(),
|
||||
AST {
|
||||
@ -186,16 +186,16 @@ fn binexps() {
|
||||
}
|
||||
);
|
||||
|
||||
assert_expr!(
|
||||
assert_expr2!(
|
||||
"1 + 2 * 3",
|
||||
binop("+", expr(NatLiteral(1)), binop("*", expr(NatLiteral(2)), expr(NatLiteral(3))))
|
||||
);
|
||||
assert_expr!(
|
||||
assert_expr2!(
|
||||
"1 * 2 + 3",
|
||||
binop("+", binop("*", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(3)))
|
||||
);
|
||||
assert_expr!("1 && 2", binop("&&", expr(NatLiteral(1)), expr(NatLiteral(2))));
|
||||
assert_expr!(
|
||||
assert_expr2!("1 && 2", binop("&&", expr(NatLiteral(1)), expr(NatLiteral(2))));
|
||||
assert_expr2!(
|
||||
"1 + 2 * 3 + 4",
|
||||
binop(
|
||||
"+",
|
||||
@ -203,12 +203,12 @@ fn binexps() {
|
||||
expr(NatLiteral(4))
|
||||
)
|
||||
);
|
||||
assert_expr!(
|
||||
assert_expr2!(
|
||||
"(1 + 2) * 3",
|
||||
binop("*", binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(3)))
|
||||
);
|
||||
assert_expr!(".1 + .2", binop("+", expr(FloatLiteral(0.1)), expr(FloatLiteral(0.2))));
|
||||
assert_expr!("1 / 2.", binop("/", expr(NatLiteral(1)), expr(FloatLiteral(2.))));
|
||||
assert_expr2!(".1 + .2", binop("+", expr(FloatLiteral(0.1)), expr(FloatLiteral(0.2))));
|
||||
assert_expr2!("1 / 2.", binop("/", expr(NatLiteral(1)), expr(FloatLiteral(2.))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user