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