|
|
1.1 ! root 1: functor Parse(F : FORMULA) : PARSE = ! 2: struct ! 3: structure F = F ! 4: ! 5: exception Syntax of string ! 6: ! 7: datatype token = NUMtok of int ! 8: | ALPHAtok of string ! 9: | PUNCTtok of string ! 10: | EOFtok ! 11: ! 12: fun for (i,j) f = if i<=j then (f i; for(i+1,j) f) else () ! 13: fun forall (a::r) f = (f a; forall r f) ! 14: | forall nil f = () ! 15: ! 16: datatype class = DIGIT | BLANK | ALPHA | PUNCT | OTHER | EOF ! 17: val class = array(257,OTHER) ! 18: val _ = ! 19: (for (ord "0", ord "9") (fn s => update(class,s,DIGIT)); ! 20: for (ord "a", ord "z") (fn s => update(class,s,ALPHA)); ! 21: for (ord "A", ord "Z") (fn s => update(class,s,ALPHA)); ! 22: forall [" ","\t","\n"] (fn s => update(class,(ord s),BLANK)); ! 23: forall ["(",")","[","]",",","+","-","*","/"] ! 24: (fn s => update(class,(ord s),PUNCT)); ! 25: update(class, 256, EOF)) ! 26: ! 27: fun parse(str : string) : F.formula = ! 28: let fun gettoken pos = ! 29: let fun char(p) = ordof(str,p) handle Ord => 256 ! 30: fun digit(z,p) = ! 31: let val c = char p ! 32: in case class sub c ! 33: of DIGIT => digit(z*10+c-ord("0"), p+1) ! 34: | _ => (p, NUMtok z) ! 35: end ! 36: fun alpha(s,p) = ! 37: let val c = char p ! 38: in case class sub c ! 39: of ALPHA => alpha(s,p+1) ! 40: | _ => (p, ALPHAtok(substring(str,s,p-s))) ! 41: end ! 42: val c = char pos ! 43: in case class sub c ! 44: of BLANK => gettoken(pos+1) ! 45: | ALPHA => alpha(pos,pos) ! 46: | DIGIT => digit(0,pos) ! 47: | PUNCT => (pos+1, PUNCTtok(chr c)) ! 48: | EOF => (pos, EOFtok) ! 49: | _ => raise (Syntax "illegal character") ! 50: end ! 51: ! 52: fun atom (p, NUMtok n) = (gettoken p, F.NUM n) ! 53: | atom (p, PUNCTtok "[") = ! 54: (case exp(gettoken p) ! 55: of ((p1, PUNCTtok ","), e1) => ! 56: (case exp(gettoken p1) ! 57: of ((p2, PUNCTtok "]"), e2) => ! 58: (gettoken p2, F.CELLREF(e1,e2)) ! 59: | _ => raise (Syntax "] expected")) ! 60: | _ => raise (Syntax ", expected")) ! 61: | atom (p, PUNCTtok "(") = ! 62: (case exp(gettoken p) ! 63: of ((p1, PUNCTtok ")"), e1) => (gettoken p1, e1) ! 64: | _ => raise (Syntax ") expected")) ! 65: | atom _ = raise (Syntax "bogus atom") ! 66: ! 67: and term' ((p, PUNCTtok "*"), e1) = ! 68: let val (s, e2) = atom(gettoken p) ! 69: in term'(s, F.BINOP(Integer.*, e1, e2)) ! 70: end ! 71: | term' ((p, PUNCTtok "/"), e1) = ! 72: let val (s, e2) = atom(gettoken p) ! 73: in term'(s, F.BINOP(Integer.div, e1, e2)) ! 74: end ! 75: | term' x = x ! 76: ! 77: and term s = term' (atom s) ! 78: ! 79: and exp' ((p, PUNCTtok "+"), e1) = ! 80: let val (s, e2) = term(gettoken p) ! 81: in exp'(s, F.BINOP(Integer.+, e1, e2)) ! 82: end ! 83: | exp' ((p, PUNCTtok "-"), e1) = ! 84: let val (s, e2) = term(gettoken p) ! 85: in exp'(s, F.BINOP(Integer.-, e1, e2)) ! 86: end ! 87: | exp' x = x ! 88: ! 89: and exp (p, ALPHAtok "if") = ! 90: (case exp(gettoken p) ! 91: of ((p',ALPHAtok "then"),e1) => ! 92: (case exp(gettoken p') ! 93: of ((p'', ALPHAtok "else"),e2) => ! 94: (case exp(gettoken p'') ! 95: of (s,e3) => (s, F.IF(e1,e2,e3))) ! 96: | _ => raise (Syntax "else expected")) ! 97: | _ => raise (Syntax "then expected")) ! 98: | exp s = exp' (term s) ! 99: ! 100: in case exp (gettoken 0) ! 101: of ( (_, EOFtok), e) => e ! 102: | _ => raise (Syntax "garbage at end of formula") ! 103: end ! 104: ! 105: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.