-- September 9, 1982 5:57 pm
-- Parser.mesa
-- Last edited January 10, 1983 5:50 pm

-- Simple operator precedence parser for operators of the following types: infix, prefix, postfix,
-- matchfix (like "begin" or left grouping parenthesis), subfix (like "[" in Mesa or "(" in f(x))
-- and closefix (like "end" or ")").

-- The symbolic expression constructed by the parser is represented as in Lisp, by a nest
-- of ordered pairs; the list cells employed are those of Mesa's LIST OF REF ANY.
-- Last Edited by: Gnelson, January 10, 1983 5:50 pm

DIRECTORY List, Atom, IO, Rope, Lexer, ParseTable;

Parser: DEFINITIONS
= BEGIN OPEN PT: ParseTable;

Handle: TYPE = REF HandleRec;

HandleRec: TYPE = RECORD
  [error: Rope.ROPE,  -- initially NIL, set to error message on lexical error
   eof: BOOL,         -- initially FALSE, set to TRUE on end of input.
   result: REF ANY,  -- contains last thing produced by Parse.
   openCount: INT,   -- number of unmatched matchfixs or subfixs in last thing parsed
   in: Lexer.Handle,  -- Source of lexemes to be parsed. 
       -- WARNING The initial value of in.a is relevant; see "Parse" below 
   table: PT.Handle];  --  associates operator types with operators.

NewHandle: PROC RETURNS [h: Handle];

Parse: PUBLIC PROC[h: Handle];
  -- sets h.result to the List representing the longest prefix of
  -- the lexeme stream h.in that is a valid symbolic expression,
  -- counting the current value of h.in.a as the first lexeme.  Thus
  -- the way to start the parser is to call Lex[h.in]; Parse[h].
  -- This will parse one expression and leave in h.in.a the first lexeme
  -- not used in the parse tree; thus successive calls will work.
  -- Sets h.eof if h.in.eof is set
  -- Sets h.error if h.in.error is set, or if a parse error occurs.
  -- If h.error AND ~ h.in.error AND ~h.in.eof then the input can be reconstructed
  -- by Unparse[h.result]; print h.in.a; print all of h.in, except that
  -- in the unparse you should skip the NIL that appears at the right-most
  -- position in h.result.

END.