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