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