expy 0.0.2

Embeddable & extensible expression evaluator
Documentation
//! Grammar for the expression parser.

WHITESPACE = _{ " " | "\t" | NEWLINE }

COMMENT = _{ block_comment | line_comment }
    block_comment = _{ "/*" ~ (!"*/" ~ ANY)* ~ "*/" }  // TODO: nesting? PUSH/POP should handle it
    line_comment = _{ "//" ~ (!NEWLINE ~ ANY)* }


input = _{ SOI ~ expr ~ EOI }
expr = { prefix_op* ~ term ~ postfix* ~ (infix_op ~ prefix_op* ~ term ~ postfix*)* }


//
// Operators
//

prefix_op = _{ neg | not }
    neg = { "-" }
    not = { "!" }

infix_op = _{ logic_op | cmp_op | arith_op }
    logic_op = _{ and | or }
        and = { "&&" }
        or = { "||" }
    cmp_op = _{ eq | not_eq | less | less_eq | greater | greater_eq }
        eq = { "==" }
        not_eq = { "!=" }
        less = { "<" }
        less_eq = { "<=" }
        greater = { ">" }
        greater_eq = { ">=" }
    arith_op = _{ add | sub | mul | div | pow }
        add = { "+" }
        sub = { "-" }
        mul = { "*" }
        div = { "/" }
        pow = { "^" }


//
// Term
//

term = _{ literal | ident | #glam = vector | "(" ~ expr ~ ")" }  // order matters

literal = _{ bool | float | int | symbol }  // order matters
    bool = { true | false }
        true = _{ "true" }
        false = _{ "false" }
    int = @{ (ASCII_NONZERO_DIGIT ~ ASCII_DIGIT+ | ASCII_DIGIT) }  // TODO: different bases
    float = @{ int ~ (mantissa ~ exponent? | exponent) }  // e.g. "1.2", "4.3e2", "5.", "6e3"
        // TODO: consider disallowing "1.e12", even though Rust understand it as float, as it would
        // allow member access to literal int values; but is there a use case for this?
        mantissa = { "." ~ ASCII_DIGIT* }
        exponent = { ^"e" ~ ("+"|"-")? ~ int }
    symbol = ${ "@" ~ ident }

ident = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }

vector = { "[" ~ expr? ~ ("," ~  expr)* ~ "]" }


//
// Suffixes
//

postfix = _{ call | subscript | access }

call = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
subscript = { "[" ~ expr ~ "]" }
access = { "." ~ ident }