it.grypho.scala.leonardo.parser

Members list

Type members

Classlikes

object Parser extends JavaTokenParsers

Recursive-descent parser for Leonardo mathematical expressions.

Recursive-descent parser for Leonardo mathematical expressions.

All grammar productions are lazy val so the combinator graph and compiled regexes are built once on first access and reused for every subsequent parse call. Only guardedExpr and guardedSignedPower remain def because they capture per-call depth state via a ThreadLocal counter.

Grammar summary:

topLevel     ::= logicExpr
logicExpr    ::= implExpr                    -- boolean connectives bind loosest
implExpr     ::= orExpr ["implies" implExpr] -- right-associative, loosest connective
orExpr       ::= xorExpr ("or" xorExpr)*
xorExpr      ::= andExpr ("xor" andExpr)*
andExpr      ::= notExpr ("and" notExpr)*
notExpr      ::= "not" notExpr | equationExpr | "(" logicExpr ")"
equationExpr ::= expr [("==" | "=") expr]   -- "==" -> _EqualityCheck; "=" -> _Equation
expr         ::= ["+" | "-"] simpleExpr
simpleExpr   ::= term (("+" | "-") term)*
term         ::= signedPower (("*" | "/") signedPower | "" power)*
signedPower  ::= ["+" | "-"] power
power        ::= factor ["^" signedPower]    -- right-associative
factor       ::= function | functional | matrix | value | "(" equationExpr ")"
matrix       ::= "[" matrixRow ("," matrixRow)* "]"
matrixRow    ::= "[" equationExpr ("," equationExpr)* "]"

Sign handling: the number token is unsigned so that implicit multiplication does not swallow 3-2 as 3 * (-2). A sign is allowed where an explicit operator precedes (start of expression, after +, -, *, /, ^, and in integral limits) but deliberately not in the operand of implicit *.

Matrix dispatch: when a syntactically visible matrix operand appears, +/-/* build MatSum/MatProduct/MatScale rather than Sum/Product. M * y with a non-literal y builds MatProduct(M, y) (not MatScale(y, M)) because y may be a variable bound to a matrix at eval time, and swapping would silently commute the product. Only a literal _Number right operand is known to commute.

Nesting guard: a ThreadLocal depth counter is incremented at every parenthesised sub-expression and at every ^ exponent; the parser returns a failure rather than blowing the JVM stack when the depth reaches MaxDepth.

Attributes

Supertypes
trait JavaTokenParsers
trait RegexParsers
trait Parsers
class Object
trait Matchable
class Any
Show all
Self type
Parser.type