use crate::SyntaxKind::{
ASSIGNMENT, EOF, EQ, IDENT, IDENTIFIER, KW_RETURN, KW_TEMP, LOGIC_LINE, MINUS_EQ, NEWLINE,
PLUS_EQ, RETURN_STMT, TEMP_DECL,
};
use super::Parser;
pub(crate) fn logic_line(p: &mut Parser<'_, '_>) {
p.start_node(LOGIC_LINE);
p.bump(); p.skip_ws();
match p.current() {
KW_RETURN => return_statement(p),
KW_TEMP => temp_declaration(p),
IDENT if is_assignment_ahead(p) => assignment(p),
_ => {
super::expression::expression(p);
}
}
p.skip_ws();
if p.at(NEWLINE) {
p.bump();
}
p.finish_node();
}
fn is_assignment_ahead(p: &Parser<'_, '_>) -> bool {
let next = p.nth(1);
matches!(next, EQ | PLUS_EQ | MINUS_EQ) && !(next == EQ && p.nth(2) == EQ)
}
fn return_statement(p: &mut Parser<'_, '_>) {
p.start_node(RETURN_STMT);
p.bump(); p.skip_ws();
if !matches!(p.current(), NEWLINE | EOF) {
super::expression::expression(p);
}
p.finish_node();
}
fn temp_declaration(p: &mut Parser<'_, '_>) {
p.start_node(TEMP_DECL);
p.bump(); p.skip_ws();
p.start_node(IDENTIFIER);
p.expect(IDENT);
p.finish_node();
p.skip_ws();
assignment_op(p);
p.skip_ws();
super::expression::expression(p);
p.finish_node();
}
fn assignment(p: &mut Parser<'_, '_>) {
p.start_node(ASSIGNMENT);
super::divert::path(p);
p.skip_ws();
assignment_op(p);
p.skip_ws();
super::expression::expression(p);
p.finish_node();
}
fn assignment_op(p: &mut Parser<'_, '_>) {
match p.current() {
PLUS_EQ | MINUS_EQ | EQ => {
p.bump();
}
_ => {
p.error("expected assignment operator".into());
}
}
}