home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 549a.lha / M2P_v1.0 / mods.lzh / FSM.mod < prev    next >
Encoding:
Modula Implementation  |  1991-08-10  |  19.9 KB  |  689 lines

  1. (*======================================================================*)
  2. (*            Modula-2 Lexical Analyzer  --  Finite State Machine       *)
  3. (*======================================================================*)
  4. (*  Version:  1.00              Author:   Dennis Brueni                 *)
  5. (*  Date:     04-29-91          Changes:  original                      *)
  6. (*======================================================================*)
  7. (*  This module contains the definitions and initialization code for    *)
  8. (*  the major tables used by the Finite State Machine of the Lexical    *)
  9. (*  Analyzer.                                                           *)
  10. (*======================================================================*)
  11.  
  12. IMPLEMENTATION MODULE FSM;
  13.  
  14. IMPORT
  15.     SYSTEM,ASCII,FIO;
  16. IMPORT
  17.     Err,HashTab;
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24. CONST
  25.     FirstCh = MIN(Alphabet);
  26.     LastCh = MAX(Alphabet);
  27.  
  28. (************************************************************************)
  29.  
  30. TYPE
  31.     HashTabEntry = POINTER TO HTEntry;
  32.  
  33.     HTEntry = RECORD
  34.         KW : POINTER TO StringsType;
  35.         KWType : Lexicals;
  36.     END;
  37.  
  38. (*----------------------------------------------------------------------*)
  39. (*  Global (to module) variables.                                       *)
  40. (*----------------------------------------------------------------------*)
  41.  
  42. VAR
  43.     token: Lexicals;
  44.  
  45.     KeyWords: ARRAY [MIN(Lexicals)..M2NOT] OF HTEntry;
  46.     HT: HashTab.HashTable;
  47.  
  48. VAR
  49.     ch: CHAR;                       (* Current INPUT CHAR   *)
  50.     PBack: BOOLEAN;                 (* PBack done?          *)
  51.     State: States;                  (* Current State        *)
  52.     CommNest: CARDINAL;             (* Current Nesting Level*)
  53.  
  54. (************************************************************************)
  55. (**                             ACTIONS                                 *)
  56. (************************************************************************)
  57. (*--PUSHBACK--Pushes the most recently read charactor back--------------*)
  58.  
  59.  
  60.  
  61. PROCEDURE PushBack;
  62. BEGIN
  63.  
  64.     PBack:=TRUE ;
  65. END PushBack;
  66.  
  67. (*--EMIT--Adds the charactor to the output string-----------------------*)
  68.  
  69. PROCEDURE Emit;
  70. BEGIN
  71.     WITH Token DO
  72.         IF Length >= TokenSize THEN
  73.             Err.Message(Err.TokTooLong);
  74.         ELSE
  75.             String[Length]:=ch;
  76.             INC(Length);
  77.         END;
  78.     END;
  79. END Emit;
  80.  
  81. (*--UNEMIT--Removes a charactor from the output string------------------*)
  82.  
  83. PROCEDURE UnEmit;
  84. BEGIN
  85.     WITH Token DO
  86.         DEC(Length);
  87.         String[Length]:=ASCII.NUL;
  88.     END;
  89. END UnEmit;
  90.  
  91. (*--ERROR--Writes the appropriate error message-------------------------*)
  92.  
  93. PROCEDURE Error;
  94.  
  95. VAR
  96.     mess: Err.Names;
  97. BEGIN
  98.     CASE State OF
  99.     STStr:
  100.         mess:=Err.StrNotEnded;
  101.     |STCommBeg, STCommSkip, STCommNest, STCommEnd, STCommLine:
  102.         mess:=Err.ComNotEnded;
  103.     ELSE
  104.         mess:=Err.IFail;
  105.     END;
  106.     Err.Message(mess);
  107.     State:=STStart;
  108.     Token.Length:=0;
  109.     CommNest:=0;
  110. END Error;
  111.  
  112. (*--NOTHING--ignores the current input charactor.-----------------------*)
  113.  
  114. PROCEDURE Nothing;
  115. BEGIN
  116. END Nothing;
  117.  
  118. (*--LINEECHO--Echo the current INPUT charactor if a linefeed------------*)
  119.  
  120. PROCEDURE LineEcho;
  121. BEGIN
  122.     INC(Err.LineNum);
  123.     IF IncludeLevel # 0 THEN
  124.         ch:=' ';
  125.         DEC(Err.LineNum);
  126.     END;
  127.     FIO.WriteChar(DestFile,ch);
  128. END LineEcho;
  129.  
  130. (*--ECHOCOMMENT--Echo a charactor in a comment to the output file------*)
  131.  
  132. PROCEDURE EchoComment;
  133. BEGIN
  134.     IF NOT StripFlag THEN
  135.         FIO.WriteChar(DestFile,ch);
  136.     END;
  137. END EchoComment;
  138.  
  139. (*--INCOMMENT--Increment the comment nesting level count----------------*)
  140.  
  141. PROCEDURE InComment;
  142. BEGIN
  143.     INC(CommNest);
  144.     IF NOT StripFlag THEN
  145.         FIO.WriteChar(DestFile,'(');
  146.         FIO.WriteChar(DestFile,'*');
  147.         EchoComment;
  148.     END;
  149. END InComment;
  150.  
  151. (*--OUTCOMMENT--Decrement the comment nesting level count---------------*)
  152.  
  153. PROCEDURE OutComment;
  154. BEGIN
  155.     DEC(CommNest);
  156.     IF CommNest=0 THEN
  157.         State:=STSkipSpaces;    (* replace comment with single space    *)
  158.     END;
  159.     EchoComment;
  160. END OutComment;
  161.  
  162. (*--ACCATSIGN--Accept an '@'-------------------------------------------*)
  163.  
  164.  
  165.  
  166. PROCEDURE AccAtSign;
  167. BEGIN
  168.     Emit;
  169.     Token.Class:=M2AtSign;
  170. END AccAtSign;
  171.  
  172. (*--ACCNOT--Accept a tilde (not)---------------------------------------*)
  173.  
  174. PROCEDURE AccNot;
  175. BEGIN
  176.     Emit;
  177.     Token.Class:=M2NOT;
  178. END AccNot;
  179.  
  180. (*--ACCCOMMA--Accept a comma-------------------------------------------*)
  181.  
  182. PROCEDURE AccComma;
  183. BEGIN
  184.     Emit;
  185.     Token.Class:=M2Comma;
  186. END AccComma;
  187.  
  188. (*--ACCLPAREN--Accept a left parenthesis-------------------------------*)
  189.  
  190. PROCEDURE AccLParen;
  191. BEGIN
  192.     PBack:=TRUE ;
  193.     Token.Class:=M2LParen;
  194. END AccLParen;
  195.  
  196. (*--ACCRPAREN--Accept a right parenthesis------------------------------*)
  197.  
  198. PROCEDURE AccRParen;
  199. BEGIN
  200.     Emit;
  201.     Token.Class:=M2RParen;
  202. END AccRParen;
  203.  
  204. (*--ACCAND--Accept a & (and)-------------------------------------------*)
  205.  
  206. PROCEDURE AccAnd;
  207. BEGIN
  208.     Emit;
  209.     Token.Class:=M2AND;
  210. END AccAnd;
  211.  
  212. (*--ACCOR--Accept a vertical bar (or)----------------------------------*)
  213.  
  214. PROCEDURE AccOr;
  215. BEGIN
  216.     Emit;
  217.     Token.Class:=M2OR;
  218. END AccOr;
  219.  
  220. (*--ACCString--Accept a string (for include filenames)-----------------*)
  221.  
  222. PROCEDURE AccString;
  223. BEGIN
  224.     Token.Class:=M2String;
  225. END AccString;
  226.  
  227. (*--ACCString--Accept a single quoted string --------------------------*)
  228.  
  229. PROCEDURE AccStr;
  230. BEGIN
  231.     Token.Class:=M2Str;
  232. END AccStr;
  233.  
  234. (*--ACCCH--Accept any charactor----------------------------------------*)
  235.  
  236. PROCEDURE Accch;
  237. BEGIN
  238.     Emit;
  239.     Token.Class:=M2ch;
  240. END Accch;
  241.  
  242. (*--ACCEOF--Accept EOF condition---------------------------------------*)
  243.  
  244. PROCEDURE AccEOF;
  245. BEGIN
  246.     Token.Class:=M2EOF;
  247. END AccEOF;
  248.  
  249. (*--AccDir--Accept a directive start-----------------------------------*)
  250.  
  251.  
  252.  
  253. PROCEDURE AccDir;
  254. BEGIN
  255.     IF CommNest=0 THEN
  256.         WITH Token DO
  257.             String:='(*$';
  258.             Class:=M2Block;
  259.             Length:=3;
  260.         END;
  261.     ELSE
  262.         State:=STCommSkip;
  263.         INC(CommNest);
  264.     END;
  265. END AccDir;
  266.  
  267. (*--ACCSPACE--Accept a space-------------------------------------------*)
  268.  
  269. PROCEDURE AccSpace;
  270. BEGIN
  271.     PBack:=TRUE ;
  272.     WITH Token DO
  273.         String[0]:=' ';
  274.         Length:=1;
  275.         Class:=M2ch;
  276.     END;
  277. END AccSpace;
  278.  
  279. (*--ACCID--Accept an identifier----------------------------------------*)
  280.  
  281. PROCEDURE AccID;
  282. VAR
  283.     KeyWord: POINTER TO HTEntry;
  284. BEGIN
  285.     PBack:=TRUE ;
  286.     WITH Token DO
  287.         String[Length]:=ASCII.NUL;
  288.         KeyWord:=HashTab.Search(HT,String);
  289.         IF KeyWord # NIL THEN
  290.             Class:=KeyWord^.KWType;
  291.         ELSE
  292.             Class:=M2ID;
  293.         END;
  294.     END;
  295. END AccID;
  296.  
  297. (************************************************************************)
  298. (*----------------------------------------------------------------------*)
  299. (*  GETBSU      Gets the next Basic Syntactic Unit from the source      *)
  300. (*              file.  This is the driver of the Finite State Machine.  *)
  301. (*----------------------------------------------------------------------*)
  302.  
  303. PROCEDURE GetBSU;
  304.  
  305. VAR
  306.     Delta: StateTabEntry;
  307. BEGIN
  308.     Token.Length:=0;
  309.     State:=STStart;
  310.     WITH Delta DO
  311.         WHILE State # STTerm DO
  312.             IF NOT PBack THEN
  313.                 ch:=FIO.ReadChar(SourceFile);
  314.             END;
  315.             PBack:=FALSE;
  316.             Delta:=Transitions[State,CharClass[ch]];
  317.             State:=NextState;
  318.             Action();
  319.         END;
  320.     END;
  321.     WITH Token DO
  322.         String[Length]:=ASCII.NUL;
  323.     END;
  324. END GetBSU;
  325.  
  326. (*----------------------------------------------------------------------*)
  327. (*  LAMBDA      Fills in lambda transitions for finite state machine    *)
  328. (*                                                                      *)
  329. (*  PARAMETERS  State - the state to initialize                         *)
  330. (*              next  - the next state to visit                         *)
  331. (*              act   - the action to take                              *)
  332. (*                                                                      *)
  333. (*  CALLED BY   Main initialization code                                *)
  334. (*----------------------------------------------------------------------*)
  335.  
  336. PROCEDURE Lambda(State,next: States; act: PROC);
  337.  
  338. VAR
  339.     chclass: Alphabet;              (* Counter used for Lambda defs *)
  340. BEGIN
  341.     FOR chclass := FirstCh TO LastCh DO
  342.         Transitions[State,chclass].NextState:=next;
  343.         Transitions[State,chclass].Action :=act;
  344.     END;
  345. END Lambda;
  346.  
  347. (************************************************************************)
  348. (*  Lots and Lots of Initialization code for Lexical Analyzer           *)
  349. (************************************************************************)
  350.  
  351. BEGIN
  352.     PBack:=FALSE;
  353.     CommNest:=0;
  354.     IncludeLevel:=0;
  355.     StripFlag:=TRUE;
  356.     SourceFile:=FIO.INPUT;
  357.     DestFile:=FIO.OUTPUT;
  358.  
  359. (*----------------------------------------------------------------------*)
  360. (* Set up the strings for the lexical units                             *)
  361. (*----------------------------------------------------------------------*)
  362.  
  363.     Strings[M2IF] := "IF";
  364.     Strings[M2THEN] := "THEN";
  365.     Strings[M2ELSIF] := "ELSIF";
  366.     Strings[M2ELSE] := "ELSE";
  367.     Strings[M2END] := "END";
  368.     Strings[M2DEFINE] := "DEFINE";
  369.     Strings[M2UNDEF] := "UNDEF";
  370.     Strings[M2INCLUDE] := "INCLUDE";
  371.     Strings[M2MACRO] := "MACRO";
  372.     Strings[M2ENDM] := "ENDM";
  373.     Strings[M2LINE] := "LINE";
  374.     Strings[M2SPACE] := "SPACE";
  375.     Strings[M2STRIP] := "STRIP";
  376.     Strings[M2NOSTRIP] := "NOSTRIP";
  377.     Strings[M2AND] := "AND";
  378.     Strings[M2OR] := "OR";
  379.     Strings[M2NOT] := "NOT";
  380.     Strings[M2ID] := "ID";
  381.     Strings[M2RParen] := "RParen";
  382.     Strings[M2LParen] := "LParen";
  383.     Strings[M2AtSign] := "AtSign";
  384.     Strings[M2Comma] := "Comma";
  385.     Strings[M2ch] := "ch";
  386.     Strings[M2String] := "String";
  387.     Strings[M2Str] := "Str";
  388.     Strings[M2KillArg] := "KillArg";(* not a real token! *)
  389.     Strings[M2EOF] := "EOF";
  390.  
  391. (*----------------------------------------------------------------------*)
  392. (* Populate the Hash table.                                             *)
  393. (*----------------------------------------------------------------------*)
  394.  
  395.     HashTab.Create(HT,31);
  396.     FOR token:=MIN(Lexicals) TO M2NOT DO
  397.         KeyWords[token].KWType:=token;
  398.         KeyWords[token].KW:=SYSTEM.ADR(Strings[token]);
  399.         HashTab.Insert(HT,SYSTEM.ADR(KeyWords[token]));
  400.     END;
  401.  
  402. (*----------------------------------------------------------------------*)
  403. (* Each ASCII charactor falls into a distinct classification in order   *)
  404. (* to cut down the size of the State-Change tables for the FSM.         *)
  405. (*----------------------------------------------------------------------*)
  406.  
  407.     FOR ch:=MIN(CHAR) TO MAX(CHAR) DO
  408.         CharClass[ch]:=CHNoClass;
  409.     END;
  410.     CharClass[ASCII.HT]:=CHSpace;
  411.     CharClass[ASCII.LF]:=CHEOLN;
  412.     CharClass[ASCII.VT]:=CHEOLN;
  413.     CharClass[ASCII.FF]:=CHEOLN;
  414.     CharClass[ASCII.CR]:=CHEOLN;
  415.     CharClass[ASCII.FS]:=CHEOF;
  416.     CharClass[' ']:=CHSpace;
  417.     CharClass['"']:=CHDQuote;
  418.     CharClass['$']:=CHDollar;
  419.     CharClass['&']:=CHAnd;
  420.     CharClass[47C]:=CHSQuote;
  421.     CharClass['(']:=CHLParen;
  422.     CharClass[')']:=CHRParen;
  423.     CharClass['*']:=CHStar;
  424.     CharClass[',']:=CHComma;
  425.     FOR ch:='0' TO '9' DO
  426.         CharClass[ch]:=CHDigit;
  427.     END;
  428.     CharClass['@']:=CHAtSign;
  429.     FOR ch:='A' TO 'Z' DO
  430.         CharClass[ch]:=CHLetter;
  431.     END;
  432.     CharClass[134C]:=CHBSlash;
  433.     CharClass['_']:=CHLetter;
  434.     FOR ch:='a' TO 'z' DO
  435.         CharClass[ch]:=CHLetter;
  436.     END;
  437.     CharClass['|']:=CHOr;
  438.     CharClass['~']:=CHNot;
  439.  
  440. (*----------------------------------------------------------------------*)
  441. (*  Define the transitions for the Finite State Automata.               *)
  442. (*----------------------------------------------------------------------*)
  443. (*  For each states, the transitions and imbedded actions are defined   *)
  444. (*  using the following convention.                                     *)
  445. (*                                                                      *)
  446. (*      (1)  The lambda transition is defined.                          *)
  447. (*                                                                      *)
  448. (*      (2)  Meaningful (non-Lambda) transitions are then defined.      *)
  449. (*----------------------------------------------------------------------*)
  450.  
  451. (************************************************************************)
  452. (*                      START STATE                                     *)
  453. (************************************************************************)
  454.  
  455.     Lambda(STStart,STTerm,Accch);
  456.  
  457.     Transitions[STStart,CHLetter].NextState :=STID;
  458.     Transitions[STStart,CHLetter].Action :=Emit;
  459.  
  460.     Transitions[STStart,CHEOF].NextState :=STTerm;
  461.     Transitions[STStart,CHEOF].Action :=AccEOF;
  462.  
  463.     Transitions[STStart,CHEOLN].NextState :=STStart;
  464.     Transitions[STStart,CHEOLN].Action :=LineEcho;
  465.  
  466.     Transitions[STStart,CHDQuote].NextState :=STString;
  467.     Transitions[STStart,CHDQuote].Action :=Nothing;
  468.  
  469.     Transitions[STStart,CHSQuote].NextState :=STStr;
  470.     Transitions[STStart,CHSQuote].Action :=Nothing;
  471.  
  472.     Transitions[STStart,CHComma].NextState :=STTerm;
  473.     Transitions[STStart,CHComma].Action :=AccComma;
  474.  
  475.     Transitions[STStart,CHLParen].NextState :=STLParen;
  476.     Transitions[STStart,CHLParen].Action :=Emit;
  477.  
  478.     Transitions[STStart,CHRParen].NextState :=STTerm;
  479.     Transitions[STStart,CHRParen].Action :=AccRParen;
  480.  
  481.     Transitions[STStart,CHComma].NextState :=STTerm;
  482.     Transitions[STStart,CHComma].Action :=AccComma;
  483.  
  484.     Transitions[STStart,CHOr].NextState :=STTerm;
  485.     Transitions[STStart,CHOr].Action :=AccOr;
  486.  
  487.     Transitions[STStart,CHAnd].NextState :=STTerm;
  488.     Transitions[STStart,CHAnd].Action :=AccAnd;
  489.  
  490.     Transitions[STStart,CHNot].NextState :=STTerm;
  491.     Transitions[STStart,CHNot].Action :=AccNot;
  492.  
  493.     Transitions[STStart,CHAtSign].NextState :=STTerm;
  494.     Transitions[STStart,CHAtSign].Action :=AccAtSign;
  495.  
  496.     Transitions[STStart,CHSpace].NextState :=STSkipSpaces;
  497.     Transitions[STStart,CHSpace].Action :=Nothing;
  498.  
  499. (************************************************************************)
  500. (*                      IDENTIFIER?                                     *)
  501. (************************************************************************)
  502.  
  503.     Lambda(STID,STTerm,AccID);
  504.  
  505.     Transitions[STID,CHLetter].NextState :=STID;
  506.     Transitions[STID,CHLetter].Action :=Emit;
  507.  
  508.     Transitions[STID,CHDigit].NextState :=STID;
  509.     Transitions[STID,CHDigit].Action :=Emit;
  510.  
  511. (************************************************************************)
  512. (*                        SKIP WHITESPACE                               *)
  513. (************************************************************************)
  514.  
  515.     Lambda(STSkipSpaces,STTerm,AccSpace);
  516.  
  517.     Transitions[STSkipSpaces,CHSpace].NextState:=STSkipSpaces;
  518.     Transitions[STSkipSpaces,CHSpace].Action :=Nothing;
  519.  
  520.     Transitions[STSkipSpaces,CHEOLN].NextState :=STStart;
  521.     Transitions[STSkipSpaces,CHEOLN].Action :=LineEcho;
  522.  
  523.     Transitions[STSkipSpaces,CHEOF].NextState :=STTerm;
  524.     Transitions[STSkipSpaces,CHEOF].Action :=AccEOF;
  525.  
  526. (************************************************************************)
  527. (*               DOUBLE-QUOTED STRING LITERAL BEGINNING                 *)
  528. (************************************************************************)
  529.  
  530.     Lambda(STString,STString,Emit);
  531.  
  532.     Transitions[STString,CHEOLN].NextState :=STString;
  533.     Transitions[STString,CHEOLN].Action :=Error;
  534.  
  535.     Transitions[STString,CHEOF].NextState :=STString;
  536.     Transitions[STString,CHEOF].Action :=Error;
  537.  
  538.     Transitions[STString,CHDQuote].NextState :=STTerm;
  539.     Transitions[STString,CHDQuote].Action :=AccString;
  540.  
  541.     Transitions[STString,CHBSlash].NextState :=STEQuote;
  542.     Transitions[STString,CHBSlash].Action :=Emit;
  543.  
  544. (************************************************************************)
  545. (*                 BACKSTROKE IN DOUBLE-QUOTED STRING                   *)
  546. (************************************************************************)
  547.  
  548.     Lambda(STEQuote,STString,Emit);
  549.  
  550.     Transitions[STEQuote,CHEOLN].NextState :=STEQuote;
  551.     Transitions[STEQuote,CHEOLN].Action :=Error;
  552.  
  553.     Transitions[STEQuote,CHEOF].NextState :=STEQuote;
  554.     Transitions[STEQuote,CHEOF].Action :=Error;
  555.  
  556. (************************************************************************)
  557. (*               SINGLE-QUOTED STRING LITERAL BEGINNING                 *)
  558. (************************************************************************)
  559.  
  560.     Lambda(STStr,STStr,Emit);
  561.  
  562.     Transitions[STStr,CHEOLN].NextState :=STStr;
  563.     Transitions[STStr,CHEOLN].Action :=Error;
  564.  
  565.     Transitions[STStr,CHEOF].NextState :=STStr;
  566.     Transitions[STStr,CHEOF].Action :=Error;
  567.  
  568.     Transitions[STStr,CHSQuote].NextState :=STTerm;
  569.     Transitions[STStr,CHSQuote].Action :=AccStr;
  570.  
  571.     Transitions[STStr,CHBSlash].NextState :=STSQuote;
  572.     Transitions[STStr,CHBSlash].Action :=Emit;
  573.  
  574. (************************************************************************)
  575. (*                 BACKSTROKE IN SINGLE-QUOTED STRING                   *)
  576. (************************************************************************)
  577.  
  578.     Lambda(STSQuote,STStr,Emit);
  579.  
  580.     Transitions[STSQuote,CHEOLN].NextState :=STSQuote;
  581.     Transitions[STSQuote,CHEOLN].Action :=Error;
  582.  
  583.     Transitions[STSQuote,CHEOF].NextState :=STSQuote;
  584.     Transitions[STSQuote,CHEOF].Action :=Error;
  585.  
  586. (************************************************************************)
  587. (*                      LEFT PARENTHESIS                                *)
  588. (************************************************************************)
  589.  
  590.     Lambda(STLParen,STTerm,AccLParen);
  591.  
  592.     Transitions[STLParen,CHStar].NextState :=STCommBeg;
  593.     Transitions[STLParen,CHStar].Action :=UnEmit;
  594.  
  595. (************************************************************************)
  596. (*                      COMMENT BEGINING                                *)
  597. (************************************************************************)
  598.  
  599.     Lambda(STCommBeg,STCommSkip,InComment);
  600.  
  601.     Transitions[STCommBeg,CHLParen].NextState :=STCommNest;
  602.     Transitions[STCommBeg,CHLParen].Action :=InComment;
  603.  
  604.     Transitions[STCommBeg,CHDollar].NextState :=STTerm;
  605.     Transitions[STCommBeg,CHDollar].Action :=AccDir;
  606.  
  607.     Transitions[STCommBeg,CHEOLN].NextState :=STCommLine;
  608.     Transitions[STCommBeg,CHEOLN].Action :=LineEcho;
  609.  
  610.     Transitions[STCommBeg,CHStar].NextState :=STCommEnd;
  611.     Transitions[STCommBeg,CHStar].Action :=InComment;
  612.  
  613. (************************************************************************)
  614. (*                 EOLN AT BEGINNING OF COMMENT                         *)
  615. (************************************************************************)
  616.  
  617.     Lambda(STCommLine,STCommSkip,InComment);
  618.  
  619.     Transitions[STCommLine,CHLParen].NextState :=STCommNest;
  620.     Transitions[STCommLine,CHLParen].Action :=InComment;
  621.  
  622.     Transitions[STCommLine,CHEOLN].NextState :=STCommLine;
  623.     Transitions[STCommLine,CHEOLN].Action :=LineEcho;
  624.  
  625.     Transitions[STCommLine,CHStar].NextState :=STCommEnd;
  626.     Transitions[STCommLine,CHStar].Action :=InComment;
  627.  
  628. (************************************************************************)
  629. (*                      COMMENT BEING SKIPPED                           *)
  630. (************************************************************************)
  631.  
  632.     Lambda(STCommSkip,STCommSkip,EchoComment);
  633.  
  634.     Transitions[STCommSkip,CHEOF].NextState :=STCommSkip;
  635.     Transitions[STCommSkip,CHEOF].Action :=Error;
  636.  
  637.     Transitions[STCommSkip,CHEOLN].NextState :=STCommSkip;
  638.     Transitions[STCommSkip,CHEOLN].Action :=LineEcho;
  639.  
  640.     Transitions[STCommSkip,CHStar].NextState :=STCommEnd;
  641.     Transitions[STCommSkip,CHStar].Action :=EchoComment;
  642.  
  643.     Transitions[STCommSkip,CHLParen].NextState :=STCommNest;
  644.     Transitions[STCommSkip,CHLParen].Action :=EchoComment;
  645.  
  646. (************************************************************************)
  647. (*                      NESTED COMMENT POSSIBLY?                        *)
  648. (************************************************************************)
  649.  
  650.     Lambda(STCommNest,STCommSkip,EchoComment);
  651.  
  652.     Transitions[STCommNest,CHEOF].NextState :=STCommNest;
  653.     Transitions[STCommNest,CHEOF].Action :=Error;
  654.  
  655.     Transitions[STCommNest,CHStar].NextState :=STCommBeg;
  656.     Transitions[STCommNest,CHStar].Action :=EchoComment;
  657.  
  658.     Transitions[STCommNest,CHLParen].NextState :=STCommNest;
  659.     Transitions[STCommNest,CHLParen].Action :=EchoComment;
  660.  
  661.     Transitions[STCommNest,CHEOLN].NextState :=STCommSkip;
  662.     Transitions[STCommNest,CHEOLN].Action :=LineEcho;
  663.  
  664. (************************************************************************)
  665. (*                      COMMENT ENDING (just read * )                   *)
  666. (************************************************************************)
  667.  
  668.     Lambda(STCommEnd,STCommSkip,EchoComment);
  669.  
  670.     Transitions[STCommEnd,CHEOF].NextState :=STCommEnd;
  671.     Transitions[STCommEnd,CHEOF].Action :=Error;
  672.  
  673.     Transitions[STCommEnd,CHEOLN].NextState :=STCommSkip;
  674.     Transitions[STCommEnd,CHEOLN].Action :=LineEcho;
  675.  
  676.     Transitions[STCommEnd,CHRParen].NextState :=STCommSkip;
  677.     Transitions[STCommEnd,CHRParen].Action :=OutComment;
  678.  
  679.     Transitions[STCommEnd,CHStar].NextState :=STCommEnd;
  680.     Transitions[STCommEnd,CHStar].Action :=EchoComment;
  681.  
  682. (************************************************************************)
  683. (*                      TERMINATION STATE                               *)
  684. (************************************************************************)
  685.  
  686.     Lambda(STTerm,STTerm,Error);
  687.  
  688. END FSM.
  689.