FALSE [IF] ******** ANS-compatible FORmula TRANslator ******** filenames: ftran2xx.f --------------------------------------------------- (C) Copyright 2001, 2004 Julian V. Noble. Permission is granted by the author to use this software for any application pro- vided this copyright notice is preserved, as per GNU Public License agreement. --------------------------------------------------- ---------------------------------------------------------------- Usage: Convert formula to Forth on the screen: f" a=b*c-3.17e-5/tanh(w)+abs(x)" b F@ c F@ F* .317000E-4 w F@ FTANH F/ F- x F@ FABS F+ a F! ok Evaluate an expression and leave the result on the stack: fvariable x fvariable y ok f\$" x=3" f\$" y=4" ok f\$" x*(x^2+y^2)" f. 75.0000 ok Compile formula into Forth word: fvariable x ok fvariable w ok fvariable c ok fvariable b ok fvariable a ok : test f" a=b*c-3.17e-5/tanh(w)+abs(x)" ; ok see test : TEST B F@ C F@ F* flit 3.17000E-5 W F@ FTANH F/ F- X F@ FABS F+ A F! ; ok Numeric literals: You do NOT need to include an exponent, all numeric literals are converted to floating point literals. However, positive integers in exponents, a^n, n in the range 1-4, are parsed as f^2, f^3, f^4 or the complex equivalents. Multiple formulas, long furmulas: A word can contain several formulas, as in : test1 f" a=b*c+sin(w)" rot dup * f" x=-3.75e6/a" ; ok see test1 : TEST1 B F@ C F@ F* W F@ FSIN F+ A F! ROT DUP * flit -3.75000E6 A F@ F/ X F! ; ok Formulas can extend over multiple lines, to a maximum of 255 characters, e.g. : test4 f" a=b*c -x/cosh(w)" ; ok see test4 : TEST4 B F@ C F@ F* X F@ W F@ FCOSH F/ F- A F! ; ok Complex arithmetic: ftran2xx.f now handles formulas with complex functions and variables. Real literals are converted to complex numbers, as in 3.75e0 -> 3.75e0 + i 0.0e0, so if you want to include a complex literal, use the FORTRANish locution cmplx(3.75,-4.21). At the moment all variables in a complex expression must be complex, and all functions must return complex numbers. The locutions that correspond to f" and f\$" are zz" and zz\$" . The latter name was chosen because Win32Forth already has z" defined in the file primutil.f . I have no idea what z" is supposed to do. Ftran2xx.f does NO type-checking. Making sure that types are consistent is the obligation of the programmer. Parsing rules: Ftran2xx.f parses according to Fortran rules, EXCEPT: - Exponentiation is done with ^ a la Basic, rather than with ** as in Fortran; - Assignments have the form "var_name = expression" ; - Formulas do NOT have to be assignments. That is, expressions like f" a*(b+x)-w" are valid. Thus f" a*(b+x)-w" will compile it within a word, or will interactively translate it and display the result on the screen. ********** January 15th, 2004 - 12:57 *********************** New capabilities of ftran202.f Passing addresses as arguments in formulas: ftran201.f assumed functions would find their arguments on the fp stack. That is, atan2 is parsed as f" atan2(x,y)" -> x F@ y F@ FATAN2 However, some functions would like arguments passed as addresses. ftran202.f lets you enclose such an argument in square braces, as in [a]. This can be useful if the argument is an array name. Thus f" Smul(lambda,[a])" -> lambda F@ a Smul You can include curly braces, as in f" Smul(lambda,[a{ 0 }])" -> lambda F@ a{ 0 } Smul (see Arrays below) CONSTANT function arguments and formula elements: The square brace notation can obviously handle FCONSTANTs or FVALUEs (providing the latter have been defined) in expressions, as with FVARIABLE a ok f\$" a=2" ok 3e0 FCONSTANT x ok f\$" a*[x]" f. 6.00000 ok f\$" [x] + a" f. 5.00000 ok : test FDUP FNEGATE FEXP F* ; f\$" test(a)" f. .270671 ok f\$" test([x])" f. .149361 ok This is entirely ANS-compatible and should be portable to any ANS-compliant system within the environmental restriction to a separate floating point stack. CAVEAT #1: Constructions like 0e0 FVALUE y f\$" [y] = a*[x]" will not work because the parser cannot tell the difference between an FVALUE and an FVARIABLE, so it doesn't know it should use FTO rather than F! CAVEAT #2: As noted above, ftran2xx.f does NO type-checking and only minimal grammatical checking. Therefore it is up to the programmer to enforce consistency with these rules. ************************************************************* Arrays: Ftran2xx.f handles arrays in "Scientific FORTH" notation: include arrays.f 10 long 1 floats 1array v{ ok : test 0 do f" v{ I } =3" loop ; ok see test : TEST 0 DO flit 3.00000 V{ I } F! LOOP ; ok The space between curly braces {} can contain a Forth index or other Forth code, as in v{ I 3 + } . You MUST include the appropriate blanks or you will get error messages. There can be no blanks or characters between successive {'s or successive }'s. In accordance with this notation, 2-dimensional arrays have names like a{{ and are dereferenced with the oper- ator }} . Thus ftran2xx.f recognizes a{{ I J }}; a{{I J}} however, does not contain the requisite blanks following a{{ and preceding }} so it will not be accepted during input. include arrays.f 3 long 1 floats 1array v{ : test3 2 0 do f" v{I}=a" loop ; first char after last { must be blank : test3 2 0 do f" v{ I}=a" loop ; last char before 1st } must be blank : test3 2 0 do f" v{ I }=a" loop ; Error: a is undefined fvariable a : test3 2 0 do f" v{ I }=a" loop ; ok see test3 : TEST3 lit "0x2" 0 DO A F@ V{ I } F! LOOP ; ok f" m{{ I J }} = [a]" a m{{ I J }} F! ok ------------------------ INSIDE THE COMPILER ------------------------- ---------------------------------------- Environmental dependencies: ANS CORE EXT, FLOAT, FLOAT EXT and TOOLS EXT wordsets ---------------------------------------- ---------------------------------------- Non STANDARD, but common words: OFF (alias 0!) store 0 to a cell NOOP "no operation" : NOOP ; PERFORM == @ EXECUTE CAPS-FIND (Win32Forth 3.5) .NAME (SwiftForth, WinForth & GForth) ---------------------------------------- Compiler documentation: ----------------------------- Backus-Naur Rules for mini FORTRAN NOTATION: | -> "or", + -> "unlimited repetitions" Q -> "empty set" & -> + | - % -> * | / f^f -> "factor raised to power of another factor" EXAMPLE: {-|Q} means "minus sign or nothing" NUMBERS: fp# -> {-|Q}{digit.digit+ | .digit digit+} exponent exponent -> {dDeE {&|Q} digit {digit|Q} {digit|Q} | Q} FORMULAS: assignment -> id = expression id -> name | name {+ Forth }+ --curly braces balance! name -> letter {letter|digit}+ arglist -> ( expression {,expression}+ ) function -> id arglist expression -> term | expression & term term -> factor | term % factor factor -> id | fp# | ( expr ) | f^f | function ------------------------------------------ end Backus-Naur Rules --------------------------------------- Description of algorithm This mini compiler uses recursive descent. It translates a valid expression or assignment statement into Forth code "on the fly". The key data structures are 1. Input buffer -- left intact 2. Output buffer 3. 3 cells wide stack holding pointers and operator tokens (it must have enough levels not to overflow during expression parsing) The input string (formula) is translated to an output string containing the Forth code. The words f", and f\$" begin the formula input and translation, and differ only in how they treat the output string. "Exposed" (in the word op_find) means "not enclosed in parentheses". To ensure the proper order of operator precedence, the parser first decomposes expressions by terms at exposed + or - signs, then parses terms by factors, at exposed * or / operators, and finally treats exponentials (factor^factor) and functions, in that order. Thus the precedence, in decreasing order of evaluation priority, is function ^ */ +- Recursion is implemented via deferred definitions. Since ANS Forth does not contain the commonly employed words DEFER and IS, I have defined similar ones, together with some utilities, in the INCLUDEd file vector1.f . The fundamental coding paradigm (besides recursion) is the finite state machine. The FSM employed here uses a minicompiler that compiles the transition-table representation of a FSM to a Forth subroutine (word) embodying the FSM. See, e.g., http://www.jfar.org/article001.html The FSM code is contained in the INCLUDEd file fsm2.f . Characters input to a FSM are generally translated to a small set of numeric tokens using an automated translation table. The table translation code is INCLUDEd in chr_tbl.f . ----------------------------------- end description of algorithm ---------------------------------------------------------------------- [THEN]