INTERFACE M3CParse; (***************************************************************************) (* Copyright (C) Olivetti 1989 *) (* All Rights reserved *) (* *) (* Use and copy of this software and preparation of derivative works based *) (* upon this software are permitted to any person, provided this same *) (* copyright notice and the following Olivetti warranty disclaimer are *) (* included in any copy of the software or any modification thereof or *) (* derivative work therefrom made by any person. *) (* *) (* This software is made available AS IS and Olivetti disclaims all *) (* warranties with respect to this software, whether expressed or implied *) (* under any law, including all implied warranties of merchantibility and *) (* fitness for any purpose. In no event shall Olivetti be liable for any *) (* damages whatsoever resulting from loss of use, data or profits or *) (* otherwise arising out of or in connection with the use or performance *) (* of this software. *) (***************************************************************************) IMPORT Text, CharType, IO; IMPORT M3AST_LX, M3AST_AS; IMPORT M3CSrcPos, M3CHash, M3CLex, M3CReservedWord; (* Parser for Modula 3 *) TYPE T <: M3CLex.T; (* Type representing parser *) (* The user provides an error handler to handle parsing errors. Its 'handle' method is called with the position and a description of the error when an error occurs *) ErrorHandler = OBJECT METHODS handle(pos: M3CSrcPos.T; msg: Text.T) RAISES {}; END; PROCEDURE New( s: IO.Stream; identifiers: M3CReservedWord.Table; literals: M3CHash.Table; errorHandler: ErrorHandler; init: T := NIL) : T RAISES {}; (* Create a new parser (and hence a new lexer) on the stream 's'. 'identifiers' is the table that will be used for identifiers found during parsing. As it is a 'M3CReservedWord.Table' it already contains all the Modula 3 reserved words. Any literals found will be stored, as texts, in the 'literals' table. The 'errorHandler' object is used whenever an error occurs; the 'handle' method is called with the position of the error and a message as arguments. The final argument 'init' is only used when creating a subtype of 'parser'; if it is non NIL 'init' is initialized to be a valid parser and no new parser is created *) PROCEDURE Compilation( t: T; headerOnly := FALSE) : M3AST_AS.Compilation_Unit RAISES {IO.Error}; (* Attempts to parse an entire compilation unit i.e. an interface or module. Any comments and pragmas found are stored with the compilation unit. If the 'headerOnly' flag is TRUE the parse is stopped after the exports and import clauses have been parsed and a skeleton compilation unit is returned. Such a skeleton may be useful for dependency analysis *) PROCEDURE Any( t: T; terminators := CharType.None) : REFANY RAISES {IO.Error}; (* Attempts to parse whatever construct is next on the parse stream. The parse finishes at a natural boundary, if end of stream is reached or if a character in 'terminators' is encountered. The result of the parse is returned. Any comments and pragmas encountered can be returned by the 'Comments' and 'Pragmas' procedures. A natural boundary is rather vaguely defined. It depends on the first symbols encountered on the parse stream. Here are the various cases. Note that where a "list of whatever" is parsed the parse is terminated by any symbol which cannot be the start of another "whatever". e.g. a sequence of imports is definitely at an end if you encounter a token which can never be in an import e.g. the start of a declaration. Initial symbol Action Start of unit parse a single unit, returning a 'UNIT'. Start of import statement parse a list of IMPORT statements, returning a 'SeqIMPORTED'. Start of statement parse a sequence of statements, returning a 'seqSTM'. Start of declaration parse a sequence of declarations. If the sequence is followed by 'BEGIN' treat these declarations as the start of a block statement - see the section on statements. Otherwise return a 'seqDECL_REVL'. Start of type parse a single type, returning a 'TYPE_SPEC'. Note that a named type cannot be distinguished from an expression by the parser, hence named types are parsed as expressions. Start of expression parse a single expression. If the expression is followed by ':=' treat it as the start of an assignment - see the section on statements. If the expression is a call and is followed by ';' treat as a procedure call statement - see the section on statements. Otherwise return the expression. If the first symbol encountered is not the start of any of the items given above 'Any' returns NIL. If the end of stream is encountered it (obviously) stops the parse. The 'terminators' set gives another way of stopping a parse. All characters in the 'terminators' set must be printable characters which are illegal in Modula 3 programs (see the set 'M3CToken.PrintableBadChars'). If a printable illegal character is encountered and it is in the user supplied set 'terminators' the parse is stopped. Otherwise an error is given and the parse continues. If the user supplies a value for 'terminators' which is not a subset of the printable illegal characters a checked runtime error results. *) PROCEDURE Comments(t: T): M3AST_LX.CommentStore RAISES {}; (* Used after a call of 'Any' to return any comments found during the parse. Each call to 'Any' resets the comment store before it starts so the result of 'Comments' always reflects the comments found in the last call to 'Any' *) PROCEDURE Pragmas(t: T): M3AST_LX.PragmaStore RAISES {}; (* Used after a call of 'Any' to return any pragmas found during the parse. Each call to 'Any' resets the pragma store before it starts so the result of 'Pragmas' always reflects the pragmas found in the last call to 'Any' *) PROCEDURE Reset(t: T; pos := M3CSrcPos.Null; s: IO.Stream := NIL) RAISES {}; (* Resets the lexer and optionally sets the position and stream used by the lexer and parser. The position is significant because many nodes have source positions and also because error messages need positions. If 's' is NIL the position is only changed if 'pos' is not null. If 's' is not NIL the position is changed to 'pos' if it is not null and otherwise to line 1 offset 0 *) END M3CParse.