1 (* Scan.mod Provides a primitive symbol fetching from input.
3 Copyright (C) 2001-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. *)
27 IMPLEMENTATION MODULE Scan
;
32 FROM ASCII
IMPORT nul
, lf
, cr
, bs
, del
, bel
;
33 FROM StdIO
IMPORT Write
;
34 FROM StrLib
IMPORT StrEqual
, StrLen
, StrCopy
;
35 FROM NumberIO
IMPORT WriteCard
, CardToStr
;
36 FROM FIO
IMPORT OpenToRead
, IsNoError
, Close
, File
, ReadChar
;
37 FROM StrIO
IMPORT WriteLn
, WriteString
;
38 FROM libc
IMPORT exit
;
42 MaxLength
= 255 ; (* Max Length of Source Line *)
46 CurrentString
: ARRAY [0..MaxLength
] OF CHAR ;
47 CurrentLineNo
: CARDINAL ;
48 CurrentCursorPos
: CARDINAL ;
50 LengthOfCurSym
: CARDINAL ;
53 HaltOnError
: BOOLEAN ;
54 AllowComments
: BOOLEAN ;
56 CommentTrailer
: ARRAY [0..MaxLength
] OF CHAR ;
57 TerminateOnEndOfLine
: BOOLEAN ;
61 PROCEDURE OpenSource (a
: ARRAY OF CHAR) : BOOLEAN ;
63 StrCopy(a
, FileName
) ;
67 StrCopy( '', CurrentString
) ;
69 CurrentCursorPos
:= 0 ;
80 PROCEDURE CloseSource
;
91 IsStartOfComment - returns TRUE if we are looking at the start of a comment.
94 PROCEDURE IsStartOfComment () : BOOLEAN ;
101 h
:= StrLen(CommentLeader
) ;
102 WHILE (i
<h
) AND (CommentLeader
[i
]=CurrentString
[CurrentCursorPos
+i
]) DO
109 END IsStartOfComment
;
113 IsEndOfComment - returns TRUE if we can see the end of comment string.
114 If TRUE is returned then we also have consumed the string.
117 PROCEDURE IsEndOfComment () : BOOLEAN ;
123 IF TerminateOnEndOfLine
AND (SymbolChar()=nul
)
129 h
:= StrLen(CommentTrailer
) ;
130 WHILE (i
<h
) AND (CommentTrailer
[i
]=CurrentString
[CurrentCursorPos
+i
]) DO
135 (* seen tailer therefore eat it *)
136 INC(CurrentCursorPos
, i
) ;
149 IsQuote - returns TRUE if the current character is a quote.
152 PROCEDURE IsQuote () : BOOLEAN ;
154 RETURN( SymbolChar()='"' )
159 GetNextSymbol - returns the next symbol from the source file.
160 It ignores comments and treats strings differently
161 from normal symbols. Strings will return " string ".
164 PROCEDURE GetNextSymbol (VAR a
: ARRAY OF CHAR) ;
175 IF (NOT EOF
) AND (NOT IsStartOfComment()) AND (index
<High
) AND IsQuote()
177 (* found final quote *)
178 a
[index
] := SymbolChar() ;
183 (* copy literal into, a *)
184 WHILE (index
<High
) AND (NOT EOF
) AND (SymbolChar()#nul
) AND (NOT IsQuote()) DO
185 a
[index
] := SymbolChar() ;
191 WriteError('unterminated string, strings must terminate before the end of a line')
195 IF (NOT EOF
) AND (NOT IsStartOfComment())
197 IF (index
<High
) AND IsQuote()
199 (* found string start *)
200 a
[index
] := SymbolChar() ;
201 NextChar
; (* skip quote *)
205 (* normal symbol, not a comment and not a string *)
206 WHILE (index
<High
) AND (NOT NonSymbolChar()) AND (NOT IsStartOfComment()) DO
207 a
[index
] := SymbolChar() ;
218 LengthOfCurSym
:= index
223 ChuckUpToSymbol - throws away white space and comments.
226 PROCEDURE ChuckUpToSymbol
;
229 IF (NOT EOF
) AND IsStartOfComment()
232 WHILE (NOT EOF
) AND (NOT IsEndOfComment()) DO
236 WHILE (NOT EOF
) AND NonSymbolChar() DO
239 UNTIL EOF
OR (NOT IsStartOfComment())
240 END ChuckUpToSymbol
;
244 SymbolChar - returns a character from the CurrentString, if the end
245 of CurrentString is found then SymbolChar returns nul.
248 PROCEDURE SymbolChar () : CHAR ;
254 IF CurrentCursorPos
<StrLen(CurrentString
)
256 RETURN( CurrentString
[CurrentCursorPos
] )
264 (* NextChar advances the CurrentCursorPos along a line of the source, *)
265 (* resetting the CurrentCursorPos every time a newline is read. *)
271 IF CurrentCursorPos
<StrLen(CurrentString
)
273 INC(CurrentCursorPos
)
275 ReadString(CurrentString
) ;
276 (* WriteString( CurrentString ) ; WriteLn ; *)
278 CurrentCursorPos
:= 0 ;
285 PROCEDURE NonSymbolChar () : BOOLEAN ;
287 RETURN( CurrentString
[CurrentCursorPos
]<=' ' )
291 PROCEDURE WriteError (a
: ARRAY OF CHAR) ;
294 LineNo
: ARRAY [0.
.20] OF CHAR ;
296 WriteString(FileName
) ;
298 CardToStr(CurrentLineNo
, 0, LineNo
) ;
299 WriteString(LineNo
) ;
301 WriteString( CurrentString
) ; WriteLn
;
302 WriteString(FileName
) ;
304 WriteString(LineNo
) ;
307 j
:= CurrentCursorPos
-LengthOfCurSym
;
312 FOR i
:= 1 TO LengthOfCurSym
DO
316 WriteString(FileName
) ;
318 WriteString(LineNo
) ;
320 WriteString( a
) ; WriteLn
;
328 PROCEDURE ReadString (VAR a
: ARRAY OF CHAR) ;
338 IF (ch
=del
) OR (ch
=bs
)
351 IF (ch
= cr
) OR (cr
= lf
)
360 ch
:= cr (* exit gracefully *)
366 PROCEDURE Read (VAR ch
: CHAR) ;
371 EOF
:= NOT IsNoError(f
)
375 IF ch
=lf
THEN ch
:= cr
END
380 TerminateOnError - exits with status 1 if we call WriteError.
383 PROCEDURE TerminateOnError
;
386 END TerminateOnError
;
390 DefineComments - defines the start of comments within the source
393 The characters in Start define the comment start
394 and characters in End define the end.
395 The BOOLEAN eoln determine whether the comment
396 is terminated by end of line. If eoln is TRUE
400 PROCEDURE DefineComments (Start
, End
: ARRAY OF CHAR; eoln
: BOOLEAN) ;
402 TerminateOnEndOfLine
:= eoln
;
403 StrCopy(Start
, CommentLeader
) ;
404 StrCopy(End
, CommentTrailer
) ;
405 AllowComments
:= StrLen(CommentLeader
)>0
411 AllowComments
:= FALSE ;
412 TerminateOnEndOfLine
:= FALSE ;
413 StrCopy('' , CurrentString
) ;
414 LengthOfCurSym
:= 0 ;
415 CurrentCursorPos
:= 0 ;