ORIGIN 'betaenv'; BODY 'private/wtextbody' (* * COPYRIGHT * Copyright (C) Mjolner Informatics, 1997-98 * All rights reserved. * * This fragment implements a UniCode stream and text concept *) ---lib:attributes--- wStream: (# <<SLOT wStreamLib: attributes>>; length:< integerValue (* returns the length of THIS(wStream) *) (# do -1->value; INNER length #); position: (* current position of THIS(wStream) *) (# enter setPos exit getPos #); eos:< (* returns 'true' if THIS(wStream) is at end-of-wStream *) booleanValue; reset: (* sets 'position' to zero *) (# do 0->setPos exit THIS(wStream)[] #); peek:< (* looks at the next character of THIS(wStream) *) (# ch: @wchar do INNER peek exit ch #); get:< (* reads a character from THIS(wStream) *) (# ch: @wchar do INNER get exit ch #); getNonBlank: (* Reads first non-whitespace character from THIS(wStream). * If called at end-of-wStream the character 'ascii.fs' is * returned *) (# ch: @wchar; skipblanks: @scanWhiteSpace; testEOS: @EOS; getCh: @get; ... exit ch #); getint: integerValue (* Reads an integer: skips whitespace characters and * returns the following digits. * * See numberio.bet for more numerical output operations *) (# syntaxError:< wStreamException (# do 'getint: syntax error - looking at: "'->msg.append; peek->msg.put; '"'->msg.putline; INNER syntaxError #); geti: @... do geti; INNER getint #); getAtom:< (* Returns the next atom (i.e. sequence of non-white * characters - skipping leading blanks) *) (# txt: ^wtext; do &wText[]->txt[]; INNER getAtom; exit txt[] #); getline:< (* Reads a sequence of characters until nl-character * appears and returns the characters read. *) (# txt: ^wText; do &wText[]->txt[]; INNER getline exit txt[] #); asInt: (* converts THIS(wText) to an integer value, ignoring * leading and trailing whitespace. See numberio.bet for * more numerical conversion operations. *) (# i: @integer; syntaxError:< wStreamException (# peekCh: @wchar enter peekCh do 'asInt: syntax error - looking at: "'->msg.append; peekCh->msg.put; '"'->msg.put; INNER syntaxError #) ... exit i #); put:< (* writes a character to THIS(wStream) *) (# ch: @wchar enter ch do INNER put exit THIS(wStream)[] #); newline: (* writes the nl-character *) (# do ascii.newline->put exit THIS(wStream)[] #); putint: (* Writes an integer to THIS(wStream); The format may be * controlled by the 'signed', 'blankSign', 'width', * 'adjustLeft' and 'zeroPadding' variable attributes. * 'width' is extended if it is too small. Examples: * '10->putint' yields: '10'; '10*pi->putint(# do 10->width; * true->adjustLeft #)' yields: '10 '; and '10->putint(# do * 10->width; true->zeroPadding #)' yields: '0000000010'. * * See numberio.bet for more numerical output operations *) (# n: @integer; signed: @boolean (* If integer is positive, a '+' will always be * displayed *); blankSign: @boolean (* If integer is positive, a ' ' space is displayed as * the sign. Ignored if 'signed=true' *); width: @integer (* Minimum width *); adjustLeft: @boolean (* Specifies if the number is to be aligned left or * right, if padding of spaces is necessary to fill up * the specified width. *); zeroPadding: @boolean (* width is padded with leading zero instead of * spaces. Ignored if 'adjustLeft=true' *); format:< (# do INNER format #); puti: @... enter n do 1->width; format; INNER putint; puti exit THIS(wStream)[] #); putText:< (* Writes a wText to THIS(wStream). *) (# txt: ^wText enter txt[] do (if txt[]<>NONE then INNER puttext if) exit THIS(wStream)[] #); putline: (* 'puttext' followed by 'newline' *) (# T: ^wText; putT: @puttext; newL: @newline enter T[] do INNER putline; T[]->putT; newL exit THIS(wStream)[] #); scan: (* Scan chars from current position in THIS(wStream) while * '(ch->while)=true'; perform INNER for each char being * scanned *) (# while:< (# ch: @wchar; value: @boolean enter ch do true->value; INNER while exit value #); ch: @wchar; whilecondition: @while; testEOS: @EOS; getPeek: @peek; getCh: @get; ... exit THIS(wStream)[] #); scanWhiteSpace: scan (* Scan whitespace characters *) (# while::< (# do ch->ascii.isWhiteSpace->value #) do INNER scanWhiteSpace exit THIS(wStream)[] #); scanAtom: (* Scan until first non-whitespace char. Scan the next * sequence of non-whitespace chars. Stop at first * whitespace char. For each non-whitespace char an INNER * is performed. Usage: 'scanAtom(# do ch-><destination> #)' *) (# ch: @wchar; ... exit THIS(wStream)[] #); scanToNl: (* Scan all chars in current line including newline char *) (# ch: @wchar; getCh: @get; ... exit THIS(wStream)[] #); wStreamException: exception (# do INNER wStreamException #); EOSerror:< wStreamException (* Raised from 'get' and 'peek' when attempted to read past * the end of the wStream. *) (# do 'Attempt to read past end-of-wStream'->msg.putline; INNER EOSerror #); otherError:< wStreamException (* Raised when some other kind of wStream error apart from * the one mentioned above occurs. *); getPos:< (* returns current position of THIS(wStream) *) integerValue; setPos:< (* sets current position in THIS(wStream) to 'p' *) (# p: @integer enter p do INNER setPos exit THIS(wStream)[] #) #); (* pattern wStream *) (***** wText pattern **********************************************) wText: wStream (* A wText is a sequence of characters. Let 'T: @wText'. The * range of 'T' is '[1,T.length]'. A wText can be initialized by * executing 'T.clear' or by assigning it another (initialized) * wText. A wText-constant has the form 'foo'. The 'wText' pattern * is primarily intended for small wTexts but there is no upper * limit in the size. However, most of the operations becomes * less efficient with larger wTexts. *) (# <<SLOT wTextLib: attributes>>; length::< (* Returns the length of THIS(wText) *) (# do lgth->value; INNER length #); eos::< (# ... #); empty: (# exit (lgth = 0) #); clear: (* Sets the length and position of THIS(wText) to zero *) (# do 0->pos->lgth exit THIS(wText)[] #); equal: booleanValue (* Tests if THIS(wText) is equal to the entered wText. If * 'NCS' is further bound to 'trueObject', the comparison * will be done Non Case Sensitive. *) (# txt: ^wText; NCS:< booleanObject enter txt[] ... #); equalNCS: equal (* As 'equal', except the the comparison will be done Non * Case Sensitive *) (# NCS:: trueObject #); less: booleanValue (* Tests whether the entered wText 'T1[1: length]' is less * than 'THIS(wText)[1: T1.length]'. The lexicographical * ordering is used. *) (# T1: ^wText enter T1[] ... #); greater: booleanValue (* Tests whether the entered wText 'T1[1: length]' is * greater than 'THIS(wText)[1: T1.length]'. The * lexicographical ordering is used. *) (# T1: ^wText enter T1[] ... #); peek::< (* Returns the character at current position; does not * update 'position' *) (# ... #); get::< (* Returns the character at current position; increments * 'position' *) (# ... #); inxGet: wcharValue (* Returns the character at position 'i' *) (# i: @integer; iget: @... enter i do iget #); getAtom::< (* Returns the next atom (i.e. sequence of non-white * characters - skipping leading blanks) *) (# ... #); getline::< (* Reads a sequence of characters until nl-character * appears and returns the characters read. *) (# ... #); put::< (* writes the character 'ch' at current position in * THIS(wText); increments 'position' *) (# ... #); inxPut: (* Replaces the character at position 'i' *) (# ch: @wchar; i: @integer; iput: @... enter (ch,i) do iput exit THIS(wText)[] #); puttext::< (# ... #); append: (* Appends a wText to THIS(wText); does not change 'position' *) (# T1: ^wText enter T1[] ... exit THIS(wText)[] #); prepend: (* Inserts the wText in 'T1' in front of THIS(wText); updates * current position to 'position+T1.length' if 'position>0' *) (# T1: ^wText enter T1[] ... exit THIS(wText)[] #); insert: (* Inserts a wText before the character at position 'inx'. * Note: inx<1 means inx=1; inx>length means inx=length+1. * If 'position>=inx' then 'position+T1.length->position'. *) (# T1: ^wText; inx: @integer enter (T1[],inx) ... exit THIS(wText)[] #); delete: (* Deletes THIS(wText)[i: j]; updates current position: * i<=position<j => i-1->position * j<=position => position-(j-i+1)->position *) (# i,j: @integer; deleteT: @... enter (i,j) do deleteT exit THIS(wText)[] #); makeLC: (* Converts all characters to lower case *) (# ... exit THIS(wText)[] #); makeUC: (* Converts all characters to upper case *) (# ... exit THIS(wText)[] #); sub: (* Returns a copy of THIS(wText)[i:j]. If 'i<1', 'i' is * adjusted to 1. If 'j>length', 'j' is adjusted to * 'length'. If (after adjustment) 'i>j', an empty wText is * returned. *) (# i,j: @integer; T1: ^wText; subI: @... enter (i,j) do subI exit T1[] #); copy: (# T1: ^wText; copyI: @... do copyI exit T1[] #); scanAll: (* Scans all the elements in THIS(wText). For 'ch' in '[1: * THIS(wText).length]' do INNER *) (# ch: @wchar do (for i: lgth repeat T[i]->ch; INNER scanAll for) exit THIS(wText)[] #); find: (* find all occurrences of the character 'ch' in * THIS(wText), executing INNER for each occurrence found, * beginning at 'THIS(wText).position'. 'inx' will contain * the position of each 'ch' in THIS(wText). If 'NCS' is * further bound to 'trueObject', the comparison will be * done Non Case Sensitive. If 'from' is further bound, the * search will begin at position 'from'. *) (# ch: @wchar; inx: @integer; NCS:< booleanObject; from:< integerObject(# do pos->value; INNER from #) enter ch ... exit THIS(wText)[] #); findAll: find (* As 'find', except that the entire wText will be searched. * Replaces 'findCh' in previous versions of betaenv (v1.4 * and earlier) *) (# from:: (# do 0->value #) do INNER findAll #); findwText: (* find all occurrences of the 'txt' in THIS(wText), * executing INNER for each occurrence found, beginning at * 'THIS(wText).position'. 'inx' will contain the position * of the first character of each occurrence found * THIS(wText). If 'NCS' is further bound to 'trueObject', * the comparison will be done Non Case Sensitive. If * 'from' is further bound, the search will begin at * position 'from'. *) (# txt: ^wText; inx: @integer; NCS:< booleanObject; from:< integerObject(# do pos->value; INNER from #) enter txt[] ... exit THIS(wText)[] #); findwTextAll: findwText (* As 'findwText', except that the entire wText will be * searched *) (# from:: (# do 0->value #) do INNER findwTextAll #); extend: (* Extend THIS(wText) with 'L' (undefined) chars. Notice * that it is only the representation of the THIS(wText), * that is extended, the 'length' and 'position' are not * changed. *) (# L: @integer enter L do L->T.extend exit THIS(wText)[] #); indexError:< wStreamException (* Raised from 'Check' when the index goes outside the * range of the wText. Message: "Index error in wText!". *) (# inx: @integer enter inx ... #); EOSerror::< (* Raised from 'get' and 'peek' when the end of the wStream is * passed. *) (# ... #); otherError::< (* Raised when an error other than the Index-/EOSerror * occurs. *) (# ... #); setPos::< (# ... #); getPos::< (# do pos->value; INNER getPos #); (* Private attributes: !!OBS!! The 3 attributes 'T', 'lgth' * and 'pos' declared below MUST be the first data items * declared in 'wStream' and 'wText' since their addresses are * hardcoded into the compiler. *) T: [16] @wchar; lgth,pos: (* 16 is default size *) @integer; setT: (# enter T do T.range->lgth->pos #); setAscii: (# t: ^ text enter T[] do T.scanAll(#do ch -> put #) #); asAscii: (# T: @text do scanAll(#do ch -> T.put #) exit T[] #) enter setT exit T[1: lgth] #) (* Pattern wText *); ascii2wText: (# T1: ^text; T2: @wText enter T1[] do T1.scanAll(#do ch -> T2.put #); exit T2[] #); ---textLib:attributes--- aswText: (# UT: @wText do scanAll(#do ch -> UT.put #) exit UT[] #)
13.22 Wtext Interface | © 1990-2002 Mjølner Informatics |
[Modified: Tuesday February 24th 1998 at 11:05]
|