I think that is a great feature. Operator precedence always confused me. In Rebol, it
is done
left-right...the way it should have been done in other languages..
rishi
----- Original Message -----
From: <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Saturday, October 14, 2000 4:12 AM
Subject: [REBOL] Expression evaluator (an example of parsing blocks)
> Hi all!
>
> Have you been sometimes annoyed by tha fact REBOL does not support
> operator precedence? Here's the answer:
>
> >> a: 2 b: 4 c: 3
> == 3
> >> eval [b ^ 2 - 4 * a * c]
> == -8
>
> The magic trick is:
>
> >> eval/translate [b ^ 2 - 4 * a * c]
> == [subtract power b 2 multiply multiply 4 a c]
>
> Other examples:
>
> >> eval/translate [1 / k !]
> == [divide 1 factorial k]
> >> eval/translate [a * - b]
> == [multiply a negate b]
> >> eval/translate [e ^ (i / h * (p * x - E * t))]
> == [power e multiply divide i h subtract multiply p x multiply E t]
>
> NOTE: it still needs improvements, such as error handling. They
> are "left to the reader as an exercise". :-)
>
> Enjoy!,
> Gabriele.
> --
> Gabriele Santilli <[EMAIL PROTECTED]> - Amigan - REBOL programmer
> Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
>
> REBOL [
> Title: "Expression evaluator"
> Author: "Gabriele Santilli <[EMAIL PROTECTED]>"
> 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]
> ]
> ]
>
--
To unsubscribe from this list, please send an email to
[EMAIL PROTECTED] with "unsubscribe" in the
subject, without the quotes.