Paste: infix math

Author: EdwardXXIV
Mode: factor
Date: Tue, 3 Feb 2009 20:22:36
Plain Text |
USING: ascii assocs fry kernel math math.parser multiline
namespaces parser peg.ebnf sequences strings words locals.parser
locals.types quotations summary ;
IN: math-parser

: prepare-operand ( term -- quot )
    dup callable? [ '[ _ call ] ] [ '[ _ ] ] if ;

: construct-op ( l r quot -- result/quot )
    2over [ number? ] both? [ call ] [ 
        [ [ prepare-operand ] bi@ ] dip compose compose
    ] if 
    ; inline

: +op ( l r -- result/quot ) [ + ] construct-op ; inline
: -op ( l r -- result/quot ) [ - ] construct-op ; inline
: *op ( l r -- result/quot ) [ * ] construct-op ; inline
: /op ( l r -- result/quot ) [ / ] construct-op ; inline

ERROR: local-not-defined name ;
M: local-not-defined summary
    drop "local is not defined" ;

: at? ( key assoc -- value/key ? ) dupd at* [ nip t ] [ drop f ] if ;

: >local-word ( string -- word )
    locals get at? [ local-not-defined ] unless ;

EBNF: math-parser
ident = [a-zA-z] [a-zA-Z_0-9]* => [[ first2 swap prefix >string >local-word ]]

num = ("-"|"+")? [0-9]+ "."? [0-9]* => [[ concat >string string>number ]]

sum-term = (sum-term ("-"|"+"))? product-term =>
    [[ first2 over [ [ first2 ] dip swap "+" = [ +op ] [ -op ] if ] [ nip ] if ]]

product-term = (product-term ("*"|"/"))? (paren-exp|terminal) =>
    [[ first2 over [ [ first2 ] dip swap "*" = [ *op ] [ /op ] if ] [ nip ] if ]]

paren-exp = "(" expression ")" => [[ second ]]
terminal = num | ident
expression = sum-term | terminal
;EBNF

: [math-parse ( end -- result/quot )
    parse-multiline-string [ blank? not ] filter math-parser
    dup number? [ '[ _ ] ] when ;

DEFER: math]
: [math
    "math]" [math-parse parsed \ call parsed ; parsing

: parse-math-locals ( assoc end -- quot )
    [
        in-lambda? on
        [ dup [ locals set ] [ push-locals ] bi ] dip
        [math-parse [ call ] curry swap pop-locals
    ] with-scope ;

: [math|
    "|" parse-bindings "math]" parse-math-locals <let>
    parsed-lambda ; parsing

New Annotation

Summary:
Author:
Mode:
Body: