Add parse for binary operators
This commit is contained in:
parent
af27da619d
commit
9c56d807fe
@ -1,6 +1,6 @@
|
|||||||
function max (a, b)
|
function max (a, b)
|
||||||
local m = a
|
local m = a
|
||||||
if a then
|
if b > a then
|
||||||
m = b
|
m = b
|
||||||
end
|
end
|
||||||
return m
|
return m
|
||||||
|
|||||||
83
src/ast.rs
83
src/ast.rs
@ -250,10 +250,91 @@ pub enum DefinitionKind {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
ValueRef(String),
|
ValueRef(String),
|
||||||
|
BinOp(BinaryOperator, Box<Node<Expression>>, Box<Node<Expression>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Expression {
|
impl Parse for Expression {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
|
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