 --<skeleton.nw>80
IMPLEMENTATION MODULE $M;

IMPORT SYSTEM;
FROM YLexicalAnalyzer IMPORT AbstractCharStream;

------------------------------------------
   CLASS $M;
     INHERITS YLexicalAnalyzer;

   
 --<skeleton.nw>311
VAR
  TheImage: ARRAY OF CHAR;
 --<skeleton.nw>323
TheMaximumLength,
TheCurrentLength: INTEGER;
 --<skeleton.nw>332
TheCurrentIncarnation: INTEGER;
 --<skeleton.nw>349
AtomicToken: INTEGER;
ArrayTokens: ARRAY OF INTEGER;
ArrayArrayTokens: ARRAY OF ARRAY OF INTEGER;
 --<skeleton.nw>368
ResultsArray: ONCE ARRAY OF ARRAY OF INTEGER;
 --<skeleton.nw>375
Burned: ARRAY OF BOOLEAN;
 --<skeleton.nw>380
TheBackTrackLevel: INTEGER;
 --<skeleton.nw>384
EofReached: BOOLEAN;


 --<skeleton.nw>91
   CONST
     ErrorState = -9876541;
     MaxCodes = 16;

   
 --<skeleton.nw>387
REDEFINE METHOD CREATE;
  CONST
    MaxLen = 256*64;
  BEGIN
  TheBackTrackLevel := BACKTRACKLEVEL;
  BASE;
  
 --<skeleton.nw>401
IF ($B > 0) OR DYNAMICBACKTRACKLEVEL THEN
  IF ResultsArray = VOID THEN
    $I
    END;
  END;
 --<skeleton.nw>394
  IF ($B > 1) OR DYNAMICBACKTRACKLEVEL THEN
    ArrayArrayTokens.CREATE (MaxLen);
    END;
  
 --<skeleton.nw>415
IF ($B = 2) OR DYNAMICBACKTRACKLEVEL THEN
  Burned.CREATE (LASTTOKEN);
  END;
 --<skeleton.nw>398
  END CREATE;

 --<skeleton.nw>97
   
 --<skeleton.nw>357
REDEFINE METHOD CurrentToken: INTEGER;
  BEGIN
  RESULT := AtomicToken;
  END CurrentToken;
 --<skeleton.nw>98
   
 --<skeleton.nw>644
REDEFINE METHOD BackTrack;
  VAR
    i, j: INTEGER;
    p: ARRAY OF INTEGER;
    Found: BOOLEAN;
  BEGIN
  IF AtomicToken <> ERROR THEN
 --<skeleton.nw>655
IF $B = 0 THEN
  AtomicToken := ERROR;
 ELSE
  
 --<skeleton.nw>704
TheCurrentIncarnation := TheCurrentIncarnation + 1;
IF TheCurrentIncarnation < ArrayTokens.SIZE THEN
  AtomicToken := ArrayTokens[TheCurrentIncarnation];
 ELSIF $B = 1 THEN
  AtomicToken := ERROR;
 ELSE
  
 --<skeleton.nw>717
TheCurrentLength := TheCurrentLength - 1;
TheCurrentIncarnation := 0;
WHILE (TheCurrentLength >= 0) AND
      (ArrayArrayTokens[TheCurrentLength] = VOID) DO
  TheCurrentLength := TheCurrentLength - 1;
  END;
IF TheCurrentLength < 0 THEN
  AtomicToken := ERROR;
 ELSE
  ArrayTokens := ArrayArrayTokens [TheCurrentLength];
  AtomicToken := ArrayTokens [0];
  END;
 --<skeleton.nw>711
  END;
 --<skeleton.nw>659
  END;
END;
 --<skeleton.nw>692
IF ($B >= 2) THEN
--  IF (AtomicToken = SKIP) AND (TheCurrentLength <> TheMaximumLength) THEN
  IF (AtomicToken = SKIP) THEN
    TheCurrentIncarnation := 0;
    Advance;
   ELSIF $B = 2 THEN
    
 --<skeleton.nw>742
IF AtomicToken <> ERROR THEN
  IF AtomicToken < 0 THEN
    Burned[-AtomicToken] := TRUE;
    BackTrack;
   ELSIF Burned[AtomicToken] THEN
    BackTrack;
   ELSE
    Burned[AtomicToken] := TRUE;
    END;
  ASSERT AtomicToken >= 0;
  END;
 --<skeleton.nw>699
    END;
  END;
END BackTrack;
 --<skeleton.nw>99
   
   $S
   
   
 --<skeleton.nw>432
VAR
  State,
  AnalyzedSize: INTEGER;
    
REDEFINE METHOD ReadCurrentToken;
  VAR
    GoOn: BOOLEAN;
    Ch: INTEGER;
    OldPos: INTEGER;
  BEGIN
  IF $B = 2 THEN
    
 --<skeleton.nw>487
FOR i := 0 TO Burned.SIZE - 1 DO
  Burned[i] := FALSE;
  END;
 --<skeleton.nw>444
    END;
  TheCurrentLength := 0;
  TheCurrentIncarnation := 0;
  State := 0;
  AnalyzedSize := 0;
  
 --<skeleton.nw>495
OldPos := GetCharStream.Position;
 --<skeleton.nw>450
  GoOn := TRUE;
  AtomicToken := ERROR;
  WHILE GoOn DO
    
 --<skeleton.nw>504
IF EofReached THEN
  State := ErrorState;
 ELSE
  Ch := GetCharStream.Read;
  IF Ch = EofChar THEN
    EofReached := TRUE;
    END;
  END;
 --<skeleton.nw>454
    IF $B > 0 THEN
      
 --<skeleton.nw>517
IF (State >= 0) AND (ResultsArray[State] <> VOID) THEN
  TheCurrentLength := AnalyzedSize;
  IF $B = 1 THEN
    ArrayTokens := ResultsArray[State];
    AtomicToken := ArrayTokens[0];
   ELSIF $B > 1 THEN
    ArrayTokens := ResultsArray[State];
    ArrayArrayTokens[TheCurrentLength] := ArrayTokens;
    AtomicToken := ArrayTokens[0];
    END;
 ELSIF $B > 1 THEN
  ArrayArrayTokens[AnalyzedSize] := VOID;
  END;
 --<skeleton.nw>456
      END;
    CASE State OF
      ErrorState:
       
 --<skeleton.nw>542
GoOn := FALSE;
IF (TheCurrentLength = 0) THEN
  IF EofReached THEN
    AtomicToken := EOF;
   ELSE
    TheCurrentLength := 1;
    AtomicToken := ERROR;
    END;
  END;
 --<skeleton.nw>460
       END;

      $A  -- Nested cases, generated automatically

      END; -- Case
    AnalyzedSize := AnalyzedSize + 1;
    END; -- While
  
 --<skeleton.nw>498
IF GetCharStream.Position <> OldPos THEN
  EofReached := FALSE;
  GetCharStream.SetPosition(OldPos);
  END;
 --<skeleton.nw>468
  END ReadCurrentToken;
 --<skeleton.nw>103
   
 --<skeleton.nw>591
REDEFINE METHOD Advance;
  VAR
    GoOn: BOOLEAN;
    i: INTEGER;
  BEGIN
  IF TheCurrentLength > 0 THEN
    GetCharStream.Advance (TheCurrentLength);
    END;
  GoOn := TRUE;
  TheImage := VOID;
  WHILE GoOn DO
    ReadCurrentToken;
    IF AtomicToken = SKIP THEN
      GetCharStream.Advance (TheCurrentLength);
     ELSE
      GoOn := FALSE;
      IF $B > 1 THEN
        TheMaximumLength := TheCurrentLength;
        END;
      END;
    END;
  
 --<skeleton.nw>621
IF $B = 2 THEN
  Burned[AtomicToken] := TRUE;
  END;
 --<skeleton.nw>613
  ASSERT AtomicToken >= 0;
  END Advance;
 --<skeleton.nw>104
   
 --<skeleton.nw>629
REDEFINE METHOD ResetMaximumLength;
  BEGIN
  IF $B > 1 THEN
    TheCurrentLength := TheMaximumLength;
    TheCurrentIncarnation := 0;
    END;
  END ResetMaximumLength;
 --<skeleton.nw>105
   
 --<skeleton.nw>759
REDEFINE METHOD Image: ARRAY OF CHAR;
  BEGIN
  IF (TheImage = VOID) OR (TheImage.SIZE <> TheCurrentLength) THEN
    TheImage := GetCharStream.GetImage (GetCharStream.Position,
                       TheCurrentLength);
    ASSERT (TheImage = VOID) OR (TheImage.SIZE = TheCurrentLength);
    END;
  RESULT := TheImage;
  END Image;
 --<skeleton.nw>106
   
 --<skeleton.nw>770
REDEFINE METHOD CurrentLength: INTEGER;
  BEGIN
  RESULT := TheCurrentLength;
  END CurrentLength;
 --<skeleton.nw>776
REDEFINE METHOD CurrentPosition: INTEGER;
  BEGIN
  RESULT := GetCharStream.Position;
  END CurrentPosition;
 --<skeleton.nw>782
REDEFINE METHOD LastToken: INTEGER;
  BEGIN
  RESULT := LASTTOKEN;
  END LastToken;
 --<skeleton.nw>788
REDEFINE METHOD CurrentIncarnation: INTEGER;
  BEGIN
  RESULT := TheCurrentIncarnation;
  END CurrentIncarnation;
 --<skeleton.nw>794
REDEFINE METHOD SetCurrentPosition (Pos: INTEGER);
  BEGIN
  IF Pos <> CurrentPosition THEN
    GetCharStream.SetPosition (Pos);
    TheImage := VOID;
    END;
  END SetCurrentPosition;
 --<skeleton.nw>107
   
 --<skeleton.nw>808
REDEFINE METHOD SetCurrentIncarnation (Carn: INTEGER);
  BEGIN
  IF $B = 2 THEN
    WHILE (TheCurrentIncarnation < Carn) AND (AtomicToken <> ERROR) DO
      BackTrack;
      END;
   ELSE
    TheCurrentIncarnation := Carn;
    END;
  END SetCurrentIncarnation;
 --<skeleton.nw>820
REDEFINE METHOD SetCurrentLength (Len: INTEGER);
  BEGIN
  IF $B = 2 THEN
    ASSERT (TheCurrentLength >= Len) OR EofReached;
    WHILE (TheCurrentLength > Len) AND (AtomicToken <> ERROR) DO
      BackTrack;
      END;
   ELSE
    TheCurrentLength := Len;
    END;
  END SetCurrentLength;
 --<skeleton.nw>835
REDEFINE METHOD ReSync (Pos, Len, Carn: INTEGER);
  BEGIN
  IF (Pos <> CurrentPosition) OR (Len <> CurrentLength) OR
     (Carn <> CurrentIncarnation) THEN
    GetCharStream.SetPosition (Pos);
    TheImage := VOID;
    ReadCurrentToken;
    IF $B=2 THEN
      Burned[AtomicToken] := TRUE;
      END;
    SetCurrentLength (Len);
    SetCurrentIncarnation (Carn);
    END;
  END ReSync;

 --<skeleton.nw>109
   
 --<skeleton.nw>578
REDEFINE METHOD AttachCharStream (CharStream: AbstractCharStream);
  BEGIN
  BASE(CharStream);
  TheCurrentLength := 0;
  EofReached := FALSE;
  TheImage := VOID;
  END AttachCharStream;

 --<skeleton.nw>111
   
 --<skeleton.nw>558
REDEFINE METHOD TokenImage (TokenNr: INTEGER): ARRAY OF CHAR;
  BEGIN
  CASE TokenNr OF
    ERROR:
      RESULT := "ERROR";
      END;
    EOF:
      RESULT := "EOF";
      END;
$T
   ELSE
    RESULT := "<Unknown>";
    END;
  END TokenImage;

 --<skeleton.nw>113
   END $M;

END $M;
