Unfortunately, PostScript is not the easiest of languages to learn. If you only have to use PostScript sparingly, and if you use PostScript only as a calculator (for instance, in the PSTricks example), you can write your program in a simple functional language instead, and use psfc to compile your program into PostScript.
For example, to define the factorial function in PostScript, we must use
/fac {
1 dict
begin
/n exch def
n 0 eq {1 } {n n 1 sub fac mul } ifelse
end
} def
Using psfc however, you can simply define the factorial function as
fac(n) = if n == 0 then 1 else n * fac(n - 1) endif
name(x, y, ..) = expr
where name is the name of the function, x, y are parameters to the function. A function can have an arbitrary number of parameters (with a maximum of 256), or none at all. If the function has no parameters, no brackets should be used. For example:
function my_const_function = ...
Important: Every psfc should have a function called main. This function will be the "top-level" function that gets evaluated by the PostScript interpreter. Function "main" should not have any parameters.
five = 5 f(x) = x + five g(x,y) = x * y main = g(f(2), 3 + 4)
The following example shows a program to calculate 5!:
fac(n) = if n == 0 then 1 else n * fac(n - 1) endif main = fac(5)
Finally, an example that shows that function can return boolean values:
i(x) = if x == 0 or x == 1 then true else false endif h(x) = if i(x) == true then 5 else 10 endif main = (h(0) + h(1)) * h(2)
To compile and run any of these programs, use
psfc -i example1.pfc -o example1.ps -s gs example1.ps
main = x
Note that if you compile this program for use with PSTricks, the -s parameter should not be used.
pfc ::= fun_def*
fun_def ::= IDENT fun_args ’=’ expr
fun_args ::= ’(’ IDENT (’,’ IDENT)* ’)’
expr ::= IF cond THEN expr ELSE expr ENDIF
| expr ’+’ expr1
| expr ’-’ expr1
| expr1
expr1 ::= expr1 ’*’ expr2
| expr1 ’/’ expr2
| expr2
expr2 ::= VALUE
| IDENT args
| ’(’ expr ’)’
args ::= ’(’ expr (’,’ expr’)* ’)’
cond ::= cond OR cond1
| cond1
cond1 ::= cond1 AND cond2
| cond2
cond2 ::= expr BOOLOP expr2
| ’(’ cond ’)’
Note the precendence order implicit in the grammar: brackets, then multiplication and division (evaluated left to right), and finally addition and subtraction (also evaluated left to right). Similarly for boolean expressions, brackets have the highest precedence level, then AND, and finally OR.
Whitespace is ignored, as are comments. Comments start with "--" and run to the end of the line. Leaves to specify the lexical tokens used in the grammar:
IDENT ::= [a-zA-Z_][a-zA-Z_0-9]* INT ::= [+-]?[0-9]+(#[0-9]+)? REAL ::= [+-]?[0-9]*.[0-9]+(E[+-]?[0-9]+)? VALUE ::= INT|REAL