Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
142
Task/Arithmetic-evaluation/Crystal/arithmetic-evaluation.cr
Normal file
142
Task/Arithmetic-evaluation/Crystal/arithmetic-evaluation.cr
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
abstract class Expression
|
||||
abstract def eval
|
||||
end
|
||||
|
||||
class IntLiteral < Expression
|
||||
property value
|
||||
|
||||
def initialize (@value : Int32)
|
||||
end
|
||||
|
||||
def eval
|
||||
@value
|
||||
end
|
||||
|
||||
def to_s (io)
|
||||
io << @value.to_s
|
||||
end
|
||||
end
|
||||
|
||||
alias UnFun = Int32 -> Int32
|
||||
alias BinFun = Int32, Int32 -> Int32
|
||||
|
||||
class UnOp < Expression
|
||||
getter operand : Expression, op : String
|
||||
@function : UnFun
|
||||
|
||||
def initialize (@operand, @op, &block : UnFun)
|
||||
@function = block
|
||||
end
|
||||
|
||||
def eval
|
||||
@function.call @operand.eval
|
||||
end
|
||||
|
||||
def to_s (io)
|
||||
io << @op
|
||||
@operand.to_s io
|
||||
end
|
||||
end
|
||||
|
||||
class BinOp < Expression
|
||||
getter left : Expression, right : Expression, op : String
|
||||
@function : BinFun
|
||||
|
||||
def initialize (@left, @right, @op, &block : BinFun)
|
||||
@function = block
|
||||
end
|
||||
|
||||
def eval
|
||||
@function.call @left.eval, @right.eval
|
||||
end
|
||||
|
||||
def to_s (io)
|
||||
io << "("
|
||||
@left.to_s io
|
||||
io << " " << @op << " "
|
||||
@right.to_s io
|
||||
io << ")"
|
||||
end
|
||||
end
|
||||
|
||||
class Parser
|
||||
UNOPS = {
|
||||
'-' => { func: UnFun.new {|a| -a } }
|
||||
}
|
||||
BINOPS = {
|
||||
'+' => { prio: 2, func: BinFun.new {|a, b| a + b } },
|
||||
'-' => { prio: 2, func: BinFun.new {|a, b| a - b } },
|
||||
'*' => { prio: 1, func: BinFun.new {|a, b| a * b } },
|
||||
'/' => { prio: 1, func: BinFun.new {|a, b| a // b } }
|
||||
}
|
||||
@chars : Array(Char)
|
||||
|
||||
def initialize (s)
|
||||
@chars = s.chars
|
||||
end
|
||||
|
||||
def consume (ch)
|
||||
raise "'#{ch}' expected" unless @chars.present? && @chars.first == ch
|
||||
@chars.shift
|
||||
end
|
||||
|
||||
def skip_spaces
|
||||
while @chars.present? && @chars.first.whitespace?
|
||||
@chars.shift
|
||||
end
|
||||
end
|
||||
|
||||
def parse_unit
|
||||
skip_spaces
|
||||
raise "Unexpected end of input" if @chars.empty?
|
||||
case @chars.first
|
||||
when '('
|
||||
consume '('
|
||||
res = parse_binop prio: 2
|
||||
consume ')'
|
||||
res
|
||||
when .in? UNOPS.keys
|
||||
op = @chars.shift
|
||||
UnOp.new parse_unit, op.to_s, &UNOPS[op][:func]
|
||||
when '0'..'9'
|
||||
n = 0
|
||||
while @chars.present? && @chars.first.in? '0'..'9'
|
||||
n = n * 10 + @chars.shift.to_i
|
||||
end
|
||||
IntLiteral.new n
|
||||
else
|
||||
raise "Unexpected '#{@chars.first}'"
|
||||
end
|
||||
end
|
||||
|
||||
def parse_binop (prio)
|
||||
left = if prio == 0
|
||||
parse_unit
|
||||
else
|
||||
parse_binop prio-1
|
||||
end
|
||||
loop do
|
||||
skip_spaces
|
||||
return left if @chars.empty?
|
||||
op = @chars.first
|
||||
opdata = BINOPS[op]?
|
||||
return left if !opdata || opdata[:prio] != prio
|
||||
consume op
|
||||
right = parse_binop prio-1
|
||||
left = BinOp.new left, right, op.to_s, &opdata[:func]
|
||||
end
|
||||
end
|
||||
|
||||
def parse
|
||||
res = parse_binop prio: 2
|
||||
skip_spaces
|
||||
raise "Unexpected '#{@chars.first}'" unless @chars.empty?
|
||||
res
|
||||
end
|
||||
end
|
||||
|
||||
formula = "1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + -1*-1"
|
||||
ast = Parser.new(formula).parse
|
||||
print "Original: ", formula, "\n"
|
||||
print "Parsed: ", ast, "\n"
|
||||
print "Result: ", ast.eval, "\n"
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
#!/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)
|
||||
|
|
@ -1,221 +1,201 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Arithmetic_evaluation.exw</span>
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
-- demo\rosetta\Arithmetic_evaluation.exw
|
||||
sequence opstack = {} -- atom elements are literals,
|
||||
-- sequence elements are subexpressions
|
||||
-- on completion length(opstack) should be 1
|
||||
object token
|
||||
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">opstack</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- atom elements are literals,
|
||||
-- sequence elements are subexpressions
|
||||
-- on completion length(opstack) should be 1</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">token</span>
|
||||
constant p_p_op = -1, -- expressions stored as p1,p2,op
|
||||
p_op_p = 0, -- expressions stored as p1,op,p2
|
||||
op_p_p = +1, -- expressions stored as op,p1,p2
|
||||
opp = op_p_p
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">op_p_p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- 1: expressions stored as op,p1,p2
|
||||
-- p_op_p -- 0: expressions stored as p1,op,p2
|
||||
-- p_p_op -- -1: expressions stored as p1,p2,op</span>
|
||||
object op = 0 -- 0 if none, else "+", "-", "*", "/", "^", "%", or "u-"
|
||||
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- 0 if none, else "+", "-", "*", "/", "^", "%", or "u-"</span>
|
||||
string s -- the expression being parsed
|
||||
integer ch
|
||||
integer sidx
|
||||
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #000080;font-style:italic;">-- the expression being parsed</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">sidx</span>
|
||||
procedure err(string msg)
|
||||
crash("%s\n%s^ %s\n\nPressEnter...",{s,repeat(' ',sidx-1),msg})
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">err</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n%s^ %s\n\nPressEnter..."</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #7060A8;">abort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
procedure nxtch(object msg="eof")
|
||||
sidx += 1
|
||||
if sidx>length(s) then
|
||||
if string(msg) then err(msg) end if
|
||||
ch = -1
|
||||
else
|
||||
ch = s[sidx]
|
||||
end if
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">nxtch</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"eof"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">sidx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">sidx</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">err</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
procedure skipspaces()
|
||||
while find(ch," \t\r\n") do nxtch(0) end while
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">skipspaces</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\t'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\r'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">})!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span> <span style="color: #000000;">nxtch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
procedure get_token()
|
||||
skipspaces()
|
||||
if ch=-1 then token = "eof" return end if
|
||||
if ch>='0' and ch<='9' then
|
||||
atom n = ch-'0'
|
||||
while 1 do
|
||||
nxtch(0)
|
||||
if ch<'0' or ch>'9' then exit end if
|
||||
n = n*10+(ch-'0')
|
||||
end while
|
||||
if ch='.' then
|
||||
integer decimal = 1
|
||||
atom fraction = 0
|
||||
while true do
|
||||
nxtch(0)
|
||||
if ch<'0' or ch>'9' then exit end if
|
||||
fraction = fraction*10 + (ch-'0')
|
||||
decimal *= 10
|
||||
end while
|
||||
n += fraction/decimal
|
||||
end if
|
||||
-- if find(ch,"eE") then -- you get the idea
|
||||
-- end if
|
||||
token = n
|
||||
return
|
||||
end if
|
||||
if find(ch,"+-/*()^%")=0 then err("syntax error") end if
|
||||
token = s[sidx..sidx]
|
||||
nxtch(0)
|
||||
return
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fraction</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">dec</span>
|
||||
<span style="color: #000000;">skipspaces</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"eof"</span> <span style="color: #008080;">return</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'9'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">nxtch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #008000;">'9'</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">dec</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #000000;">fraction</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">nxtch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #008000;">'9'</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">fraction</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fraction</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span>
|
||||
<span style="color: #000000;">dec</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">10</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #000000;">n</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">fraction</span><span style="color: #0000FF;">/</span><span style="color: #000000;">dec</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000080;font-style:italic;">-- if find(ch,"eE") then -- you get the idea
|
||||
-- end if</span>
|
||||
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
|
||||
<span style="color: #008080;">return</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"+-/*()^%"</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">err</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"syntax error"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">..</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">nxtch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
procedure Match(string t)
|
||||
if token!=t then err(t&" expected") end if
|
||||
get_token()
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Match</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">t</span> <span style="color: #008080;">then</span> <span style="color: #000000;">err</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">&</span><span style="color: #008000;">" expected"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
procedure PopFactor()
|
||||
object p1, p2 = opstack[$], f
|
||||
if op="u-" then
|
||||
p1 = 0
|
||||
else
|
||||
opstack = opstack[1..$-1]
|
||||
p1 = opstack[$]
|
||||
end if
|
||||
switch opp do
|
||||
case op_p_p: f = {op,p1,p2}
|
||||
case p_op_p: f = {p1,op,p2}
|
||||
case p_p_op: f = {p1,p2,op}
|
||||
end switch
|
||||
opstack[$] = f
|
||||
op = 0
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">PopFactor</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">p2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">opstack</span><span style="color: #0000FF;">[$]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"u-"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">p1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">opstack</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">opstack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">p1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">opstack</span><span style="color: #0000FF;">[$]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">op_p_p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">opstack</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- op_p_p</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op_p_p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">opstack</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- p_op_p</span>
|
||||
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">-- -1</span>
|
||||
<span style="color: #000000;">opstack</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- p_p_op</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
procedure PushFactor(atom t)
|
||||
if op!=0 then PopFactor() end if
|
||||
opstack = append(opstack,t)
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">PushFactor</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">PopFactor</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">opstack</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opstack</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
procedure PushOp(string t)
|
||||
if op!=0 then PopFactor() end if
|
||||
op = t
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">PushOp</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">PopFactor</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
forward procedure Expr(integer p)
|
||||
|
||||
<span style="color: #008080;">forward</span> <span style="color: #008080;">procedure</span> <span style="color: #000000;">Expr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
|
||||
procedure Factor()
|
||||
if atom(token) then
|
||||
PushFactor(token)
|
||||
if ch!=-1 then
|
||||
get_token()
|
||||
end if
|
||||
elsif token="+" then -- (ignore)
|
||||
nxtch()
|
||||
Factor()
|
||||
elsif token="-" then
|
||||
get_token()
|
||||
-- Factor()
|
||||
Expr(3) -- makes "-3^2" yield -9 (ie -(3^2)) not 9 (ie (-3)^2).
|
||||
if op!=0 then PopFactor() end if
|
||||
if integer(opstack[$]) then
|
||||
opstack[$] = -opstack[$]
|
||||
else
|
||||
PushOp("u-")
|
||||
end if
|
||||
elsif token="(" then
|
||||
get_token()
|
||||
Expr(0)
|
||||
Match(")")
|
||||
else
|
||||
err("syntax error")
|
||||
end if
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Factor</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">PushFactor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"+"</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (ignore)</span>
|
||||
<span style="color: #000000;">nxtch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">Factor</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"-"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000080;font-style:italic;">-- Factor()</span>
|
||||
<span style="color: #000000;">Expr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- makes "-3^2" yield -9 (ie -(3^2)) not 9 (ie (-3)^2).</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">PopFactor</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opstack</span><span style="color: #0000FF;">[$])</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">opstack</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">opstack</span><span style="color: #0000FF;">[$]</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">PushOp</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"u-"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">token</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"("</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">Expr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">Match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">")"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">err</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"syntax error"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
constant {operators,
|
||||
precedence,
|
||||
associativity} = columnize({{"^",3,0},
|
||||
{"%",2,1},
|
||||
{"*",2,1},
|
||||
{"/",2,1},
|
||||
{"+",1,1},
|
||||
{"-",1,1},
|
||||
$})
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">operators</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">precedence</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">associativity</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">({{</span><span style="color: #008000;">"^"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"*"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"/"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"+"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"-"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">$})</span>
|
||||
procedure Expr(integer p)
|
||||
--
|
||||
-- Parse an expression, using precedence climbing.
|
||||
--
|
||||
-- p is the precedence level we should parse to, eg/ie
|
||||
-- 4: Factor only (may as well just call Factor)
|
||||
-- 3: "" and ^
|
||||
-- 2: "" and *,/,%
|
||||
-- 1: "" and +,-
|
||||
-- 0: full expression (effectively the same as 1)
|
||||
-- obviously, parentheses override any setting of p.
|
||||
--
|
||||
Factor()
|
||||
while 1 do
|
||||
integer k = find(token,operators) -- *,/,+,-
|
||||
if k=0 then exit end if
|
||||
integer thisp = precedence[k]
|
||||
if thisp<p then exit end if
|
||||
get_token()
|
||||
Expr(thisp+associativity[k])
|
||||
PushOp(operators[k])
|
||||
end while
|
||||
end procedure
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Expr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">--
|
||||
-- Parse an expression, using precedence climbing.
|
||||
--
|
||||
-- p is the precedence level we should parse to, eg/ie
|
||||
-- 4: Factor only (may as well just call Factor)
|
||||
-- 3: "" and ^
|
||||
-- 2: "" and *,/,%
|
||||
-- 1: "" and +,-
|
||||
-- 0: full expression (effectively the same as 1)
|
||||
-- obviously, parentheses override any setting of p.
|
||||
--</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">thisp</span>
|
||||
<span style="color: #000000;">Factor</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">,</span><span style="color: #000000;">operators</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- *,/,+,-</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">thisp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">precedence</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">thisp</span><span style="color: #0000FF;"><</span><span style="color: #000000;">p</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">Expr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">thisp</span><span style="color: #0000FF;">+</span><span style="color: #000000;">associativity</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #000000;">PushOp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">operators</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
function evaluate(object s)
|
||||
object lhs, rhs
|
||||
string op
|
||||
if atom(s) then return s end if
|
||||
switch opp do
|
||||
case op_p_p: {op,lhs,rhs} = s
|
||||
case p_op_p: {lhs,op,rhs} = s
|
||||
case p_p_op: {lhs,rhs,op} = s
|
||||
default: ?9/0
|
||||
end switch
|
||||
if sequence(lhs) then lhs = evaluate(lhs) end if
|
||||
if sequence(rhs) then rhs = evaluate(rhs) end if
|
||||
if op="+" then return lhs+rhs
|
||||
elsif op="-" then return lhs-rhs
|
||||
elsif op="*" then return lhs*rhs
|
||||
elsif op="/" then return lhs/rhs
|
||||
elsif op="^" then return power(lhs,rhs)
|
||||
elsif op="%" then return rmdr(lhs,rhs)
|
||||
elsif op="u-" then return -rhs
|
||||
else ?9/0
|
||||
end if
|
||||
end function
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">evaluate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rhs</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">op</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">op_p_p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- op_p_p</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op_p_p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- p_op_p</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span>
|
||||
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">-- -1 -- p_p_op</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">lhs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">evaluate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">rhs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">evaluate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"+"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">+</span><span style="color: #000000;">rhs</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"-"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">-</span><span style="color: #000000;">rhs</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"*"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">*</span><span style="color: #000000;">rhs</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"/"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">/</span><span style="color: #000000;">rhs</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"^"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"%"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"u-"</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">rhs</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"3+4+5+6*7/1*5^2^3"</span> <span style="color: #000080;font-style:italic;">-- 16406262</span>
|
||||
<span style="color: #000000;">sidx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #000000;">nxtch</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">get_token</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">Expr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">PopFactor</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opstack</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000000;">err</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"some error"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"expression: \"%s\"\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"AST (flat): "</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">opstack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"AST (tree):\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">ppEx</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opstack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],{</span><span style="color: #004600;">pp_Nest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9999</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"result: "</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">evaluate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opstack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
|
||||
<!--
|
||||
s = "3+4+5+6*7/1*5^2^3" -- 16406262
|
||||
sidx = 0
|
||||
nxtch()
|
||||
get_token()
|
||||
Expr(0)
|
||||
if op!=0 then PopFactor() end if
|
||||
if length(opstack)!=1 then err("some error") end if
|
||||
printf(1,"expression: \"%s\"\n",{s})
|
||||
puts(1,"AST (flat): ")
|
||||
?opstack[1]
|
||||
puts(1,"AST (tree):\n")
|
||||
ppEx(opstack[1],{pp_Nest,9999})
|
||||
puts(1,"result: ")
|
||||
?evaluate(opstack[1])
|
||||
{} = wait_key()
|
||||
|
|
|
|||
87
Task/Arithmetic-evaluation/Pluto/arithmetic-evaluation.pluto
Normal file
87
Task/Arithmetic-evaluation/Pluto/arithmetic-evaluation.pluto
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
-- If string is empty, returns zero.
|
||||
local function to_double_or_zero(s)
|
||||
local n = tonumber(s)
|
||||
return n ? n : 0
|
||||
end
|
||||
|
||||
local function multiply(s)
|
||||
local b = s:split("*"):map(|c| -> to_double_or_zero(c))
|
||||
return tostring(b[1] * b[2])
|
||||
end
|
||||
|
||||
local function divide(s)
|
||||
local b = s:split("/"):map(|c| -> to_double_or_zero(c))
|
||||
return tostring(b[1] / b[2])
|
||||
end
|
||||
|
||||
local function add(s)
|
||||
local t = s:gsub("^%+", ""):gsub("%++", "+")
|
||||
local b = t:split("+"):map(|c| -> to_double_or_zero(c))
|
||||
return tostring(b[1] + b[2])
|
||||
end
|
||||
|
||||
local function subtract(s)
|
||||
local t = s:gsub("(%+%-|%-%+)", "-")
|
||||
if "--" in t then return add(t:replace("--", "+")) end
|
||||
local b = t:split("-"):map(|c| -> to_double_or_zero(c))
|
||||
return tostring(#b == 3 ? -b[2] - b[3] : b[1] - b[2])
|
||||
end
|
||||
|
||||
local function eval_exp(s)
|
||||
local t = s:gsub("[()]", "")
|
||||
local pmd = "%d+%.?%d*%s*[*/]%s*[+-]?%d+%.?%d*"
|
||||
local pm = "%*"
|
||||
local pas = "%-?%d+%.?%d*%s*[+-]%s*[+-]?%d+%.?%d*"
|
||||
local pa = "%d%+"
|
||||
|
||||
while true do
|
||||
local exp = t:match(pmd)
|
||||
if !exp then break end
|
||||
local exp2 = exp:match(pm)
|
||||
if exp2 then
|
||||
t = t:replace(exp, multiply(exp))
|
||||
else
|
||||
t = t:replace(exp, divide(exp))
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
local exp = t:match(pas)
|
||||
if !exp then break end
|
||||
local exp2 = exp:match(pa)
|
||||
if exp2 then
|
||||
t = t:replace(exp, add(exp))
|
||||
else
|
||||
t = t:replace(exp, subtract(exp))
|
||||
end
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
local function eval_arithmetic_exp(s)
|
||||
local t = s:gsub("%s", ""):gsub("^%+", "")
|
||||
local ppara = "%([^()]*%)"
|
||||
while true do
|
||||
local exp = t:match(ppara)
|
||||
if !exp then break end
|
||||
t = t:replace(exp, eval_exp(exp))
|
||||
end
|
||||
return to_double_or_zero(eval_exp(t))
|
||||
end
|
||||
({
|
||||
"2+3",
|
||||
"2+3/4",
|
||||
"2*3-4",
|
||||
"2*(3+4)+5/6",
|
||||
"2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10",
|
||||
"2*-3--4+-0.25",
|
||||
"-4 - 3",
|
||||
"((((2))))+ 3 * 5",
|
||||
"1 + 2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10",
|
||||
"1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + 1"
|
||||
}):foreach(|s| -> do
|
||||
local r = eval_arithmetic_exp(s)
|
||||
if r % 1.0 == 0 then r = math.round(r) end
|
||||
print($"{s} = {r}")
|
||||
end)
|
||||
117
Task/Arithmetic-evaluation/Rebol/arithmetic-evaluation.rebol
Normal file
117
Task/Arithmetic-evaluation/Rebol/arithmetic-evaluation.rebol
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
Rebol [
|
||||
title: "Rosetta code: Arithmetic evaluation"
|
||||
file: %Arithmetic_evaluation.r3
|
||||
url: https://rosettacode.org/wiki/Arithmetic_evaluation
|
||||
needs: 3.15.0 ;; or something like that
|
||||
note: "Ported Red language solution (Hinjolicious)!"
|
||||
purpose: {
|
||||
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).
|
||||
}
|
||||
]
|
||||
|
||||
s-expr: function/with [expr [string!] /trace] [
|
||||
output: copy [] ops: copy []
|
||||
tokens: split expr " "
|
||||
stats: either trace [:print-stats][none]
|
||||
while [not empty? tokens] [
|
||||
tok: first tokens tokens: next tokens
|
||||
case [
|
||||
find "0123456789" tok [
|
||||
act: "1.Push number as value"
|
||||
append output to integer! tok
|
||||
stats tok
|
||||
]
|
||||
tok = "(" [
|
||||
act: "2.Push ( to ops"
|
||||
append ops tok
|
||||
stats tok
|
||||
]
|
||||
tok = ")" [
|
||||
while [(last ops) <> "("] [
|
||||
act: "3.Pop op, build node"
|
||||
append/only output make-node take/last ops
|
||||
stats tok
|
||||
]
|
||||
act: "4.Discard ("
|
||||
take/last ops
|
||||
stats tok
|
||||
]
|
||||
find "+-*/^^" tok [
|
||||
while [popping] [
|
||||
act: "5.Pop op, build node"
|
||||
append/only output make-node take/last ops
|
||||
stats tok
|
||||
]
|
||||
act: "6.Push current op"
|
||||
append ops tok
|
||||
stats tok
|
||||
]
|
||||
]
|
||||
]
|
||||
act: "7.Final flush ops"
|
||||
stats " "
|
||||
while [not empty? ops] [
|
||||
act: "8.Pop op, build node"
|
||||
append/only output make-node take/last ops
|
||||
stats " "
|
||||
]
|
||||
output/1
|
||||
][
|
||||
output: ops: act: tok: tokens: none
|
||||
prec: #["+" 2 "-" 2 "*" 3 "/" 3 "^^" 4]
|
||||
asc: #["+" "L" "-" "L" "*" "L" "/" "L" "^^" "R"]
|
||||
print-stats: function [t] [
|
||||
print [t "|" pad act 25 "|" pad (mold output) 45 pad (reverse form ops) -15]
|
||||
]
|
||||
make-node: function [op] [
|
||||
right: take/last output
|
||||
left: take/last output
|
||||
node: load rejoin ["[" op " " mold left " " mold right "]"]
|
||||
node
|
||||
]
|
||||
popping: func [][
|
||||
if empty? ops [return false]
|
||||
if none? last ops [return false]
|
||||
last-op: last ops
|
||||
if last-op = ")" [return false]
|
||||
if none? prec/:last-op [return false]
|
||||
return (prec/:last-op > prec/:tok)
|
||||
or ((prec/:last-op = prec/:tok) and (asc/:tok = "L"))
|
||||
]
|
||||
]
|
||||
|
||||
; basic s-expression evaluator
|
||||
s-eval: function [expr][
|
||||
either block? expr [
|
||||
op: expr/1
|
||||
a: s-eval expr/2
|
||||
b: s-eval expr/3
|
||||
case [
|
||||
op = '+ [a + b]
|
||||
op = '- [a - b]
|
||||
op = '* [a * b]
|
||||
op = '/ [a / b]
|
||||
op = '^ [a ** b]
|
||||
true [do make error! rejoin ["Unknown operator: " mold op]]
|
||||
]
|
||||
][
|
||||
expr ; base case: just a number
|
||||
]
|
||||
]
|
||||
|
||||
print "Simple test:"
|
||||
s: "1 + 2" se: s-expr s printf [40 " ==> " 45 " = "] reduce [s mold se s-eval se]
|
||||
s: "1 + 2 * 3" se: s-expr s printf [40 " ==> " 45 " = "] reduce [s mold se s-eval se]
|
||||
s: "( 1 + 2 ) * 3" se: s-expr s printf [40 " ==> " 45 " = "] reduce [s mold se s-eval se]
|
||||
s: "( 1 + 2 * 3 ) / 2" se: s-expr s printf [40 " ==> " 45 " = "] reduce [s mold se s-eval se]
|
||||
|
||||
print "^/Complex ones:"
|
||||
s: "3 + 4 * 2 / ( 1 - 5 ) ^^ 2 ^^ 3" se: s-expr s printf [40 " ==> " 45 " = "] reduce [s mold se s-eval se]
|
||||
s: "( 1 + 2 * 3 ) ^^ 2 / 6 ^^ 2 ^^ 3 - 1" se: s-expr s printf [40 " ==> " 45 " = "] reduce [s mold se s-eval se]
|
||||
|
||||
print "^/Some test for input and output with trace:"
|
||||
print ["^/" s: "3 + 4 * 2 / ( 1 - 5 ) ^^ 2 ^^ 3"] se: s-expr/trace s print [s " ==> " mold se " = " s-eval se]
|
||||
print ["^/" s: "( ( 1 + 2 ) ^^ ( 3 + 4 ) ) ^^ ( 5 + 6 )"] se: s-expr/trace s print [s " ==> " mold se " = " s-eval se]
|
||||
print ["^/" s: "1 + 2 * 3 / 4 + 5"] se: s-expr/trace s print [s " ==> " mold se " = " s-eval se]
|
||||
Loading…
Add table
Add a link
Reference in a new issue