Data update

This commit is contained in:
Ingy döt Net 2026-02-01 16:33:20 -08:00
parent 5150844a7d
commit 4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions

View file

@ -1,8 +1,8 @@
/*
hand coded recursive descent parser
expr : term ( ( PLUS | MINUS ) term )* ;
term : factor ( ( MULT | DIV ) factor )* ;
factor : NUMBER | '(' expr ')';
expr : term ( ( PLUS | MINUS ) term )* ;
term : factor ( ( MULT | DIV ) factor )* ;
factor : NUMBER | '(' expr ')';
*/
calcLexer := makeCalcLexer()

View file

@ -1,13 +1,13 @@
(def precedence '{* 0, / 0
+ 1, - 1})
+ 1, - 1})
(defn order-ops
"((A x B) y C) or (A x (B y C)) depending on precedence of x and y"
[[A x B y C & more]]
(let [ret (if (<= (precedence x)
(precedence y))
(list (list A x B) y C)
(list A x (list B y C)))]
(precedence y))
(list (list A x B) y C)
(list A x (list B y C)))]
(if more
(recur (concat ret more))
ret)))
@ -18,10 +18,10 @@
(clojure.walk/postwalk
#(if (seq? %)
(let [c (count %)]
(cond (even? c) (throw (Exception. "Must be an odd number of forms"))
(= c 1) (first %)
(= c 3) %
(>= c 5) (order-ops %)))
(cond (even? c) (throw (Exception. "Must be an odd number of forms"))
(= c 1) (first %)
(= c 3) %
(>= c 5) (order-ops %)))
%)
s))
@ -34,16 +34,16 @@
add-parens))
(def ops {'* *
'+ +
'- -
'/ /})
'+ +
'- -
'/ /})
(def eval-ast
(partial clojure.walk/postwalk
#(if (seq? %)
(let [[a o b] %]
((ops o) a b))
%)))
#(if (seq? %)
(let [[a o b] %]
((ops o) a b))
%)))
(defn evaluate [s]
"Parse and evaluate an infix arithmetic expression"

View file

@ -322,7 +322,7 @@ class Parser
}
}
public program()
public Program()
{
var text := new StringWriter();
var parser := new Parser();
@ -331,7 +331,7 @@ public program()
{
try
{
Console.printLine("=",parser.run(text))
Console.printLine("=",parser.run(text as:string))
}
catch(Exception e)
{

View file

@ -1,93 +0,0 @@
#!/usr/bin/env emacs --script
;; -*- mode: emacs-lisp; lexical-binding: t -*-
;;> ./arithmetic-evaluation '(1 + 2) * 3'
(defun advance ()
(let ((rtn (buffer-substring-no-properties (point) (match-end 0))))
(goto-char (match-end 0))
rtn))
(defvar current-symbol nil)
(defun next-symbol ()
(when (looking-at "[ \t\n]+")
(goto-char (match-end 0)))
(cond
((eobp)
(setq current-symbol 'eof))
((looking-at "[0-9]+")
(setq current-symbol (string-to-number (advance))))
((looking-at "[-+*/()]")
(setq current-symbol (advance)))
((looking-at ".")
(error "Unknown character '%s'" (advance)))))
(defun accept (sym)
(when (equal sym current-symbol)
(next-symbol)
t))
(defun expect (sym)
(unless (accept sym)
(error "Expected symbol %s, but found %s" sym current-symbol))
t)
(defun p-expression ()
" expression = term { ('+' | '-') term } . "
(let ((rtn (p-term)))
(while (or (equal current-symbol "+") (equal current-symbol "-"))
(let ((op current-symbol)
(left rtn))
(next-symbol)
(setq rtn (list op left (p-term)))))
rtn))
(defun p-term ()
" term = factor { ('*' | '/') factor } . "
(let ((rtn (p-factor)))
(while (or (equal current-symbol "*") (equal current-symbol "/"))
(let ((op current-symbol)
(left rtn))
(next-symbol)
(setq rtn (list op left (p-factor)))))
rtn))
(defun p-factor ()
" factor = constant | variable | '(' expression ')' . "
(let (rtn)
(cond
((numberp current-symbol)
(setq rtn current-symbol)
(next-symbol))
((accept "(")
(setq rtn (p-expression))
(expect ")"))
(t (error "Syntax error")))
rtn))
(defun ast-build (expression)
(let (rtn)
(with-temp-buffer
(insert expression)
(goto-char (point-min))
(next-symbol)
(setq rtn (p-expression))
(expect 'eof))
rtn))
(defun ast-eval (v)
(pcase v
((pred numberp) v)
(`("+" ,a ,b) (+ (ast-eval a) (ast-eval b)))
(`("-" ,a ,b) (- (ast-eval a) (ast-eval b)))
(`("*" ,a ,b) (* (ast-eval a) (ast-eval b)))
(`("/" ,a ,b) (/ (ast-eval a) (float (ast-eval b))))
(_ (error "Unknown value %s" v))))
(dolist (arg command-line-args-left)
(let ((ast (ast-build arg)))
(princ (format " ast = %s\n" ast))
(princ (format " value = %s\n" (ast-eval ast)))
(terpri)))
(setq command-line-args-left nil)

View file

@ -10,7 +10,7 @@ def eval:
elif .[-2] == "+" then $v + .[-1]
elif .[-2] == "-" then $v - .[-1]
else tostring|error
end
end
end
end
else .

View file

@ -19,20 +19,20 @@ function eval(expr)
--arithmetic functions
tb = {["+"] = function(a,b) return eval(a) + eval(b) end,
["-"] = function(a,b) return eval(a) - eval(b) end,
["*"] = function(a,b) return eval(a) * eval(b) end,
["/"] = function(a,b) return eval(a) / eval(b) end}
["-"] = function(a,b) return eval(a) - eval(b) end,
["*"] = function(a,b) return eval(a) * eval(b) end,
["/"] = function(a,b) return eval(a) / eval(b) end}
--you could add ^ or other operators to this pretty easily
for i, v in ipairs{"*/", "+-"} do
for s, u in ipairs(expr) do
local k = type(u) == "string" and C(S(v)):match(u)
if k then
expr[s-1] = tb[k](expr[s-1],expr[s+1])
table.remove(expr, s)
table.remove(expr, s)
end
end
local k = type(u) == "string" and C(S(v)):match(u)
if k then
expr[s-1] = tb[k](expr[s-1],expr[s+1])
table.remove(expr, s)
table.remove(expr, s)
end
end
end
return expr[1]
end

View file

@ -1,85 +1,85 @@
Module CheckAst {
class EvalAst {
private:
Function Ast(&in$) {
object Ast=stack, op=stack
Do
stack Ast {stack .Ast1(&in$)}
in$=Trim$(in$)
oper$=left$(in$,1)
if Instr("+-", oper$)>0 else exit
if len(oper$)>0 then stack op {push oper$}
in$=Mid$(in$, 2)
until len(in$)=0
stack Ast {stack op} // dump op to end of stack Ast
=Ast
}
Function Ast1(&in$) {
object Ast=stack, op=stack
Do
stack Ast {stack .Ast2(&in$)}
in$=Trim$(in$)
oper$=left$(in$,1)
if Instr("*/", oper$)>0 else exit
if len(oper$)>0 then stack op {push oper$}
in$=Mid$(in$, 2)
until len(in$)=0
stack Ast {stack op}
=Ast
}
Function Ast2(&in$) {
in$=Trim$(in$)
if Asc(in$)<>40 then =.GetNumber(&in$) : exit
in$=Mid$(in$, 2)
=.Ast(&in$)
in$=Mid$(in$, 2)
}
Function GetNumber (&in$) {
Def ch$, num$
Do
ch$=left$(in$,1)
if instr("0123456789", ch$)>0 else exit
num$+=ch$
in$=Mid$(in$, 2)
until len(in$)=0
=stack:=val(num$)
}
public:
value () {
=.Ast(![])
}
}
Ast=EvalAst()
Expr$ = "1+2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10"
// Expr$="1/2+(4-3)/2+1/2"
print "Result through eval$:";eval(Expr$)
print "Expr :";Expr$
mres=Ast(&Expr$)
print "RPN :";array(stack(mres))#str$()
reg=stack
stack mres {
while not empty
if islet then
read op$
stack reg {
select case op$
case "+"
push number+number
case "-"
shift 2:push number-number
case "*"
push number*number
case "/"
shift 2:push number/number // shif 2 swap top 2 values
end select
}
else
read v
stack reg {push v}
end if
end while
}
if len(reg)<>1 then Error "Wrong Evaluation"
print "Result :";stackitem(reg)
class EvalAst {
private:
Function Ast(&in$) {
object Ast=stack, op=stack
Do
stack Ast {stack .Ast1(&in$)}
in$=Trim$(in$)
oper$=left$(in$,1)
if Instr("+-", oper$)>0 else exit
if len(oper$)>0 then stack op {push oper$}
in$=Mid$(in$, 2)
until len(in$)=0
stack Ast {stack op} // dump op to end of stack Ast
=Ast
}
Function Ast1(&in$) {
object Ast=stack, op=stack
Do
stack Ast {stack .Ast2(&in$)}
in$=Trim$(in$)
oper$=left$(in$,1)
if Instr("*/", oper$)>0 else exit
if len(oper$)>0 then stack op {push oper$}
in$=Mid$(in$, 2)
until len(in$)=0
stack Ast {stack op}
=Ast
}
Function Ast2(&in$) {
in$=Trim$(in$)
if Asc(in$)<>40 then =.GetNumber(&in$) : exit
in$=Mid$(in$, 2)
=.Ast(&in$)
in$=Mid$(in$, 2)
}
Function GetNumber (&in$) {
Def ch$, num$
Do
ch$=left$(in$,1)
if instr("0123456789", ch$)>0 else exit
num$+=ch$
in$=Mid$(in$, 2)
until len(in$)=0
=stack:=val(num$)
}
public:
value () {
=.Ast(![])
}
}
Ast=EvalAst()
Expr$ = "1+2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10"
// Expr$="1/2+(4-3)/2+1/2"
print "Result through eval$:";eval(Expr$)
print "Expr :";Expr$
mres=Ast(&Expr$)
print "RPN :";array(stack(mres))#str$()
reg=stack
stack mres {
while not empty
if islet then
read op$
stack reg {
select case op$
case "+"
push number+number
case "-"
shift 2:push number-number
case "*"
push number*number
case "/"
shift 2:push number/number // shif 2 swap top 2 values
end select
}
else
read v
stack reg {push v}
end if
end while
}
if len(reg)<>1 then Error "Wrong Evaluation"
print "Result :";stackitem(reg)
}
CheckAst

View file

@ -3,60 +3,60 @@ Expr.eval = 0
BinaryExpr = new Expr
BinaryExpr.eval = function()
if self.op == "+" then return self.lhs.eval + self.rhs.eval
if self.op == "-" then return self.lhs.eval - self.rhs.eval
if self.op == "*" then return self.lhs.eval * self.rhs.eval
if self.op == "/" then return self.lhs.eval / self.rhs.eval
if self.op == "+" then return self.lhs.eval + self.rhs.eval
if self.op == "-" then return self.lhs.eval - self.rhs.eval
if self.op == "*" then return self.lhs.eval * self.rhs.eval
if self.op == "/" then return self.lhs.eval / self.rhs.eval
end function
binop = function(lhs, op, rhs)
e = new BinaryExpr
e.lhs = lhs
e.op = op
e.rhs = rhs
return e
e = new BinaryExpr
e.lhs = lhs
e.op = op
e.rhs = rhs
return e
end function
parseAtom = function(inp)
tok = inp.pull
if tok >= "0" and tok <= "9" then
e = new Expr
e.eval = val(tok)
while inp and inp[0] >= "0" and inp[0] <= "9"
e.eval = e.eval * 10 + val(inp.pull)
end while
else if tok == "(" then
e = parseAddSub(inp)
inp.pull // swallow closing ")"
return e
else
print "Unexpected token: " + tok
exit
end if
return e
tok = inp.pull
if tok >= "0" and tok <= "9" then
e = new Expr
e.eval = val(tok)
while inp and inp[0] >= "0" and inp[0] <= "9"
e.eval = e.eval * 10 + val(inp.pull)
end while
else if tok == "(" then
e = parseAddSub(inp)
inp.pull // swallow closing ")"
return e
else
print "Unexpected token: " + tok
exit
end if
return e
end function
parseMultDiv = function(inp)
next = @parseAtom
e = next(inp)
while inp and (inp[0] == "*" or inp[0] == "/")
e = binop(e, inp.pull, next(inp))
end while
return e
next = @parseAtom
e = next(inp)
while inp and (inp[0] == "*" or inp[0] == "/")
e = binop(e, inp.pull, next(inp))
end while
return e
end function
parseAddSub = function(inp)
next = @parseMultDiv
e = next(inp)
while inp and (inp[0] == "+" or inp[0] == "-")
e = binop(e, inp.pull, next(inp))
end while
return e
next = @parseMultDiv
e = next(inp)
while inp and (inp[0] == "+" or inp[0] == "-")
e = binop(e, inp.pull, next(inp))
end while
return e
end function
while true
s = input("Enter expression: ").replace(" ","")
if not s then break
inp = split(s, "")
ast = parseAddSub(inp)
print ast.eval
s = input("Enter expression: ").replace(" ","")
if not s then break
inp = split(s, "")
ast = parseAddSub(inp)
print ast.eval
end while

View file

@ -31,7 +31,7 @@ class Yaccer(object):
def o2( self, operchar ):
# Operator character or open paren in state1
def openParen(a,b):
return 0 # function should not be called
return 0 # function should not be called
opDict= { '+': ( operator.add, 2, 2 ),
'-': (operator.sub, 2, 2 ),
@ -56,7 +56,7 @@ class Yaccer(object):
# reduce node until matching open paren found
self.redeuce( 1 )
if len(self.operstak)>0:
self.operstak.pop() # pop off open parenthesis
self.operstak.pop() # pop off open parenthesis
else:
print 'Error - no open parenthesis matches close parens.'
self.__dict__.update(self.state2)

View file

@ -1,6 +1,11 @@
Red [ "Arithmetic Evaluator - Hinjo, August 2025"
{Using a Modified Shunting-Yard algorithm to produce S-Expression as the AST
and a simple S-Expression evaluator (recursive).}
Red [
Title: "Arithmetic Evaluation"
Author: "hinjolicious"
Date: "August 2025"
Purpose: {
Using a Modified Shunting-Yard algorithm to produce S-Expression as the AST
and a simple S-Expression evaluator (recursive).
}
]
s-expr: function [expr [string!] /trace] [

View file

@ -1,10 +1,10 @@
(* AST *)
datatype expression =
Con of int (* constant *)
| Add of expression * expression (* addition *)
| Mul of expression * expression (* multiplication *)
| Sub of expression * expression (* subtraction *)
| Div of expression * expression (* division *)
Con of int (* constant *)
| Add of expression * expression (* addition *)
| Mul of expression * expression (* multiplication *)
| Sub of expression * expression (* subtraction *)
| Div of expression * expression (* division *)
(* Evaluator *)
fun eval (Con x) = x
@ -15,13 +15,13 @@ fun eval (Con x) = x
(* Lexer *)
datatype token =
CON of int
| ADD
| MUL
| SUB
| DIV
| LPAR
| RPAR
CON of int
| ADD
| MUL
| SUB
| DIV
| LPAR
| RPAR
fun lex nil = nil
| lex (#"+" :: cs) = ADD :: lex cs
@ -43,7 +43,7 @@ exception Error of string
fun match (a,ts) t = if null ts orelse hd ts <> t
then raise Error "match"
else (a, tl ts)
else (a, tl ts)
fun extend (a,ts) p f = let val (a',tr) = p ts in (f(a,a'), tr) end
@ -64,6 +64,6 @@ and parseP (CON c :: ts) = (Con c, ts)
(* Test *)
fun lex_parse_eval (str:string) =
case parseE (lex (explode str)) of
(exp, nil) => eval exp
| _ => raise Error "not parseable stuff at the end"
case parseE (lex (explode str)) of
(exp, nil) => eval exp
| _ => raise Error "not parseable stuff at the end"

View file

@ -11,9 +11,9 @@ proc s {args} {
if [regexp {[()]} $args] {
eval s [string map {( "\[s " ) \]} $args]
} elseif {"*" in $args} {
s [s_group $args *]
s [s_group $args *]
} elseif {"/" in $args} {
s [s_group $args /]
s [s_group $args /]
} elseif {"+" in $args} {
s [s_group $args +]
} elseif {"-" in $args} {