using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
t.DefaultRuleSet.RewindOnChange = true;

// {@@Eval} evaluates the expression obtained by concatinating the captured
// elements {op} for operator, and {a} and {b} for the two numbers.
// These elements are strings and do not need curly braces within {@@Eval}
// :1 tels it to capture one token at a time.
t.FromTo("({op:1} {a:1} {b:1})", "{@@Eval: a + op + b}");

// If there are more than to numbers, as indicated by {more}, then the first
// two numbers are evaluated and put back into the list.  The operator remains.
t.FromTo("({op:1} {a:1} {b:1} {more})", "({op} {@@Eval: a + op + b} {more})");

// If a nested expression is present, it is evaluated immediately, by using
// % in {expr%} and the section is reprocessed again with the resulting value
// since .@RewindOnChange(true) was set.
t.FromTo("({op:1} {expr%: ({exp})}", "({op} {expr}");
t.FromTo("({op:1} {a:1} {expr%: ({exp})}", "({op} {a} {expr}");

// --- Test Cases ---
Console.WriteLine("--- Simple Binary ---");
var expr = "(- 100 25)";
Console.WriteLine($"LISP: {expr}");
Console.WriteLine($"Result: {t.Transform(expr)}");
Console.WriteLine("");

Console.WriteLine("--- Variadic (Multiple Args) ---");
expr = "(* 2 3 4)";
Console.WriteLine($"LISP: {expr}");
Console.WriteLine($"Result: {t.Transform(expr)}");
Console.WriteLine("");

Console.WriteLine("--- Nested Expressions ---");
expr = "(/ 100 (+ 5 5))";
Console.WriteLine($"LISP: {expr}");
Console.WriteLine($"Result: {t.Transform(expr)}");
expr = "(+ (* (- 100 (/ 80 4)) 3) (- (* (+ 5 3) (- 12 7)) (+ (* 2 3) 4)))";
Console.WriteLine($"LISP: {expr}");
Console.WriteLine($"Result: {t.Transform(expr)}");
Console.WriteLine("");