<<-- MUMBLE PARSER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Parser>> -- MUMParser.mesa of August 3, 1982 6:44 pm <<-- To do: revise for viewers>> DIRECTORY Rope USING [Ref, Int]; MUMParser: DEFINITIONS = BEGIN -- SOURCE CHARACTERS AND LEXICAL SYMBOLS - - - - - - - - - - - - - - - - - - - - - - - - CHAR: TYPE = CHARACTER; <<-- The following character is expected at the end of the source string.>> ETX: CHAR = 277C; <<-- A SourcePt defines a substring of the input text and gives its position in it.>> SourcePt: TYPE = RECORD [Src: Rope.Ref, Pos: Rope.Int]; <<-- The lexical analyzer breaks (on demand) the input text into a sequence of Symbols, returned as a Tail.>> Token: TYPE = RECORD [Sy: Symbol, SP: SourcePt]; Tail: TYPE = RECORD [Toks: LIST OF Token, Rest: SourcePt]; <<-- The symbols recognized by the parser. Invalid must be last.>> Symbols: TYPE = {Add, All, And, AndAlso, Array, BegExpr, BegParms, BegRec, Blt, Box, Cast, Cat, Center, Circle, Count, Cut, Def, Depth, DeRef, Div, Do, Ellipse, Else, EndExpr, EndParms, EndRec, Eql, Eqv, Erase, For, From, GEq, Gtr, HMirror, Id, In, Is, Laminate, LEq, Lss, Mod, NEq, Not, Num, Or, Opaque, Paste, Quote, ReDef, Ref, Rep, RevShift, RevRot, Rot, Sample, Shift, String, Sub, Then, ThenDo, Triangle, VMirror, Xor, Invalid}; Ord: PROC [Sy: Symbol] RETURNS [INTEGER] = INLINE {RETURN [LOOPHOLE [Sy]]}; <<-- Each symbol except Id, Num and String has a "standard" one-character representation, defined by the functions below. These functions return InvalidChar and Invalid, respectively, if the argument is invalid.>> <<-- The MUMBLE editor may feel free to generate the standard character codes (e.g., by defining keyboard chords for all or some of them).>> <<-- We'd better not to use more than 11110 symbols... >> FirstSymbolChar: CHAR = 221C; InvalidChar: CHAR = SymbolBaseChar + Ord [Invalid]; SymbolToChar: PROC [Sy: Symbol] RETURNS [Char: CHAR] = INLINE {RETURN [IF Sy = Id OR Sy = Num OR Sy = String THEN InvalidChar ELSE FirstSymbolChar + Ord [Sy]]}; CharToSymbol: PROC [Char: CHAR] RETURNS [Sy: Symbol] = INLINE {IF Char IN [SymbolBaseChar .. LastSymbolChar) THEN {Sy _ LOOPHOLE [Char - SymbolBaseChar, Symbol]; IF Sy = Num OR Sy = String THEN Sy _ Invalid} ELSE Sy _ Invalid}; -- LEXICAL AND SYNTACTICAL TABLES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <<-- The table below distinguishes between operators (unary and binary) and other symbols. It gives also the "priority" and "associativity" of binary operators.>> <<-- The priority increases as the numerical value of Prio decreases. If Assoc = TRUE, the operator can be mixed with other of same priority, and the expression will be evaluated from left to right. If Assoc = FALSE, there must be a parenthesis or equivalent somewhere between that operator and any other with the same priority.>> <<-- Besides the "standard" character code defined above, a symbol usually has also an "alternate" representations (a string of letters or special characters). These are also given by the table below.>> SymbolKind: TYPE = {UnOp, BinOp, Other}; SymbolProperties: TYPE = RECORD [Alias: STRING, Kind: SymbolKind _ Other, Prio: Priority _ NULL, Assoc: BOOLEAN _ NULL] Props: ARRAY Symbol OF SymbolProperties = [[Mod: ["mod", BinOp, 02, TRUE], Mul: ["*", BinOp, 02, TRUE], Div: ["/", BinOp, 02, TRUE], Array: ["array", BinOp, 02, FALSE], Cat: ["cat", BinOp, 03, TRUE], Cut: ["cut", BinOp, 04, TRUE], HMirror: ["hmir", BinOp, 04, TRUE], RevRot: ["rrot", BinOp, 04, TRUE], Rot: ["rot", BinOp, 04, TRUE], Sample: ["sample", BinOp, 04, TRUE], VMirror: ["vmir", BinOp, 04, TRUE], Center: ["center", BinOp, 06, TRUE], RevShift: ["rsh", BinOp, 06, TRUE], Shift: ["sh", BinOp, 06, TRUE], Add: ["+", BinOp, 06, TRUE], Sub: ["-", BinOp, 06, TRUE], Eql: ["=", BinOp, 08, FALSE], GEq: [">=", BinOp, 08, FALSE], GTr: [">", BinOp, 08, FALSE], In: ["in", BinOp, 08, FALSE], Is: ["?", BinOp, 08, FALSE], LEq: ["<=", BinOp, 08, FALSE], Lss: ["<", BinOp, 08, FALSE], NEq: ["#", BinOp, 08, FALSE], Xor: ["xor", BinOp, 09, TRUE], Eqv: ["eqv", BinOp, 09, FALSE], And: ["&", BinOp, 10, TRUE], Erase: ["ers", BinOp, 10, TRUE], Where: ["wh", BinOp, 10, FALSE], Or: ["or", BinOp, 12, TRUE], Over: ["over", BinOp, 12, TRUE], From: ["fr", BinOp, 14, TRUE], Depth: ["dp", BinOp, 14, TRUE], Laminate: ["|", BinOp, 16, TRUE], Blt: ["_", BinOp, 18, FALSE], ReDef: [":=", BinOp, 20, TRUE], ThenDo: [";", BinOp, 22, TRUE], Box: ["box", UnOp], Circle: ["circle", UnOp], Count: ["count", UnOp], DeRef: ["^", UnOp], Ellipse: ["ellipse", UnOp], Not: ["~", UnOp], Opaque: ["opaque", UnOp], Quote: ["'", UnOp], Ref: ["@", UnOp], Rep: ["rep", UnOp], Triangle: ["tri", UnOp], All: ["all", UnOp], AndAlso: [","], BegExpr: ["("], BegParms: ["{"], BegRec: ["["], Cast: ["!"], Def: [":"], Do: ["do"], Else: ["else"], EndExpr: [")"], EndParms: ["}"], EndRec: ["]"], For: ["for"], Then: ["then"]]; -- PARSED EXPRESSION TREE - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Expr: TYPE = RECORD [Good: BOOLEAN, Source: SourcePt, Body: SELECT Kind: * FROM Int => [Val: LONG INTEGER], Id, String => [Chars: Rope.Ref], Symbol => [Sy: Symbol], Infix => [Op, Left, Right: RefExpr], Cond => [Test, Then, Else: RefExpr], Loop => [Var: REF Id Expr, Count, Test, Body: RefExpr], Proc => [Parm: FieldExpr, Body: RefExpr], RecExpr => [LS: LIST OF FieldExpr] ENDCASE]; RefExpr: TYPE = REF Expr; FieldExpr: TYPE = RECORD [Name: REF Id Expr, Val: RefExpr, Mold: RefExpr]; -- THE PARSER (PHEW!) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Parse: PROCEDURE [T: Tail] RETURNS [EX: RefExpr, RT: Tail]; END.