Add parse for binary operators
This commit is contained in:
parent
af27da619d
commit
9c56d807fe
@ -1,6 +1,6 @@
|
||||
function max (a, b)
|
||||
local m = a
|
||||
if a then
|
||||
if b > a then
|
||||
m = b
|
||||
end
|
||||
return m
|
||||
|
||||
83
src/ast.rs
83
src/ast.rs
@ -250,10 +250,91 @@ pub enum DefinitionKind {
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Expression {
|
||||
ValueRef(String),
|
||||
BinOp(BinaryOperator, Box<Node<Expression>>, Box<Node<Expression>>),
|
||||
}
|
||||
|
||||
impl Parse for Expression {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
|
||||
Ok(Expression::ValueRef(stream.parse()?))
|
||||
let primary_expr = stream.parse::<PrimaryExpression>()?;
|
||||
parse_binop_rhs(&mut stream, primary_expr, None).map(|v| v.kind)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PrimaryExpression(Node<Expression>);
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum BinaryOperator {
|
||||
Lt,
|
||||
Gt,
|
||||
}
|
||||
|
||||
impl BinaryOperator {
|
||||
pub fn precedence(&self) -> u32 {
|
||||
match self {
|
||||
BinaryOperator::Lt => 100,
|
||||
BinaryOperator::Gt => 105,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for PrimaryExpression {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
|
||||
let pre = Metadata::pre(&mut stream, "expression")?;
|
||||
Ok(PrimaryExpression(Node {
|
||||
kind: Expression::ValueRef(stream.parse()?),
|
||||
meta: Metadata::produce(&mut stream, pre),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_binop_rhs(
|
||||
stream: &mut TokenStream,
|
||||
mut lhs: PrimaryExpression,
|
||||
prev_op: Option<BinaryOperator>,
|
||||
) -> Result<Node<Expression>, TokenStreamError> {
|
||||
let meta_pre = Metadata::pre(stream, "binary expression")?;
|
||||
|
||||
let precedence = if let Some(op) = prev_op {
|
||||
op.precedence()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
while let Ok(curr_operator) =
|
||||
stream.parse_if::<BinaryOperator, _>(|op| op.precedence() >= precedence)
|
||||
{
|
||||
let mut rhs = stream.parse::<PrimaryExpression>()?;
|
||||
|
||||
if let Ok(next_op) = stream.parse_peek::<BinaryOperator>() {
|
||||
if curr_operator.precedence() < next_op.precedence() {
|
||||
// Operator on the right of rhs has more precedence, turn
|
||||
// rhs into lhs for new binop
|
||||
let rhs_expr = stream
|
||||
.parse_with(|mut st| parse_binop_rhs(&mut st, rhs, Some(curr_operator)))?;
|
||||
rhs = PrimaryExpression(rhs_expr);
|
||||
}
|
||||
}
|
||||
|
||||
lhs = PrimaryExpression(Node {
|
||||
kind: Expression::BinOp(curr_operator, Box::new(lhs.0), Box::new(rhs.0)),
|
||||
meta: Metadata::produce(stream, meta_pre.clone()),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(lhs.0)
|
||||
}
|
||||
|
||||
impl Parse for BinaryOperator {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
|
||||
if let Some(token) = stream.next() {
|
||||
match token {
|
||||
Token::Symbol('<') => Ok(BinaryOperator::Lt),
|
||||
Token::Symbol('>') => Ok(BinaryOperator::Gt),
|
||||
_ => Err(stream.expected_err("binop")),
|
||||
}
|
||||
} else {
|
||||
Err(stream.expected_err("binop"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user