unit strtype; interface type strec = object function isblank (c: char): Boolean; function isdigit (c: char): Boolean; function isletter (c: char): Boolean; function isname (c: char): Boolean; function hasat (i: integer; s1: string): Boolean; function posof (s1: string): integer; procedure replace (j, k: integer; s1: string); function hasprefix (s1: string): Boolean; function empty: Boolean; function str: string; procedure ini (s1: string); (* token functions: *) procedure resetposition; function nexttoken: string; function lasttoken: string; function firsttoken: string; function nthtoken (n: integer): string; function lookuptoken (s1: string): Boolean; function findtoken (s1: string): Boolean; procedure gotonexttoken; procedure replacelasttoken (s1: string); private s: string; len: integer; position: integer (* current scan position *); startpos: integer (* start of last retrieved token *); function cc: char; end; implementation function strec.isblank (c: char): Boolean; begin isblank := (c = ' ') or (c = ' ') end; function strec.isdigit (c: char): Boolean; begin isdigit := (c >= '0') and (c <= '9') end; function strec.isletter (c: char): Boolean; begin isletter := ((c >= 'A') and (c <= 'Z')) or ((c >= 'a') and (c <= 'z')) end; function strec.isname (c: char): Boolean; begin (* isname := not isblank (c) and (c <> '(') and (c <> ')') and (c <> '<') and (c <> '>') and (c <> '[') and (c <> ']') and (c <> '{') and (c <> '}') and (c <> '/') and (c <> '%') *) isname := not (c in [' ', ' ', '(', ')', '<', '>', '[', ']', '{', '}', '/', '%']) end; function strec.cc: char; begin if position > len then cc := ' ' else cc := s [position] end; function strec.hasat (i: integer; s1: string): Boolean; begin hasat := pos (s1, s) = i end; function strec.posof (s1: string): integer; begin posof := pos (s1, s) end; procedure strec.replace (j, k: integer; s1: string); begin delete (s, j, k - j + 1); insert (s1, s, j) end; function strec.hasprefix (s1: string): Boolean; begin hasprefix := pos (s1, s) = 1 end; function strec.empty: Boolean; begin empty := s = '' end; function strec.str: string; begin str := s end; procedure strec.ini (s1: string); begin s := s1; position := 0; len := length (s) end; procedure strec.resetposition; begin position := 0 end; function strec.nexttoken: string; const specialchars = [' ', ' ', '(', ')', '<', '>', '[', ']', '{', '}', '/', '%']; var level: integer; quote: Boolean; nexttok: string; begin if position = 0 then position := position + 1; while (position <= len) and isblank (s [position]) do position := position + 1; startpos := position; if startpos > len then nexttok := '' else begin if (cc = '/') or not (cc in specialchars) then begin (* scan name or number *) if cc = '/' then begin position := position + 1; (* ignore the special cases /[ and /] *) if cc = '/' then position := position + 1; end; while not (cc in specialchars) do position := position + 1 end else if cc = '=' then begin (* scan special symbol *) position := position + 1; if cc = '=' then position := position + 1 end else if cc = '<' then begin (* scan hex string *) while (position <= len) and (cc <> '>') do position := position + 1; if position <= len then position := position + 1 end else if cc = '(' then begin (* scan string *) position := position + 1; level := 1; quote := false; while (position <= len) and (level > 0) do begin if not quote then if cc = '\' then quote := true else begin quote := false; if cc = '(' then level := level + 1 else if cc = ')' then level := level - 1 end; position := position + 1 end end else if cc = '%' then (* scan comment *) position := len + 1 else (* scan one-character symbol *) position := position + 1; nexttok := copy (s, startpos, position - startpos) end; (* writeln ('nexttoken: ¯', nexttok, '®'); *) nexttoken := nexttok end; function strec.lasttoken: string; begin if startpos > len then lasttoken := '' else lasttoken := copy (s, startpos, position - startpos) end; function strec.firsttoken: string; begin position := 0; firsttoken := nexttoken end; function strec.nthtoken (n: integer): string; var i: integer; r: string; begin position := 0; for i := 1 to n do r := nexttoken; nthtoken := r end; function strec.lookuptoken (s1: string): Boolean; var t: string; r: Boolean; begin r := false; t := nexttoken; while t <> '' do if t = s1 then begin r := true; t := '' end else t := nexttoken; lookuptoken := r end; function strec.findtoken (s1: string): Boolean; begin position := 0; findtoken := lookuptoken (s1) end; procedure strec.gotonexttoken; var t: string; begin t := nexttoken end; procedure strec.replacelasttoken (s1: string); begin replace (startpos, position - 1, s1) end; end.