<> <> <<>> DIRECTORY Rope, IO, Convert, MathDisplayExpr, Parser; ParserImpl: CEDAR PROGRAM IMPORTS Convert, Rope EXPORTS Parser = BEGIN OPEN Parser; <> parseError: PUBLIC ERROR = CODE; <> ROPE: TYPE ~ Rope.ROPE; DisplayExpr: TYPE ~ MathDisplayExpr.DisplayExpr; <> LexChar: PUBLIC PROC[c: CHAR] RETURNS[LexType] ~ { <> RETURN[ SELECT c FROM IN ['0..'9] => digit, IN ['a..'z] => lcAlpha, IN ['A..'Z], '%, '$, '@, '\134 => ucAlpha, '. => decimalPoint, '? => templateDelimiter, '[, '\005 => leftBracket, '% => symbolDelimiter, '+, ' , '-, '*, '/, '^, '_, '{, '(, '!, '$, '@, '&, '|, '~, '=, '>, '<, '#, '' => singleCharTemplate, '\010 => backSpace, ENDCASE => other ]; }; <<1/15/87 - Control characters typed by holding down the control key will be processed through the tip table, but hitting the backspace key should bring us through here>> <> <> <<>> ParseKBChar: PUBLIC PROC[c: CHAR, inBuffer: KbBuffer, primaryActive, keyboardActive: BOOL _ FALSE] RETURNS [outBuffer: KbBuffer, action: ParseAction _ NIL] ~ { <> <> << Updates kbBuffer, message window, and $keyboard selection (viewer & expr).>> <<>> <> lexC: LexType _ LexChar[c]; -- lexical type of character c ropeC: Rope.ROPE _ Convert.RopeFromChar[c, FALSE]; -- rope equivalent of char c kbBuffer: KbBuffer _ inBuffer; SELECT lexC FROM singleCharTemplate => { wrapAround: ATOM _ IF primaryActive THEN $primary ELSE $keyboard; SELECT c FROM '+ => action _ NEW[WrapAction _ [wrap[wrapAround, $sum]]]; ' => action _ NEW[WrapAction _ [wrap[wrapAround, $difference]]]; '- => action _ NEW[WrapAction _ [wrap[wrapAround, $negation]]]; '* => action _ NEW[WrapAction _ [wrap[wrapAround, $product]]]; '/ => action _ NEW[WrapAction _ [wrap[wrapAround, $fraction]]]; '^ => action _ NEW[WrapAction _ [wrap[wrapAround, $pow]]]; '_ => action _ NEW[WrapAction _ [wrap[wrapAround, $assign]]]; '' => action _ NEW[WrapAction _ [wrap[wrapAround, $quote]]]; '{ => action _ NEW[WrapAction _ [wrap[wrapAround, $curly]]]; '( => action _ NEW[WrapAction _ [wrap[wrapAround, $paren]]]; <<'[ => action _ NEW[WrapAction _ [wrap[wrapAround, $square]]];>> '! => action _ NEW[WrapAction _ [wrap[wrapAround, $factorial]]]; <<'$ => action _ NEW[WrapAction _ [wrap[wrapAround, $exists]]];>> <<'@ => action _ NEW[WrapAction _ [wrap[wrapAround, $forAll]]];>> '& => action _ NEW[WrapAction _ [wrap[wrapAround, $and]]]; '| => action _ NEW[WrapAction _ [wrap[wrapAround, $or]]]; '~ => action _ NEW[WrapAction _ [wrap[wrapAround, $not]]]; '= => action _ NEW[WrapAction _ [wrap[wrapAround, $eqFormula]]]; '> => action _ NEW[WrapAction _ [wrap[wrapAround, $gtFormula]]]; '< => action _ NEW[WrapAction _ [wrap[wrapAround, $ltFormula]]]; '# => action _ NEW[WrapAction _ [wrap[wrapAround, $notEqFormula]]]; ENDCASE => ERROR; -- check consistency with defn of singleCharTemplate kbBuffer _ [type: none, data: "", savedWrapArg: NIL]; -- reset kbBuffer }; templateDelimiter => SELECT kbBuffer.type FROM templateName => { -- finishing a multiChar templateName name: Rope.ROPE _ kbBuffer.data; class: ATOM _ Convert.AtomFromRope[ExpandAbbreviation[name]]; action _ NEW[FinishMultiCharTemplateAction _ [finishMultiCharTemplate[class]] ]; }; ENDCASE => { -- start multi-character templateName wrapAround: ATOM _ IF primaryActive THEN $primary ELSE $keyboard; action _ NEW[BeginMultiCharTemplateAction _ [beginMultiCharTemplate[wrapAround]] ]; }; backSpace => action _ NEW[UndoAction]; ENDCASE => SELECT keyboardActive FROM FALSE => { -- newly active keyboard; should never be here with Templates SELECT lexC FROM digit => { -- replace $primary with keystroke digit kbBuffer.type _ integer; kbBuffer.data _ ropeC; action _ NEW[ReplaceAction _ [replace[$primary, integer, kbBuffer.data, $keyboard]]]; }; lcAlpha, ucAlpha => { -- replace $primary with keystroke letter kbBuffer.type _ variable; kbBuffer.data _ ropeC; action _ NEW[ReplaceAction _ [replace[$primary, variable, kbBuffer.data, $keyboard]]]; }; ENDCASE => action _ NEW[NoAction]; }; TRUE => { -- already active keyboard SELECT kbBuffer.type FROM integer => { -- extend the integer currently in KB buffer, or convert to real SELECT lexC FROM digit => { kbBuffer.data _ kbBuffer.data.Cat[ropeC]; action _ NEW[ReplaceAction _[replace[$keyboard, integer, kbBuffer.data, $keyboard]]]; }; decimalPoint => { kbBuffer.type _ real; kbBuffer.data _ kbBuffer.data.Cat[ropeC]; action _ NEW[ReplaceAction _ [replace[$keyboard, real, kbBuffer.data, $keyboard]]]; }; ENDCASE => action _ NEW[NoAction]; }; real => { -- extend the REAL currently in KB buffer SELECT lexC FROM digit => { kbBuffer.data _ kbBuffer.data.Cat[ropeC]; action _ NEW[ReplaceAction _ [replace[$keyboard, real, kbBuffer.data, $keyboard]]]; }; ENDCASE => action _ NEW[NoAction]; }; variable => { SELECT lexC FROM ucAlpha, lcAlpha => { -- extend the var currently in KB buffer kbBuffer.data _ kbBuffer.data.Cat[ropeC]; action _ NEW[ReplaceAction _ [replace[$keyboard, variable, kbBuffer.data, $keyboard]]]; }; leftBracket => { -- interpret the identifier currently in KB buffer as a (completed) templateName name: Rope.ROPE _ ExpandAbbreviation[kbBuffer.data]; action _ NEW[ReplaceAction _ [replace[$keyboard, template, name, $primary]]]; kbBuffer _ [type: none, data: "", savedWrapArg: NIL]; -- reset kbBuffer }; ENDCASE => action _ NEW[NoAction]; }; templateName => { -- extend the templateName currently in KB buffer SELECT lexC FROM ucAlpha, lcAlpha, digit => { kbBuffer.data _ kbBuffer.data.Cat[ropeC]; action _ NEW[ReplaceAction _ [replace[$keyboard, templateName, kbBuffer.data, $keyboard]]]; }; ENDCASE => action _ NEW[NoAction]; }; ENDCASE => ERROR; }; ENDCASE => ERROR; RETURN[kbBuffer, action]; }; ExpandAbbreviation: PUBLIC PROC [name: ROPE] RETURNS [ROPE] ~ { SELECT TRUE FROM -- check for recognized abbreviations Rope.Equal[name, "nRad"] => RETURN["nRadical"]; Rope.Equal[name, "partialderiv"] => RETURN["partialDeriv"]; Rope.Equal[name, "indefint"] => RETURN["indefInt"]; Rope.Equal[name, "sigma"] => RETURN["summation"]; Rope.Equal[name, "Pow"] => RETURN["pow"]; Rope.Equal[name, "Mult"] => RETURN["product"]; Rope.Equal[name, "Div"] => RETURN["fraction"]; Rope.Equal[name, "Plus"] => RETURN["sum"]; Rope.Equal[name, "Minus"] => RETURN["negation"]; -- for SMP Rope.Equal[name, "mult"] => RETURN["product"]; Rope.Equal[name, "div"] => RETURN["fraction"]; Rope.Equal[name, "plus"] => RETURN["sum"]; Rope.Equal[name, "minus"] => RETURN["negation"]; -- for SMP Rope.Equal[name, "Difference"] => RETURN["difference"]; -- for SMP ENDCASE; RETURN[name]; }; END.