(*>>>>>>>>>>>>PARSER>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*) (*$S+*) (*$I-*) (*$R-*) (*$V-*) UNIT parser; INTRINSIC CODE 23 DATA 24; INTERFACE USES kermglob, kermutil; FUNCTION parse: statustype; IMPLEMENTATION VAR first_sym, last_sym : vocab; PROCEDURE isolate_word ( var line, word : string; var wlen : integer ); var line_len : integer; begin word := ''; wlen := 0; linelen := length( line ); if linelen > 0 then begin delete( line, 1, scan( linelen, <> ' ', line[1] ) ); linelen := length( line ); if linelen > 0 then begin wlen := scan( linelen, = ' ', line[1] ); word := copy( line, 1, wlen ); delete( line, 1, wlen ); end; end; end; { isolate_word } FUNCTION get_fn( var line, fn: string; namelen : integer ) : boolean; checks the length of the filename requested for 'send'. Or checks the prefix volume name for files to be received. var i, l: integer; begin get_fn := true; isolate_word( line, fn, l ); if (l > namelen) or (l < 1) then get_fn := false { max filename length, incl. volumename = 23 } { max volumename length, incl. ':' = 8 } else begin if (fn[l] = ':') and (namelen=23) then get_fn := false; if (fn[l] <> ':') and (namelen=8) then get_fn := false; { legality of volume and filename will be tested } { when the file is actually opened. ( see unit "sender" ) } end; end; (* get_fn *) FUNCTION get_num( var line: string; var n: integer ): boolean; var numstr: string; i, numstr_len : integer; begin get_num := true; n := 0; isolate_word( line, numstr, numstr_len ); if (numstr_len < 6) and (numstr_len > 0) then begin i := 1; numstr := concat( numstr, ' ' ); while (numstr[i] in ['0'..'9']) do begin if n<(maxint div 10) then n := n*10 + ord( numstr[i] ) - ord( '0' ); i := i + 1 end { while } end; { if } if n = 0 then get_num := false; end; { get_num } FUNCTION nextch(var ch: char): boolean; var s: string; ch_len : integer; begin isolate_word( line, s, ch_len ); if ch_len <= 1 then begin if ch_len = 1 then ch := s[1] else ch := cr; nextch := true; end else nextch := false; end; (* nextch *) FUNCTION get_sym(var word: vocab): statustype; var i: vocab; s: string; stat: statustype; done: boolean; matches, slen : integer; begin isolate_word( line, s, slen ); if slen = 0 then getsym := ateol else begin stat := null; done := false; i := first_sym; 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 = last_sym ) 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 parse(*: statustype*); type states = (start, fin, get_filename, get_set_parm, get_parity, get_on_off, get_esc_char, get_show_parm, get_help_show, get_help_parm, exitstate, get_baud, get_wordlen, get_stopbit, get_xon_char, get_xoff_char, get_xoffwait, get_nofeed, get_timeout, get_maxpak, get_eoln_char, get_maxtry, get_prefix, get_dir); var status: statustype; word: vocab; state: states; procedure case_start; begin expected := [consym, exitsym, helpsym, phelpsym, quitsym, recsym, sendsym, setsym, showsym, pshowsym, dirsym, pdirsym]; 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 consym, recsym, exitsym, quitsym: state := fin; helpsym : begin state := get_help_parm; pr_out:= false end; phelpsym : begin state := get_help_parm; pr_out:= true end; dirsym : begin state := get_dir; pr_out := false; end; pdirsym : begin state := get_dir; pr_out := true; end; sendsym : state := getfilename; setsym : state := get_set_parm; showsym : begin state := get_show_parm; pr_out:= false end; pshowsym : begin state := get_show_parm; pr_out:= true end; end (* case *) end; (* case_start *) procedure case_fin; begin expected := []; status := getsym(verb); if status = ateol then begin parse := null; exit(parse) end (* if status *) else status := unconfirmed end; (* case_fin *) procedure case_getfilename; begin expected := []; if getfn(line,xfilename,23) then begin status := null; state := fin end (* if *) else status := fnexpected end; (* case_getfilename *) procedure case_gtprefixname; begin expected := []; if getfn(line,newprefix_vol,8) then begin status := null; state := fin end else status := pnexpected end; (* case_gtprefixname *) procedure case_getsetparm; begin expected := [paritysym, localsym, ibmsym, escsym, prefixsym, wordlensym, stopbsym, delsym, debugsym, filewarnsym, baudsym, xonsym, xoffsym, xoffwaitsym, nofeedsym, timeoutsym, eolnsym, maxtrysym, emulatesym, maxpsym, textfsym, rejectsym]; 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; prefixsym: state := get_prefix; escsym: state := get_esc_char; baudsym: state := get_baud; wordlensym: state := get_wordlen; stopbsym: state := get_stopbit; xonsym: state := get_xon_char; xoffsym: state := get_xoff_char; eolnsym: state := get_eoln_char; xoffwaitsym: state := get_xoffwait; timeoutsym: state := get_timeout; maxtrysym: state := get_maxtry; maxpsym: state := get_maxpak; nofeedsym, filewarnsym, debugsym, delsym, textfsym, ibmsym, localsym, rejectsym, emulatesym: state := get_on_off; end (* case *) end; (* case_getsetparm *) procedure case_getparity; 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_getparity *) procedure case_getnum( var newnum : integer ); begin expected := []; if get_num( line, newnum ) then begin status := null; state := fin end else status := num_expected end; (* case_getnum *) procedure case_getonoff; 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; (* case_ getonoff *) procedure case_getchar( var newchar : char ); begin if nextch(newchar) then state := fin else status := ch_expected; end; (* case_getchar *) procedure case_gtshowparm; begin expected := [allsym, paritysym, localsym, ibmsym, prefixsym, wordlensym, stopbsym, escsym, delsym, debugsym, filewarnsym, baudsym, xonsym, xoffsym, xoffwaitsym, nofeedsym, timeoutsym, eolnsym, emulatesym, maxpsym, maxtrysym, textfsym, rejectsym]; status := getsym(noun); if status = ateol then status := parm_expected else if (status <> unrec) and (status <> ambiguous) then state := fin end; (* case_gtshowparm *) procedure case_gethelpshow; begin expected := [paritysym, localsym, ibmsym, escsym, delsym, wordlensym, stopbsym, debugsym, filewarnsym, baudsym, xonsym, xoffsym, xoffwaitsym, emulatesym, nofeedsym, timeoutsym, eolnsym, prefixsym, maxpsym, maxtrysym, textfsym, rejectsym]; 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_gethelpshow *) procedure case_gthelpparm; begin expected := [consym, exitsym, helpsym, phelpsym, quitsym, recsym, sendsym, setsym, showsym, pshowsym, dirsym, pdirsym]; status := getsym(noun); if status = ateol then begin parse := null; exit(parse) end; if (status <> unrec) and (status <> ambiguous) then case noun of consym, sendsym, recsym, showsym, pshowsym, helpsym, phelpsym, exitsym, quitsym, dirsym, pdirsym : state := fin; setsym : state := get_help_show; end (* case *) end; (* case_gthelpparm *) begin (* parse *) state := start; parse := null; noun := nullsym; verb := nullsym; adj := nullsym; uppercase ( line ); repeat case state of start : case_start; fin : case_fin; get_filename : case_getfilename; get_prefix : case_gtprefixname; get_set_parm : case_getsetparm; get_parity : case_getparity; get_baud : case_getnum( newbaud ); get_wordlen : case_getnum( newdbit ); get_stopbit : case_getnum( newstopbit ); get_xoffwait : case_getnum( newxoffwait); get_timeout : case_getnum( newtimeout ); get_maxtry : case_getnum( newmaxtry ); get_maxpak : case_getnum( newmaxpack ); get_dir : case_getnum( vol_num ); get_on_off : case_getonoff; get_esc_char : case_getchar( newescchar ); get_xon_char : case_getchar( newxonchar ); get_xoff_char : case_getchar( newxoffchar); get_eoln_char : case_getchar( newxeol_char ); get_show_parm : case_gtshowparm; get_help_show : case_gethelpshow; get_help_parm : case_gthelpparm; end; { case } until (status <> null); parse := status end; (* parse *) BEGIN { initialization } vocablist[allsym] := 'ALL'; vocablist[baudsym] := 'BAUD'; vocablist[consym] := 'CONNECT'; vocablist[debugsym] := 'DEBUG'; vocablist[delsym] := 'DELKEY'; vocablist[dirsym] := 'DIRECTORY'; vocablist[emulatesym] := 'EMULATE'; vocablist[eolnsym] := 'END-OF-LINE'; vocablist[escsym] := 'ESCAPE'; vocablist[evensym] := 'EVEN'; vocablist[exitsym] := 'EXIT'; vocablist[filewarnsym] := 'FILE-WARNING'; vocablist[helpsym] := 'HELP'; vocablist[ibmsym] := 'IBM'; vocablist[localsym] := 'LOCAL-ECHO'; vocablist[marksym] := 'MARK'; vocablist[maxpsym] := 'MAXPACK'; vocablist[maxtrysym] := 'MAXTRY'; vocablist[nofeedsym] := 'NOFEED'; vocablist[nonesym] := 'NONE'; vocablist[oddsym] := 'ODD'; vocablist[offsym] := 'OFF'; vocablist[onsym] := 'ON'; vocablist[paritysym] := 'PARITY'; vocablist[pdirsym] := 'PDIRECTORY'; vocablist[phelpsym] := 'PHELP'; vocablist[prefixsym] := 'PREFIX'; vocablist[pshowsym] := 'PSHOW'; vocablist[quitsym] := 'QUIT'; vocablist[recsym] := 'RECEIVE'; vocablist[rejectsym] := 'REJECT'; vocablist[sendsym] := 'SEND'; vocablist[setsym] := 'SET'; vocablist[showsym] := 'SHOW'; vocablist[spacesym] := 'SPACE'; vocablist[stopbsym] := 'STOPBIT'; vocablist[textfsym] := 'TEXTFILE'; vocablist[timeoutsym] := 'TIMEOUT'; vocablist[wordlensym] := 'WORD-LENGTH'; vocablist[xoffsym] := 'XOFF-CHAR'; vocablist[xoffwaitsym] := 'XOFF-WAIT-COUNT'; vocablist[xonsym] := 'XON-CHAR'; first_sym := allsym; last_sym := xonsym; END. (* end of unit parser *)