home *** CD-ROM | disk | FTP | other *** search
- ###########################################################################
- #
- # File: parse.icn
- #
- # Subject: Program to parse simple statements
- #
- # Author: Kenneth Walker
- #
- # Date: December 22, 1989
- #
- ############################################################################
-
- 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
-