$include "defs.icn" $include "global_vars.icn" #################################################################### ##################################################################### #* # * Russell scanner # */ #DJDSTOP # # # # ##include "../parser/y.tab.h" # # # # #define STKSIZE 5 /* depth of scanner error recovery stack */ # # # # # # /* # # * code for nil pointer # # */ # # #define NIL 0 # # # # # # extern boolean pflag; /* input is preprocessor output */ # # #define ESCCHAR '#' /* signals position in preprocessor output */ # # # # # # /* entry in reserved identifier table */ # # struct restab { # # char * rt_txt; # # int rt_val; }; # # # # /* # # * reserved word tables # # */ # # # # struct restab residtab[]; # # int nresids; # # # # struct restab resoptab[]; # # int nresops; # # # # /* # # * table of character classes # # * and macro to find character class # # */ # # # # int cctab[]; # # # # # define CCLASS(c) ((c) == EOF ? EOFCC : cctab[c]) # # # # # # /* # # * global variables for communicating with yacc; # # */ # # # # int yyline = 0; # # int yycolno = 0; # # char * yyinfnm; # # # # int yydebug; # # # # int yylval; # # # # /* declarations for table of virtual line numbers versus real line # # * numbers and filenames. The table is created by the scanner and # # * then used by later passes to convert a virtual line number # # * stored in the syntax tree to the real line number printed in # # * an error message. # # */ # # typedef struct VrLine{ # # int vr_vline, /* virtual line number at which file */ # # /* change or line number jump occurred */ # # vr_rline, /* corresponding real line number */ # # vr_fname; /* string table index of filename */ # # struct VrLine * vr_next; /* pointer to next record */ } vrline; # # # # vrline * vrtable = NIL, /* pointers to first and last table entries */ # # * vrtend = NIL; # # # # int yyvline = 0; /* curent virtual line number */ # # # # static int scansavc = '\n'; /* n.b. preprocessor line number scan */ # # /* routine only checks for '@' after '\n' */ # # # # static int scanstk[STKSIZE]; # # static int stktop = -1; # # # # char tokenbuf[1000]; /* also used by some other routines as string buffer */ # # /* static */ int tokenlgth; # # # # # # /* # # * get next token -- # # * put it in tokenbuf. # # * return token code. # # */ # #DJDSTART procedure yylex() local c, cc, p, outtok, retry_loop, saw_quote, startline, startfnm , cmtnest , yycat, yydescr, do_retry if (stktop >= 0) then { outtok := scanstk[stktop] stktop -:= 1 token_cnt +:= 1 rpt_progress(p,yycat,outtok,yydescr) return ( outtok ) } retry_loop := TRUE while retry_loop = TRUE do { # retry: c := scansavc cc := cclass(c) yylval := 0 p := "" # Will concat to while( cc = WHTCC ) do { if( c == "\n" ) then { yyline +:= 1 yyvline +:= 1 c := getchr() if( c == ESCCHAR & pflag) then { rdposition() c = "\n" # Repeat check for ESCCHAR next time around yyline -:= 1 yyvline -:= 1 # Line number is correct for next line } } else { c := getchr() } cc := cclass(c) } case (cc) of { LETCC: { p ||:= c c := getchr() cc := cclass(c) while ( (cc == LETCC) | (cc == DIGCC) ) do { p ||:= c c := getchr() cc := cclass(c) } tokenlgth := *p outtok := reschk_id(p,WORDID) scansavc := c token_cnt +:= 1 yycat := "ID" if outtok ~= WORDID then yydescr := "RESERVED ID" else yydescr := "DEFINED ID" rpt_progress(p,yycat,outtok,yydescr) return outtok } SQUCC: # single quote { p ||:= c c := getchr() cc := cclass(c) saw_quote := FALSE repeat { if ( cc == EOFCC | c == "\n" ) then { yyperror("Unterminated quoted identifier") break } if (c == "\\") then { c := getchr() case (c) of { "t": p ||:= "\t" "n": p ||:= "\n" "r": p ||:= "\r" default: p ||:= c } } else { p ||:= c } c := getchr() cc := cclass(c) if (saw_quote == TRUE) then { if (cc == SQUCC) then { # ignore this character and keep scanning c := getchr() cc := cclass(c) } else { # end of identifier break } } if (cc == SQUCC) then saw_quote := TRUE else saw_quote := FALSE } outtok := WORDID yylval := stt_enter(p,*p) ################################# scansavc := c token_cnt +:= 1 yycat := "Sing Quote" yydescr := "Sing Quote" sing_quoted_cnt +:= 1 rpt_progress(p,yycat,outtok,yydescr) return outtok ################################### } DQUCC: # double quote { # p ||:= c # c := getchr() # cc := cclass(c) saw_quote := FALSE repeat { if (cc == EOFCC | c == "\n") then { yyperror("Unterminated string") break } if (c == "\\") then { c := getchr() case (c) of { "t": p ||:= "\t" "n": p ||:= "\n" "r": p ||:= "\r" default: p ||:= c } } else { p ||:= c } c := getchr() cc := cclass(c) if (saw_quote == TRUE) then { if (cc == DQUCC) then { # ignore this character and keep scanning # Note that the previous double quote was saved c := getchr() cc = cclass(c) } else { # end of string break } } if (cc == DQUCC) then saw_quote := TRUE else saw_quote := FALSE } # Delete trailing quote. outtok := QSTRING # allocate a buffer for the string and return it yylval := p[2:-1] ################################# scansavc := c token_cnt +:= 1 yycat := "Dbl Quote" yydescr := "Dbl Quote" dbl_quoted_cnt +:= 1 rpt_progress(p,yycat,outtok,yydescr) return outtok ################################### } SEPCC: { do_retry := FALSE p := scansavc := c c := getchr() if( (scansavc == "(") & (c == "*") ) then { comments_cnt +:= 1 # process a comment startline := yyline # temporary line counter used in comments # so error message has a useful line number # if EOF occurs inside a comment startfnm := yyinfnm cmtnest := 0 $include "pass1/scanner/scan_sep_inc.icn" while( cmtnest > 0 ) do $include "pass1/scanner/scan_sep_inc.icn" if do_retry = TRUE then { next } # put2w( S_YYLINE, yyline ) scansavc := c next # outtok := p ||:= c } # if comment outtok := ord(p) # not sure -- was outtok = p++ yyinfo("SEP p = " || p || " c = " || c || " outtok = " || outtok ) yycat := "SEP" yydescr := p scansavc := c token_cnt +:= 1 seperator_cnt +:= 1 rpt_progress(p,yycat,outtok,yydescr) return ( outtok ) } DIGCC: { p ||:= c c := getchr() cc := cclass(c) while( cc == DIGCC | cc == LETCC ) do { p ||:= c c := getchr() cc := cclass(c) } outtok := UQSTRING # unquoted string #allocate buffer and return it, as for quoted strings yylval := p yycat := "NUM" yydescr := p scansavc := c token_cnt +:= 1 numeral_cnt +:= 1 rpt_progress(p,yycat,outtok,yydescr) return ( outtok ) } OPRCC: { p ||:= c c := getchr() cc := cclass(c) while ( cc == OPRCC ) do { p ||:= c c := getchr() cc := cclass(c) } tokenlgth := *p outtok := reschk_op(p,OPID) scansavc := c token_cnt +:= 1 yycat := "OPR" if outtok ~= OPID then yydescr := "RESERVED OPR" else yydescr := "DEFINED OPR" rpt_progress(p,yycat,outtok,yydescr) return outtok } EOFCC: { scansavc := "\n" # Set things up for core image to be subsequently # restarted rpt_progress(p,"EOF",EOF,"EOF") return(EOF) } BADCC: { c := getchr() scansavc := c next } } scansavc := c } token_cnt +:= 1 rpt_progress(p,yycat,outtok,yydescr) return ( outtok ) end #* # * read current position ( line no, file name ) # * up to and including newline character # * This routine clobbers tokenbuf & tokenlgth this shouldn't matter. # */ procedure rdposition() #DJDSTOP # # local c, n = 0, p # # initial n := 0 # # while ( (c := getchr()) == " " ) # # yyline := # # if /(c ? any(&digits)) then break # # n := n * 10 + (c - "0") # # c := getchr() # # } # # yyline = n # # # # repeat { # # if( c == EOF ) goto bad # # if( c != " " ) break; # # c := getchr(); # # } # # if( c != """ ) goto bad; # # c:= getchr(); # # # # p := "" # # for(;;) { # # if( c == EOF ) goto bad; # # if( c == """) break; # # p ||:= c # # c := getchr(); # # } # # tokenlgth = p - tokenbuf; # # yyinfnm = (char *)stt_enter( tokenbuf, tokenlgth ); # # addposition(yyinfnm, yyline); # # # # goto out; # # # # bad: # # # There was a syntax error in the line number specification. # # # This is either a preprocessor error or a bizarre input pgm # # yyperror("Error in line number"); # # out: # # # Scan to the end of the line discarding any junk. # # while ( (c != "\n") & (c != EOF) ) { # # c:= getchr(); # # } # #DJDSTART end #DJDSTOP # # # add new record to vrtable, associating fn and ln with the current # # # value of yyvline # # procedure addposition(fn,ln) # # unsigned fn; # stt pointer # # int ln; # # { register vrline * p; # # # # p = (vrline *) gc_malloc(sizeof(vrline)); # # if (vrtable == NIL) # # vrtable = p; # # else # # (vrtend -> vr_next) = p; # # vrtend = p; # # (p -> vr_vline) = yyvline; # # (p -> vr_rline) = ln; # # (p -> vr_fname) = fn; # # (p -> vr_next ) = NIL; # # } # # # # /* # # * look up contents of token buf in a reserved-word table # # * of nentries entries. # # * # # * return value if it is reserved, # # * otherwise return default value, # # * add token buf to string table, # # * and set yylval to the string table pointer. # # */ # # reschk( tbl, nentries, dflt ) # # register struct restab *tbl; # # { # # register int m; # # register int l, r; # # register char * this_entry; # # # # l = 0; r = nentries-1; # # while ( l < r ) { # # m = (l + r) / 2; # # this_entry = tbl[m].rt_txt; # # if( *this_entry < *tokenbuf | # # (*this_entry == *tokenbuf & strcmp(this_entry, tokenbuf) < 0) ) # # l = m + 1; # # else # # r = m; # # } # # # # if( strcmp(tbl[l].rt_txt,tokenbuf) == 0 ) # # return( tbl[l].rt_val ); # # else { # # yylval = stt_enter( tokenbuf, tokenlgth ); # # return( dflt ); # # } # # # # end # # /* # # * push a token back onto the input # # */ # #DJDSTART procedure yyunlex( tok ) stktop +:= 1 scanstk[stktop] = tok end #*************************************************************************** #*# define cclass(c) ((c) == EOF ? EOFCC : cctab[c]) procedure cclass(c) local it yyinfo("cclass1 c = " || c) if (c =="\n" | c == "\t") then { yyinfo("cclass WHTCC") write(ccode_file, "c = " || c || " class = " || WHTCC) return WHTCC } if (c == EOF) then { yyinfo("cclass EOFCC") write(ccode_file, "c = " || c || " class = " || EOFCC) return EOFCC } it := cctab[c] write(ccode_file, "c = " || c || " class = " || it) yyinfo("cclass c = " || c || "cctab[c] = " || it) return it end #***************************************************************************** # Fast version of c = getchr() */ # charfix() # #define getchr(c) (yycolno++, ((c = getchar()) < 32? charfix(c) : c)) # c = getchr() procedure getchr() local ch, gotit gotit := TRUE yyinfo("getchr linebuf = " || linebuf) while (*linebuf = 0) do { if \linebuf := read(infile) then { linebuf := " " || linebuf # sub for missing end of line line_cnt +:= 1 gotit := TRUE } else { gotit := FALSE return EOF } } if (gotit = TRUE) then { yyinfo("in while *linebuf = " || *linebuf) yyinfo(" after read linebuf = " || linebuf) ch := linebuf[1:2] yyinfo("ch = " || ch) char_cnt +:= 1 linebuf := linebuf[2:0] yyinfo("scan getchr read linebuf = " || linebuf || "ch = " || ch) return ch } ch := linebuf[1:2] char_cnt +:= 1 linebuf := linebuf[2:0] yyinfo("scan getchr from linebuf = " || linebuf || "ch = " || ch) return ch end #***************************************************************************** #* reschk_id(p, dflt ) procedure reschk_id(p,dflt) local it yyinfo("reschk_id p = " || p) if ((it := restab[p]) > 0) then { reserved_id_cnt +:= 1 return it } else { defined_id_cnt +:= 1 yylval := stt_enter(p,*p) yydescr := yylval return dflt } end procedure reschk_op(p,dflt) local it yyinfo("reschk_op p = " || p) if ((it := restab[p]) > 0) then { reserved_op_cnt +:= 1 return it } else { defined_op_cnt +:= 1 yylval := stt_enter(p,*p) yydescr := yylval return dflt } end #DJDSTOP # # *************************************************************************** # # *# define cclass(c) ((c) == EOF ? EOFCC : cctab[c]) # # cclass debug = "cclass1 c = " c # # DIFFER(c,"\n") :s(cclass_skip1a) # # cclass = WHTCC :(RETURN) # # cclass_skip1a DIFFER(c,"\t") :s(cclass_skip1b) # # cclass = WHTCC :(RETURN) # # cclass_skip1b DIFFER(c,EOF) :s(cclass_skip2) # # cclass = EOFCC :(RETURN) # # cclass_skip2 debug = "cclass2 c = " c # # cclass = cctab[c] :(RETURN) # # ***************************************************************************** # # * Fast version of c = getchr() */ # # # # * charfix() # # * #define getchr(c) (yycolno++, ((c = getchar()) < 32? charfix(c) : c)) # # * c = getchr() # # getchr debug = "getchr2 linebuf = " linebuf # # EQ(SIZE(linebuf),0) :f(getchr_sk2) # # * indicate new line (really 2 chars - snobol doesn't return new line # # linebuf = infile :f(getchr_sk) # # line_cnt = line_cnt + 1 # # debug = linebuf # # getchr = "\n" :(RETURN) # # getchr_sk2 linebuf LEN(1) . getchr = # # char_cnt = char_cnt + 1 # # DIFFER(getchr,tab_chr) :s(getchr_sk3) # # * handle tab character # # getchr = "\t" # # getchr_sk3 :(RETURN) # # getchr_sk getchr = EOF :(RETURN) # # ***************************************************************************** # # * reschk_id(p, dflt ) # # reschk_id debug = "reschk_id p = " p # # debug = "restab[p] = " restab[p] # # DIFFER(restab[p]) :f(reschk_id_empty) # # reserved_id_cnt = reserved_id_cnt + 1 # # reschk_id = restab[p] :(RETURN) # # reschk_id_empty yylval = stt_enter(p,SIZE(p)) # # yydescr = yylval # # reschk_id = dflt :(RETURN) # # ************************************************************************** # # * reschk_op(p, dflt ) # # reschk_op debug = "reschk_op p = " p # # debug = "restab[p] = " restab[p] # # DIFFER(restab[p]) :f(reschk_op_empty) # # reserved_op_cnt = reserved_op_cnt + 1 # # # # reschk_op = restab[p] :(RETURN) # # reschk_op_empty yylval = stt_enter(p,SIZE(p)) # # yydescr = yylval # # reschk_op = dflt :(RETURN) # # # # **************************************************************************** # #DJDSTART procedure rpt_progress(p,yycat,outtok,yydescr) local sz,it,sz1,sz2,sz3,it5,prog_part1 initial { sz := 26 - *"token" if (sz < 2) then sz := 2 sz1 := 18 - *"yydescr" if (sz1 < 2) then sz1 := 2 sz2 := 18 - *"yycat" if (sz2 < 2) then sz2 := 2 sz3 := 8 - *"outtok" if (sz3 < 2) then sz3 := 2 prog_part1 := "token" || repl(" ",sz) || "yydescr" || repl(" ",sz1) || "yycat" || repl(" ",sz2) || "outtok" || repl(" ",sz3) || "yylval" write(progress,prog_part1) } sz := 26 - *p if (sz < 2) then sz := 2 it := string(yydescr) sz1 := 18 - *it if (sz1 < 2) then sz1 := 2 sz2 := 18 - *yycat if (sz2 < 2) then sz2 := 2 sz3 := 8 - *outtok if (sz3 < 2) then sz3 := 2 it5 := string(yylval) prog_part1 := p || repl(" ",sz) || yydescr || repl(" ",sz1) || yycat || repl(" ",sz2) || outtok || repl(" ",sz3) || it5 write(progress,prog_part1) end