Adapted from the infix calculator in "The AWK Programming Language", Chapter 5, which all too conveniently uses a context-free grammar that we can pass right to Instaparse. All I've done here is expand it to support variables and implicit multiplication for equations.
(nsalgae.core(:require[instaparse.core:asinsta]))(defequation(insta/parser"<equation> = left <'='> right left = expr+ right = expr+ <expr> = term | (expr '+' term) | (expr '-' term) <term> = factor | (term '*'? factor) | (term '/' factor) <factor> = number | variable | <'('> expr <')'> number = #'[0-9]+' variable = #'[A-Za-z]'"))
But wait... The Instaparse documentation already gave us a basic infix parser, and also demonstrates how to use insta/transform to evaluate expressions. But this grammar (from the AWK text:) "... captures not only the form of arithmetic expressions but also the precedences and associativities of the operators. For example, an expr is the sum or difference of terms, but a term is made up of factors, which assures that multiplication and division are dealt with before addition or subtraction."
What we want the solver to do (ultimately) is to analyze the tree and figure out which operation to perform. But first we'll just take this one as a given and make a function to solve it for . Since one side is a single number and the other is and a number, we just need to subtract the from the :
Cool... but needs to be generalized, obviously. Working with these nested vectors seems really awkward the way I'm trying to do it. I feel like I'm missing something, but let's just do some more and see how it goes, see which patterns emerge.
See, this one is perfect because it just switches the order of the right terms. This forces us to write a function that will check that.