home *** CD-ROM | disk | FTP | other *** search
- (* ----------------------------------------------------------------------- *)
- (* SCANNER.PAS *)
- (* PASCAL baut einen Pascal-Compiler, Teil 3 *)
- (* Prozedur zur Bestimmung des naechsten Symbols aus der Eingabe: *)
- PROCEDURE insymbol;
- LABEL 1,2,3;
- VAR
- i, k :INTEGER;
- digit : PACKED ARRAY[1..strglgth] OF CHAR; (* Buffer f. Ziffern *)
- STRING: PACKED ARRAY[1..strglgth] OF CHAR; (* Buffer f. Stringkonstante *)
- lvp : csp;
- test : BOOLEAN;
- wert : long_integer;
- (* ----------------------------------------------------------------------- *)
- (* liest das naechste Zeichen aus der Eingabe und weist es an ch zu: *)
- PROCEDURE nextch;
- BEGIN
- IF eol THEN
- BEGIN
- IF list THEN WriteLn(Output); (* komplettes Compiler-Listing! *)
- endofline;
- linepos := 1; (* Zeiger auf den Zeilenpuffer 'line', der
- immer genau eine Eingabezeile aufnimmt *)
- END;
- IF NOT Eof(Input) THEN
- BEGIN
- eol := Eoln(Input);
- Read(Input,ch);
- enterline(ch); (* fuegt das neu gelesene Zeichen
- in den Zeilenpuffer 'line' ein *)
- IF list THEN Write(Output,ch);
- chcnt := chcnt+1 (* 'charactercounter', Zeichenzaehler *)
- END
- ELSE
- BEGIN
- WriteLn(Output,' *** eof encountered'); test := FALSE
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* erkennt Compileroptionen, die mit (*$<Option>{+,-} eingeleitet werden.
- Optionen sind :
- l : kommentiertes Compiler-Listing
- d : Debug-Option : Wenn diese eingeschaltet ist, wird Code zur Ueber-
- pruefung von Grenzbereichen, Aufzaehlungstypen ,...
- erzeugt.
- c : Compiler-Option. Eingeschaltet erzeugt diese Option interpretier-
- baren P-Code *)
- PROCEDURE options;
- BEGIN
- REPEAT
- nextch;
- IF (ch <> '*') AND (ch <> '}') THEN
- BEGIN
- IF ch = 'l' THEN
- BEGIN
- nextch; list := ch = '+';
- IF NOT list THEN WriteLn(Output)
- END
- ELSE IF ch = 'd' THEN
- BEGIN nextch; debug := ch = '+' END
- ELSE IF ch = 'c' THEN
- BEGIN nextch; prcode := ch = '+' END;
- nextch
- END
- UNTIL ch <> ',';
- END;
- (* ----------------------------------------------------------------------- *)
- BEGIN (* of insymbol *)
- 1:
- REPEAT
- WHILE (ch = ' ') AND NOT eol DO nextch; (* ueberlese Blanks..... *)
- test := eol;
- IF test THEN nextch (* ... und Separatoren. *)
- UNTIL NOT test;
- IF chartp[ch] = illegal THEN
- (* chartp gibt den Typ jedes Zeichens an. Es wird dabei
- nach Buchstaben, Ziffern und Sonderzeichen unterschieden *)
- BEGIN (* illegales Zeichen erkannt. *)
- sy := othersy; op := noop; error(399); nextch
- END
- ELSE
- CASE chartp[ch] OF
- letter: (* Bezeichner einlesen *)
- BEGIN
- k := 0;
- REPEAT
- IF k < 8 THEN (* Aufnahme des Bezeichners in Zwischenpuffer *)
- BEGIN k := k+1; id[k] := ch END;
- nextch
- (* Das Ende eines Bezeichners ist durch einen Separator bestimmt *)
- UNTIL chartp[ch] IN [special,illegal,chstrquo,chcolon,
- chperiod,chlt,chgt,chlparen,chspace];
- (* kk gibt die Laenge des letzten Bezeichners,
- k die Laenge des neuen Bezeichners an *)
- IF k >= kk THEN kk := k
- ELSE
- REPEAT (* Fuelle die unbenutzten Stellen *)
- id[kk] := ' '; kk := kk-1 (* des id-arrays mit Blanks auf *)
- UNTIL kk = k;
- (* Der Bezeichner ist nun in id eingelesen. *)
- FOR i := frw[k] TO frw[k+1]-1 DO
- IF rw[i] = id THEN (* ist id ein reserviertes Wort ?? *)
- BEGIN (* jawoll, dem is' so... *)
- sy := rsy[i]; op := rop[i]; GOTO 2
- END;
- (* Nee, id ist kein reserviertes Wort !.
- id ist ein neudefinierter Bezeichner *)
- sy := ident; op := noop;
- 2:
- END;
- number: (* Zahl einlesen *)
- BEGIN
- op := noop; i := 0;
- REPEAT (* Einlesen der Ziffern in den Ziffernpuffer *)
- i := i+1;
- IF i <= digmax THEN digit[i] := ch;
- nextch
- UNTIL chartp[ch] <> number;
- IF (ch = '.') OR (ch = 'e') THEN
- BEGIN (* Realzahl einlesen *)
- k := i;
- IF ch = '.' THEN
- BEGIN
- k := k+1;
- IF k <= digmax THEN digit[k] := ch;
- nextch;
- IF ch = '.' THEN
- BEGIN ch := ':'; GOTO 3 END;
- IF chartp[ch] <> number THEN error(201)
- ELSE
- REPEAT
- k := k+1;
- IF k <= digmax THEN digit[k] := ch;
- nextch
- UNTIL chartp[ch] <> number
- END;
- IF ch = 'e' THEN
- BEGIN (* Exponent einlesen *)
- k := k+1;
- IF k <= digmax THEN digit[k] := ch;
- nextch;
- IF (ch = '+') OR (ch = '-') THEN
- BEGIN
- k := k+1;
- IF k <= digmax THEN digit[k] := ch;
- nextch
- END;
- IF chartp[ch] <> number THEN error(201)
- ELSE
- REPEAT
- k := k+1;
- IF k <= digmax THEN digit[k] := ch;
- nextch
- UNTIL chartp[ch] <> number
- END;
- (* Zahl ist in Ziffernpuffer eingelesen *)
- New(lvp); sy := realconst; lvp^.cclass := reel;
- WITH lvp^ DO
- BEGIN
- FOR i := 1 TO strglgth DO rval[i] := ' ';
- IF k <= digmax THEN
- FOR i := 2 TO k+1 DO rval[i] := digit[i-1]
- ELSE
- BEGIN
- error(203);
- rval[2] := '0'; rval[3] := '.'; rval[4] := '0'
- END
- END;
- Val.valp := lvp
- END
- ELSE
- 3:
- BEGIN (* Konstante ist vom Typ (long)integer *)
- IF i > digmax THEN
- BEGIN error(203); Val.ival := 0 END
- ELSE
- WITH Val DO
- BEGIN
- wert := 0;
- FOR k := 1 TO i DO wert := wert*10+ordint[digit[k]];
- IF wert <= MaxInt THEN
- BEGIN (* integer-Konstante *)
- sy := intconst; ival := Int(wert);
- END
- ELSE
- BEGIN (* longinteger-Konstante *)
- sy := longconst; New(lvp);
- lvp^.cclass := long; lvp^.lval := wert;
- Val.valp := lvp;
- END;
- END
- END
- END;
- chstrquo: (* Stringkonstante einlesen *)
- BEGIN
- lgth := 0; sy := stringconst; op := noop;
- REPEAT
- REPEAT
- nextch; lgth := lgth+1;
- IF lgth <= strglgth THEN STRING[lgth] := ch
- (* ^^ String in Stringpuffer zwischenspeichern *)
- UNTIL (eol) OR (ch = '''');
- if eol then error(202) else nextch
- until ch <> '''';
- lgth := lgth-1;
- IF lgth = 0 THEN error(205)
- ELSE IF lgth = 1 THEN Val.ival := Ord(STRING[1])
- (* ^^ String ist einzelner Character*)
- ELSE
- BEGIN
- New(lvp); lvp^.cclass := strg;
- IF lgth > strglgth THEN
- BEGIN
- error(399); lgth := strglgth; (* String zu lang, Rest *)
- END; (* wird einfach abgeschnitten *)
- WITH lvp^ DO
- BEGIN
- slgth := lgth;
- FOR i := 1 TO lgth DO sval[i] := STRING[i]
- END;
- Val.valp := lvp;
- END
- END;
- chcolon: (* SONDERZEICHEN *)
- BEGIN
- op := noop; nextch;
- IF ch = '=' THEN
- BEGIN sy := becomes; nextch END
- ELSE sy := colon
- END;
- chperiod:
- BEGIN
- op := noop; nextch;
- IF ch = '.' THEN
- BEGIN sy := colon; nextch END
- ELSE sy := period
- END;
- chlt:
- BEGIN
- nextch; sy := relop;
- IF ch = '=' THEN
- BEGIN op := leop; nextch END
- ELSE IF ch = '>' THEN
- BEGIN op := neop; nextch END
- ELSE op := ltop
- END;
- chgt:
- BEGIN
- nextch; sy := relop;
- IF ch = '=' THEN
- BEGIN op := geop; nextch END
- ELSE op := gtop
- END;
- chlparen: (* Kommentare *)
- BEGIN
- nextch;
- IF ch = '*' THEN
- BEGIN
- nextch;
- IF ch = '$' THEN options;
- REPEAT
- WHILE (ch <> '*') AND NOT Eof(Input) DO nextch;
- nextch
- UNTIL (ch = ')') OR Eof(Input);
- nextch; GOTO 1
- END;
- sy := lparent; op := noop
- END;
- special:
- BEGIN
- sy := ssy[ch]; op := sop[ch]; nextch
- END;
- chspace:
- sy := othersy;
- lbrace: (* Kommentare mit { *)
- BEGIN
- nextch;
- IF ch = '$' THEN options;
- WHILE (ch <> '}') AND NOT Eof(Input) DO nextch;
- nextch; GOTO 1
- END;
- END; (* of CASE *)
- END;
- (* ----------------------------------------------------------------------- *)
- (* Ende SCANNER.PAS *)
-