(*$R-*) (* turn range checking off *) (*$S+*) (* turn swapping on *) (* $L+*) (* no listing *) Unit ParseUnit; { This is a unit because the magiscan does have enough memory to hold it without swapping } Interface Uses M2Types,M2IpRoot,M2Sys; (* Parser Types *) type statustype = (null, at_eol, unconfirmed, parm_expected, ambiguous, unrec, fn_expected, ch_expected); vocab = (nullsym, zerosym, onesym, twosym, threesym, foursym, fivesym, sixsym, sevensym, eightsym, ninesym, allsym, baudsym, binsym, consym, datasym, debugsym, delsym, dirsym, disksym, escsym, evensym, exitsym, filewarnsym, helpsym, ibmsym, imagesym, loadsym, localsym, marksym, muxsym, nonesym, oddsym, offsym, onsym, paritysym, quitsym, recsym, sendsym, setsym, showsym, spacesym, textsym, transym, typesym ); (* Parser vars *) var noun, verb, adj : vocab; status : statustype; vocablist : array[vocab] of string[13]; value : integer; filename, line : string; newescchar : char; expected : set of vocab; procedure uppercase(var s: string); procedure initvocab; function parse: statustype; Implementation (* ---------------------------------------------------- *) procedure uppercase; var i: integer; begin for i := 1 to length(s) do if s[i] in ['a'..'z'] then s[i] := chr(ord(s[i]) - ord('a') + ord('A')) end; (* uppercase *) (* ---------------------------------------------------- *) function parse; type states = (start, fin, get_filename, get_set_parm, get_parity, get_on_off, get_char, get_show_parm, get_help_show, get_help_parm, get_value, exitstate, get_trans, get_type); var status: statustype; word: vocab; state: states; procedure eatspaces(var s: string); var done: boolean; i: integer; begin done := (length(s) = 0); while not done do begin if s[1] = ' ' then begin i := length(s) - 1; s := copy(s,2,i); done := length(s) = 0 end (* if *) else done := true end (* while *) end; (* eatspaces *) procedure isolate_word(var line, s: string); var i: integer; done: boolean; begin done := false; i := 1; s := copy(' ',0,0); while (i <= length(line)) and not done do begin if line[i] = ' ' then done := true else s := concat(s,copy(line,i,1)); i := i + 1; end; (* while *) line := copy(line,i,length(line)-i+1); end; (* isolate_word *) function get_fn(var line, fn: string): boolean; var i, l: integer; begin get_fn := true; isolate_word(line, fn); l := length(fn); if (l < 1) then get_fn := false end; (* get_fn *) function getch(var ch: char): boolean; var s: string; begin isolate_word(line,s); if length(s) <> 1 then getch := false else begin ch := s[1]; get_ch := true end (* else *) end; (* getch *) function get_sym(var word: vocab): statustype; var i: vocab; s: string; stat: statustype; done: boolean; matches: integer; begin eat_spaces(line); if length(line) = 0 then getsym := ateol else begin stat := null; done := false; isolate_word(line,s); i := allsym; matches := 0; repeat if (pos(s,vocablist[i]) = 1) and (i in expected) then begin matches := matches + 1; word := i end else if (s[1] < vocablist[i,1]) then done := true; if (i = typesym) then done := true else i := succ(i) until (matches > 1) or done; if matches > 1 then stat := ambiguous else if (matches = 0) then stat := unrec; getsym := stat end (* else *) end; (* getsym *) function get_val(var value : integer): statustype; var i: vocab; s: string; stat: statustype; gotval,done: boolean; function NewVal(Value : integer; S : vocab ) : integer; begin case S of zerosym : NewVal := Value * 10 + 0; onesym : NewVal := Value * 10 + 1; twosym : NewVal := Value * 10 + 2; threesym : NewVal := Value * 10 + 3; foursym : NewVal := Value * 10 + 4; fivesym : NewVal := Value * 10 + 5; sixsym : NewVal := Value * 10 + 6; sevensym : NewVal := Value * 10 + 7; eightsym : NewVal := Value * 10 + 8; ninesym : NewVal := Value * 10 + 9 end{case} end{NewVal}; function NextDigit : boolean; var i : integer; begin if length(s) <= 1 then NextDigit := False else begin i := length(s) - 1; s := copy(s,2,i); NextDigit := True end end{NextDigit}; begin eat_spaces(line); if length(line) = 0 then getval := ateol else begin stat := null; done := false; isolate_word(line,s); value := 0; repeat GotVal := False; for i := zerosym to ninesym do if (s[1] = vocablist[i][1]) then begin Value := NewVal(value,i); GotVal := True end; if not GotVal then begin stat := unrec; done := True end else done := not NextDigit until done; getval := stat end (* else *) end; (* getval *) begin state := start; parse := null; noun := nullsym; verb := nullsym; adj := nullsym; uppercase(line); repeat case state of start: begin expected := [consym, exitsym, helpsym, quitsym, recsym, delsym, dirsym, sendsym, setsym, showsym, transym, loadsym]; status := getsym(verb); if status = ateol then begin parse := null; exit(parse) end (* if *) else if (status <> unrec) and (status <> ambiguous) then case verb of dirsym, consym: state := fin; exitsym, quitsym: state := fin; helpsym: state := get_help_parm; recsym: state := fin; loadsym, delsym, sendsym: state := getfilename; setsym: state := get_set_parm; showsym: state := get_show_parm; transym: state := get_trans; end (* case *); end; (* case start *) fin: begin expected := []; status := getsym(verb); if status = ateol then begin parse := null; exit(parse) end (* if status *) else status := unconfirmed end; (* case fin *) getfilename: begin expected := []; if getfn(line,filename) then begin status := null; state := fin end (* if *) else status := fnexpected end; (* case get file name *) get_trans: begin expected := [typesym]; status := getsym(noun); if status = ateol then status := parm_expected else if (status <> unrec) and (status <> ambiguous) then case noun of typesym: state := get_type; end (* case *) end; (* case get_set_parm *) get_set_parm: begin expected := [paritysym, localsym, ibmsym, escsym, muxsym, disksym, debugsym, filewarnsym, baudsym]; status := getsym(noun); if status = ateol then status := parm_expected else if (status <> unrec) and (status <> ambiguous) then case noun of paritysym: state := get_parity; localsym: state := get_on_off; ibmsym: state := get_on_off; escsym: state := getchar; debugsym: state := getonoff; filewarnsym: state := getonoff; muxsym, baudsym : state := getvalue; disksym : state := getvalue; transym : state := get_on_off; end (* case *) end; (* case get_set_parm *) get_type: begin expected := [binsym, datasym, imagesym, textsym]; status := getsym(adj); if status = ateol then status := parm_expected else if (status <> unrec) and (status <> ambiguous) then state := fin end; (* case get_parity *) get_parity: begin expected := [marksym, spacesym, nonesym, evensym, oddsym]; status := getsym(adj); if status = ateol then status := parm_expected else if (status <> unrec) and (status <> ambiguous) then state := fin end; (* case get_parity *) get_value: begin expected := [zerosym, onesym, twosym, threesym, foursym, fivesym, sixsym, sevensym, eightsym, ninesym]; status := getval(value); if status = ateol then status := parm_expected else if (status <> unrec) and (status <> ambiguous) then state := fin end; (* get_speed *) get_on_off: begin expected := [onsym, offsym]; status := getsym(adj); if status = ateol then status := parm_expected else if (status <> unrec) and (status <> ambiguous) then state := fin end; (* get_on_off *) get_char: if getch(newescchar) then state := fin else status := ch_expected; get_show_parm: begin expected := [allsym, paritysym, localsym, ibmsym, escsym, muxsym, transym, disksym, baudsym, debugsym, filewarnsym]; status := getsym(noun); if status = ateol then status := parm_expected else if (status <> unrec) and (status <> ambiguous) then state := fin end; (* case get_show_parm *) get_help_show: begin expected := [paritysym, localsym, ibmsym, escsym, debugsym, filewarnsym]; status := getsym(adj); if (status = at_eol) then begin status := null; state := fin end else if (status <> unrec) and (status <> ambiguous) then state := fin end; (* case get_help_show *) get_help_parm: begin expected := [consym, delsym, exitsym, helpsym, quitsym, recsym, dirsym, transym, sendsym, setsym, showsym]; status := getsym(noun); if status = ateol then begin parse := null; exit(parse) end; if (status <> unrec) and (status <> ambiguous) then case noun of consym: state := fin; sendsym: state := fin; recsym: state := fin; setsym: state := get_help_show; showsym: state := fin; helpsym: state := fin; exitsym, quitsym: state := fin; end (* case *) end; (* case get_help_show *) end (* case *) until (status <> null); parse := status end; (* parse *) (* ---------------------------------------------------- *) procedure initvocab; var i: integer; begin vocablist[zerosym] := '0'; vocablist[onesym] := '1'; vocablist[twosym] := '2'; vocablist[threesym] := '3'; vocablist[foursym] := '4'; vocablist[fivesym] := '5'; vocablist[sixsym] := '6'; vocablist[sevensym] := '7'; vocablist[eightsym] := '8'; vocablist[ninesym] := '9'; vocablist[allsym] := 'ALL'; vocablist[baudsym] := 'BAUDRATE'; vocablist[binsym] := 'BINARY'; vocablist[consym] := 'CONNECT'; vocablist[datasym] := 'DATA'; vocablist[debugsym] := 'DEBUG'; vocablist[delsym] := 'DELETE'; vocablist[dirsym] := 'DIRECTORY'; vocablist[disksym] := 'DISK'; vocablist[escsym] := 'ESCAPE'; vocablist[evensym] := 'EVEN'; vocablist[exitsym] := 'EXIT'; vocablist[filewarnsym] := 'FILE-WARNING'; vocablist[helpsym] := 'HELP'; vocablist[ibmsym] := 'IBM'; vocablist[imagesym] := 'IMAGE'; vocablist[loadsym] := 'LOAD'; vocablist[localsym] := 'LOCAL-ECHO'; vocablist[marksym] := 'MARK'; vocablist[muxsym] := 'MUX'; vocablist[nonesym] := 'NONE'; vocablist[oddsym] := 'ODD'; vocablist[offsym] := 'OFF'; vocablist[onsym] := 'ON'; vocablist[paritysym] := 'PARITY'; vocablist[quitsym] := 'QUIT'; vocablist[recsym] := 'RECEIVE'; vocablist[sendsym] := 'SEND'; vocablist[setsym] := 'SET'; vocablist[showsym] := 'SHOW'; vocablist[spacesym] := 'SPACE'; vocablist[transym] := 'TRANSFER'; vocablist[textsym] := 'TEXT'; vocablist[typesym] := 'TYPE'; end; (* initvocab *) (* ---------------------------------------------------- *) end{Parse}.