Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: Evaluating a maths expression in a string?

From: g:santilli:tiscalinet:it at: 29-Dec-2000 20:47

Hello Andrew! On 29-Dic-00, you wrote: AM> IIRC, Gabriele had a maths parser which could be able to AM> handle this problem. It parses blocks only, but it can be adapted to parse strings. I hope not to annoy anyone if I repost it here. Regards, Gabriele. -- Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/ REBOL [ Title: "Expression evaluator" Author: "Gabriele Santilli <[giesse--writeme--com]>" Comment: { Evaluates expressions taking usual operator precedence into account. 1. (...) 2. - [negation], ! [factorial] 3. ^ [power] 4. *, / 5. +, - [subtraction] } ] ; A simple iterative implementation; returns 1 for negative ; numbers. FEEL FREE TO IMPROVE THIS! factorial: func [n [integer!] /local res] [ if n < 2 [return 1] res: 1 ; should avoid doing the loop for i = 1... repeat i n [res: res * i] ] expression-parser: make object! [ slash: to-lit-word first [ / ] expr-val: expr-op: none expression: [ term (expr-val: term-val) any [ ['+ (expr-op: 'add) | '- (expr-op: 'subtract)] term (expr-val: compose [(expr-op) (expr-val) (term-val)]) ] ] term-val: term-op: none term: [ pow (term-val: power-val) any [ ['* (term-op: 'multiply) | slash (term-op: 'divide)] pow (term-val: compose [(term-op) (term-val) (power-val)]) ] ] power-val: none pow: [ unary (power-val: unary-val) opt ['^ unary (power-val: compose [power (power-val) (unary-val)])] ] unary-val: pre-uop: post-uop: none unary: [ (post-uop: pre-uop: []) opt ['- (pre-uop: 'negate)] primary opt ['! (post-uop: 'factorial)] (unary-val: compose [(post-uop) (pre-uop) (prim-val)]) ] prim-val: none ; WARNING: uses recursion for parens. primary: [ set prim-val [number! | word!] | set prim-val paren! (prim-val: translate to-block :prim-val) ] translate: func [expr [block!] /local res recursion] [ ; to allow recursive calling, we need to preserve our state recursion: reduce [ :expr-val :expr-op :term-val :term-op :power-val :unary-val :pre-uop :post-uop :prim-val ] res: if parse expr expression [expr-val] set [ expr-val expr-op term-val term-op power-val unary-val pre-uop post-uop prim-val ] recursion res ] set 'eval func [expr [block!] /translate] [ expr: self/translate expr either translate [expr] [do expr] ] ]