diff options
Diffstat (limited to 'ipl/progs/parse.icn')
-rw-r--r-- | ipl/progs/parse.icn | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/ipl/progs/parse.icn b/ipl/progs/parse.icn new file mode 100644 index 0000000..ee3c11c --- /dev/null +++ b/ipl/progs/parse.icn @@ -0,0 +1,133 @@ +############################################################################ +# +# File: parse.icn +# +# Subject: Program to parse simple statements +# +# Author: Kenneth Walker +# +# Date: February 18, 1996 +# +############################################################################ +# +# This file is in the public domain. +# +############################################################################ +# +# This program parses simple statements. +# +# It provides an interesting example of the use of co-expressions. +# +############################################################################ + +global lex # co-expression for lexical analyzer +global next_tok # next token from input + +record token(type, string) + +procedure main() + lex := create ((!&input ? get_tok()) | |token("eof", "eof")) + prog() +end + +# +# get_tok is the main body of lexical analyzer +# +procedure get_tok() + local tok + repeat { # skip white space and comments + tab(many(' ')) + if ="#" | pos(0) then fail + + if any(&letters) then # determine token type + tok := token("id", tab(many(&letters ++ '_'))) + else if any(&digits) then + tok := token("integer", tab(many(&digits))) + else case move(1) of { + ";" : tok := token("semi", ";") + "(" : tok := token("lparen", "(") + ")" : tok := token("rparen", ")") + ":" : if ="=" then tok := token("assign", ":=") + else tok := token("colon", ":") + "+" : tok := token("add_op", "+") + "-" : tok := token("add_op", "-") + "*" : tok := token("mult_op", "*") + "/" : tok := token("mult_op", "/") + default : err("invalid character in input") + } + suspend tok + } +end + +# +# The procedures that follow make up the parser +# + +procedure prog() + next_tok := @lex + stmt() + while next_tok.type == "semi" do { + next_tok := @lex + stmt() + } + if next_tok.type ~== "eof" then + err("eof expected") +end + +procedure stmt() + if next_tok.type ~== "id" then + err("id expected") + write(next_tok.string) + if (@lex).type ~== "assign" then + err(":= expected") + next_tok := @lex + expr() + write(":=") +end + +procedure expr() + local op + + term() + while next_tok.type == "add_op" do { + op := next_tok.string + next_tok := @lex + term() + write(op) + } +end + +procedure term() + local op + + factor() + while next_tok.type == "mult_op" do { + op := next_tok.string + next_tok := @lex + factor() + write(op) + } +end + +procedure factor() + case next_tok.type of { + "id" | "integer": { + write(next_tok.string) + next_tok := @lex + } + "lparen": { + next_tok := @lex + expr() + if next_tok.type ~== "rparen" then + err(") expected") + else + next_tok := @lex + } + default: + err("id or integer expected") + } +end + +procedure err(s) + stop(" ** error ** ", s) +end |