JunoExpressionsImpl.mesa (was OldJunoParserEtcImpl.mesa)
Coded December 7, 1982 4:18 pm
Last Edited by: Gnelson, January 19, 1984 1:35 pm
Last Edited by: Stolfi June 13, 1984 1:07:04 pm PDT

DIRECTORY

Rope USING [ROPE],
JunoExpressions,
JunoParseUnparse USING
[Se, Verdict, SyntacticPredicate, Or, HasForm, Is, VerdictAndCulprit, False],
Atom USING [MakeAtom];

JunoExpressionsImpl: CEDAR PROGRAM

IMPORTS

JunoParseUnparse,
Atom

EXPORTS

JunoExpressions =

BEGIN

OPEN

Rope,
JunoExpressions,
JunoParseUnparse;

- - - - IMPORTED TYPES

Sp: TYPE = SyntacticPredicate; -- Se = "symbolic expression"

VaC: TYPE = VerdictAndCulprit;

- - - - RESERVED ATOMS

Tokens that have special meaning for the Juno interpreter:
and: PUBLIC ATOM ← $and;
approx: PUBLIC ATOM ← Atom.MakeAtom["=="];
assign: PUBLIC ATOM ← Atom.MakeAtom[":="];
at: PUBLIC ATOM ← $at;
ccw: PUBLIC ATOM ← $ccw;
colon: PUBLIC ATOM ← Atom.MakeAtom[":"];
comma: PUBLIC ATOM ← Atom.MakeAtom[","];
cong: PUBLIC ATOM ← $cong;
cons: PUBLIC ATOM ← $cons;
dec: PUBLIC ATOM ← $dec;
dist: PUBLIC ATOM ← Atom.MakeAtom["--"];
div: PUBLIC ATOM ← Atom.MakeAtom["/"];
do: PUBLIC ATOM ← $do;
draw: PUBLIC ATOM ← $draw;
ends: PUBLIC ATOM ← $ends;
fill: PUBLIC ATOM ← $fill;
first: PUBLIC ATOM ← $first;
floor: PUBLIC ATOM ← $floor;
font: PUBLIC ATOM ← $font;
hor: PUBLIC ATOM ← $hor;
if: PUBLIC ATOM ← $if;
inc: PUBLIC ATOM ← $inc;
justified: PUBLIC ATOM ← $justified;
lambda: PUBLIC ATOM ← Atom.MakeAtom[">>"];
leftPren: PUBLIC ATOM ← Atom.MakeAtom["("];
minus: PUBLIC ATOM ← Atom.MakeAtom["-"];
obox: PUBLIC ATOM ← Atom.MakeAtom["//"];
paint: PUBLIC ATOM ← $paint;
para: PUBLIC ATOM ← $para;
perp: PUBLIC ATOM ← $perp;
plus: PUBLIC ATOM ← Atom.MakeAtom["+"];
print: PUBLIC ATOM ← $print;
rel: PUBLIC ATOM ← $rel;
rest: PUBLIC ATOM ← $rest;
rightArrow: PUBLIC ATOM ← Atom.MakeAtom["->"];
semicolon: PUBLIC ATOM ← Atom.MakeAtom[";"];
size: PUBLIC ATOM ← $size;
skip: PUBLIC ATOM ← $skip;
stroke: PUBLIC ATOM ← $stroke;
face: PUBLIC ATOM ← $face;
suchThat: PUBLIC ATOM ← Atom.MakeAtom["|"];
times: PUBLIC ATOM ← Atom.MakeAtom["*"];
true: PUBLIC ATOM ← $T;
ver: PUBLIC ATOM ← $ver;
width: PUBLIC ATOM ← $width;
xcoord: PUBLIC ATOM ← $xcoord;
ycoord: PUBLIC ATOM ← $ycoord;

- - - - SYNTAX CHECKING TOOLS

Nest: PROC [f: Se, Elem: Sp, op: ATOM ← comma, min: INT ← 0, max: INTLAST[INT],
Zero: Sp ← False] RETURNS [r: VaC] =
Checks for a nest of a specific binary operator. The Zero may occur only on the right side.

BEGIN
nel: INT ← 0;
CtElem: Sp = {r ← Elem[f]; IF r.verdict = yes THEN nel ← nel+1};
NestRest: Sp = {RETURN [Or[Zero[f], HasForm[f, op, CtElem, NestRest]]]};
r ← NestRest[f];
IF r.verdict = yes THEN
{IF nel > max OR nel < min THEN r ← [no, f]}
END;

OptParNest: PROC [f: Se, Elem: Sp, op: ATOM ← comma,
min: INT ← 0, max: INTLAST[INT], Zero: Sp ← False] RETURNS [r: VaC] =
Checks for a nest, possibly enclosed in parenthesis

BEGIN
Nst: Sp = {RETURN [Nest[f, Elem, op, min, max, Zero]]};
RETURN[Or[HasForm[f, leftPren, Nst], Nst[f]]]
END;

InfixLength: PROC[l: Se] RETURNS [INT] =
{IF ISTYPE[NARROW[l, REF ANY], ATOM]
THEN RETURN[1]
ELSE RETURN[1 + InfixLength[Caddr[NARROW[l]]]]};

- - - - SYNTAX OF JUNO SYMBOLIC EXPRESSIONS

Command: PUBLIC Sp = {RETURN [Or
[AtomicCommand[f],
Alternation[f],
Iteration[f],
PushState[f],
Composition[f]]]};

AtomicCommand: Sp = {RETURN [Or
[Draw[f],
Print[f],
ProcCall[f],
Assignment[f],
Is[f, skip]]]};

Draw: Sp = {RETURN [Or
[HasForm[f, stroke, DrawList],
HasForm[f, fill, DrawList],
HasForm[f, draw, DrawList]]]};

DrawList: Sp = {RETURN [Or
[DrawListElem[f],
HasForm[f, comma, DrawListElem, DrawList]]]};

DrawListElem: Sp = {RETURN [Or[PointPairExpr[f], PointQuadExpr[f]]]};

PointPairExpr: Sp = {RETURN [OptParNest[f: f, Elem: PointExpr, min: 2, max: 2]]};

PointQuadExpr: Sp = {RETURN [OptParNest[f: f, Elem: PointExpr, min: 4, max: 4]]};

PointExpr: Sp = {RETURN [Or
[Or[Var[f],
NumPairExpr[f],
FuncCall[f],
HasForm[f, leftPren, PointExpr],
HasForm[f, rel, NumPairExpr, FrameExpr]]]]};

Var: Sp = {IF ISTYPE[Car[f], ATOM]
THEN RETURN [[yes, NIL]] ELSE RETURN [[ofCourseNot, f]]};

FuncCall: Sp = {RETURN [HasForm[f, leftPren, Var, ExprList]]};

VarList: Sp = {RETURN[Or[Var[f], HasForm[f, comma, Var, VarList]]]};

ExprList: Sp = {RETURN [Nest[f: f, Elem: Expr, op: comma, Zero: NIL]]};

NumPairExpr: Sp = {RETURN [HasForm[f, leftPren, TwoNumExprs]]};

TwoNumExprs: Sp = {RETURN [HasForm[f, comma, NumExpr, NumExpr]]};

NumExpr: Sp = {RETURN [Or
[Var[f],
FuncCall[f],
NumLit[f],
ArithOp[f],
HasForm[f, leftPren, NumExpr]]]};

NumLit: Sp = {IF ISTYPE[Car[f], REF INT] OR ISTYPE[Car[f], REF REAL]
   THEN RETURN [[yes, NIL]]
   ELSE RETURN [[ofCourseNot, f]]};

ArithOp: Sp = {RETURN [Or
[HasForm[f, LIST[minus, inc, dec, floor, first, xcoord, ycoord], NumExpr],
HasForm[f, LIST[plus, times, minus, div], NumExpr, NumExpr],
HasForm[f, dist, PointExpr, PointExpr]]]};

Expr: PUBLIC Sp = {RETURN [Or
[Var[f],
FuncCall[f],
NumLit[f],
RopeLit[f], Or[
ArithOp[f],
OtherOp[f],
Lambda[f],
HasForm[f, leftPren, Expr]]]]};

OtherOp: Sp = {RETURN [Or
[HasForm[f, LIST[rest], Expr],
HasForm[f, LIST[cons], Expr, Expr],
HasForm[f, dist, PointExpr, PointExpr]]]};

Print: Sp = {RETURN [HasForm[f, leftPren, PrintOp, PrintList]]};

PrintOp: Sp = {RETURN [Is[f, print]]};

PrintList: Sp = {RETURN [HasForm[f, comma, RopeLit, PointExpr]]};

RopeLit: Sp = {IF ISTYPE[Car[f], ROPE]
   THEN RETURN [[yes]]
   ELSE RETURN [[ofCourseNot, f]]};

ProcCall: Sp = {RETURN [Or[Var[f], HasForm[f, leftPren, Var, ExprList]]]};

Assignment: Sp =
{v: VaC ← HasForm[f, assign, VarList, VarList];
IF v.verdict = yes AND InfixLength[Cadr[Car[f]]] # InfixLength[Caddr[Car[f]]]
THEN RETURN [[no, f]]
ELSE RETURN [v]};

Alternation: Sp = {RETURN[HasForm[f, if, GuardedCmdList, NIL]]};

Iteration: Sp = {RETURN[HasForm[f, do, GuardedCmdList, NIL]]};

GuardedCmdList: Sp = {RETURN[Or
[GuardedCmd[f],
HasForm[f, obox, GuardedCmd, GuardedCmdList]]]};

GuardedCmd: Sp = {RETURN[HasForm[f, rightArrow, Guard, Command]]};

Guard: Sp = {RETURN[Or [PredicateList[f], HasForm[f, suchThat, LocalList, PredicateList]]]};

LocalList: Sp = {RETURN[Or[LocalDecl[f], HasForm[f, comma, LocalDecl, LocalList]]]};

PredicateList: Sp = {RETURN[Or [Constraint[f], HasForm[f, and, Constraint, PredicateList]]]};

Constraint: Sp = {RETURN[Or
[Is[f, true],
HasForm[f, rel, PointConstraint, FrameExpr],
PointConstraint[f]]]};

PointConstraint: Sp = {RETURN[Or
[HasForm[f, LIST [hor, ver], PointPairExpr],
HasForm[f, LIST [cong, para, perp], PointPairExpr, PointPairExpr],
HasForm[f, ccw, PointTripletExpr],
HasForm[f, at, PointExpr, PointExpr]]]};

PointTripletExpr: Sp = {RETURN [OptParNest[f:f, Elem: PointExpr, min: 3, max: 3]]};

FrameExpr: Sp = {RETURN [OptParNest[f:f, Elem: PointExpr, min: 1, max: 3]]};

LocalDecl: Sp = {RETURN[Or[Var[f], HasForm[f, approx, Var, PointExpr]]]};

PushState: Sp = {RETURN[Or
[HasForm[f, LIST[width, size], NumExpr, Command],
HasForm[f, font, RopeLit, Command],
HasForm[f, LIST[face, paint, ends, justified], Var, Command]]]};

Composition: Sp = {RETURN[HasForm[f, semicolon, Command, Command]]};

Lambda: PUBLIC Sp = {RETURN[HasForm[f, lambda, Formals, Body]]};

Body: PUBLIC Sp = {RETURN[Or[Command[f], Expr[f]]]};

Formals: Sp = {RETURN[Nest[f: f, Elem: Var]]};

Definition: PUBLIC Sp = {RETURN[HasForm[f, colon, Header, Command]]};

Header: Sp = {RETURN[Or[Var[f], HasForm[f, leftPren, Var, Formals]]]};

- - - - CAR, CDR, ETC

Car: PUBLIC PROC [r: Se] RETURNS [Se] = {RETURN[NARROW[r, LIST OF REF ANY].first]};

Cdr: PUBLIC PROC [r: Se] RETURNS [Se] = {RETURN[NARROW[r, LIST OF REF ANY].rest]};

Cadr: PUBLIC PROC [r: Se] RETURNS [Se] = {RETURN[Car[Cdr[r]]]};

Caddr: PUBLIC PROC [r: Se] RETURNS [Se] = {RETURN[Car[Cdr[Cdr[r]]]]};

Cddr: PUBLIC PROC [r: Se] RETURNS [Se] = {RETURN[Cdr[Cdr[r]]]};

Caadr: PUBLIC PROC [r: Se] RETURNS [Se] = {RETURN[Car[Car[Cdr[r]]]]};

Cdar: PUBLIC PROC [r: Se] RETURNS [Se] = {RETURN[Cdr[Car[r]]]};

Cddar: PUBLIC PROC [r: Se] RETURNS [Se] = {RETURN[Cdr[Cdr[Car[r]]]]};

END.