IMPLEMENTATION MODULE YaflCreator;

FROM CGCode IMPORT CCodeGeneratorCreator;
IMPORT Space;
   CLASS ObjectCreator;
   
     METHOD CreateDefinitionModule: DefinitionModule;
       BEGIN
       RESULT.CREATE;
       END CreateDefinitionModule;
 
     METHOD CreateImplementationModule: ImplementationModule;
       BEGIN
       RESULT.CREATE;
       END CreateImplementationModule;
 
     METHOD CreateClassDefinition (LineNr, ColNr: INTEGER):
                                               ClassDefinition;
      VAR
        Tmp: InstClassDefinition;
      BEGIN
      Tmp.CREATE(LineNr, ColNr);
      RESULT := Tmp;
      END CreateClassDefinition;

    METHOD CreateClassImplementation (LineNr, ColNr: INTEGER):
                                               ClassImplementation;
      BEGIN
      RESULT.CREATE(LineNr, ColNr);
      END CreateClassImplementation;

    METHOD CreateMethodDefinition (LineNr, ColNr: INTEGER):
                                               MethodDefinition;
      BEGIN
      RESULT.CREATE(LineNr, ColNr);
      END CreateMethodDefinition;

    METHOD CreateMethodImplementation (LineNr, ColNr: INTEGER):
                                               MethodImplementation;
      BEGIN
      RESULT.CREATE(LineNr, ColNr);
      END CreateMethodImplementation;

    METHOD CreateImportList(LineNr, ColNr: INTEGER): ImportList;
      BEGIN
      RESULT.CREATE(LineNr, ColNr);
      END CreateImportList;

    METHOD CreateDesigElement (LineNr, ColNr, Context: INTEGER): DesigElement; 
      BEGIN
      RESULT.CREATE (LineNr, ColNr, Context);
      END CreateDesigElement;
      
    METHOD CreateDesig (LineNr, ColNr, Context: INTEGER): Desig; 
      BEGIN
      RESULT.CREATE (LineNr, ColNr, Context);
      END CreateDesig;
      
    METHOD CreateDataItem (Id: Ident;
                           TheType: Type;
                           ReadOnly,
                           Once: BOOLEAN): SingleDataItem;
      BEGIN
      RESULT.CREATE (Id, TheType, ReadOnly, Once);
      END CreateDataItem;
                                 
    METHOD CreatePreCondition (LineNr, ColNr: INTEGER): PreCondition;                       
      BEGIN
      RESULT.CREATE(LineNr, ColNr);
      END CreatePreCondition;
      
    METHOD CreatePostCondition (LineNr, ColNr: INTEGER): PostCondition;                       
      BEGIN
      RESULT.CREATE(LineNr, ColNr);
      END CreatePostCondition;
      
    METHOD CreateClassInvariant (LineNr, ColNr: INTEGER): ClassInvariant;
      BEGIN
      RESULT.CREATE(LineNr, ColNr);
      END CreateClassInvariant;
      
    METHOD CreateLoopInvariant (LineNr, ColNr: INTEGER): LoopInvariant;
      BEGIN
      RESULT.CREATE(LineNr, ColNr);
      END CreateLoopInvariant;
      
    METHOD CreateOldExpression (LineNr, ColNr, Context: INTEGER): OldExpression;                       
      BEGIN
      RESULT.CREATE(LineNr, ColNr, Context);
      END CreateOldExpression;
      
    METHOD CreateAssertionExpressionList: AssertionExpressionList;                       
      BEGIN
      RESULT.CREATE;
      END CreateAssertionExpressionList;

    METHOD CreatePostExpressionList: PostExpressionList;                       
      BEGIN
      RESULT.CREATE;
      END CreatePostExpressionList;

    METHOD CreateQuantifier (LineNr, ColNr, Context: INTEGER): Quantifier;                       
	  BEGIN
      RESULT.CREATE (LineNr, ColNr, Context);
      END CreateQuantifier;
      
    METHOD CreateSetSpecification (LineNr, ColNr: INTEGER): SetSpecification;                       
	  BEGIN
      RESULT.CREATE (LineNr, ColNr);
      END CreateSetSpecification;
      
    METHOD CreateIntegerLiteral(LineNr, ColNr, Context, Value: INTEGER):
                                  IntegerLiteral;
      BEGIN
      RESULT.CREATE (LineNr, ColNr, Context, Value);
      END CreateIntegerLiteral;
                                        
    METHOD CreateRealLiteral(LineNr, ColNr, Context: INTEGER;
                             Value: REAL): RealLiteral;
      BEGIN
      RESULT.CREATE (LineNr, ColNr, Context, Value);
      END CreateRealLiteral;
    
    METHOD CreateStringLiteral(LineNr, ColNr, Context: INTEGER;
                           Value: ARRAY OF CHAR): StringLiteral;
      BEGIN
      RESULT.CREATE (LineNr, ColNr, Context, Value);
      END CreateStringLiteral;
                                        
  END ObjectCreator;
--------------------------------------
  CLASS PragmaCreator;
 
    VAR
      Keywords: ONCE ARRAY OF ARRAY OF CHAR;
    CONST
      CallBack = 0;
      Include = 1;
      InlineConst = 2;
      KeepFields = 3;
      NoKeepFields = 4;
      VarType = 5;
      Error = 6;
      Warning = 7;
      Obsolete = 8;
      InlineMethod = 9;
      Publish = 10;

    METHOD CreatePragma (Keyword: ARRAY OF CHAR;
                         LineNr, ColNr: INTEGER): Pragma;
      VAR
        Found: INTEGER; 
        CBPragma: CallBackPragma;
        IncPragma: IncludePragma;
        InConst: InlineConstPragma;
        KeepField: KeepFieldsPragma;
        AttrType: VarTypePragma;
        Err: ErrorPragma;
        Obsol: ObsoletePragma;
        InMethod: InlineMethodPragma;
        Publ: PublishPragma;
      BEGIN
      Found := -1;
      FOR i := 0 TO Keywords.SIZE - 1 WHILE Found < 0 DO
        IF Keyword = Keywords [i] THEN
          Found := i;
          END;
        END;
      CASE Found OF              
        CallBack:
          CBPragma.CREATE (LineNr, ColNr);
          RESULT := CBPragma;
          END;
        Include:
          IncPragma.CREATE (LineNr, ColNr);
          RESULT := IncPragma;
          END;
        InlineConst:
          InConst.CREATE (LineNr, ColNr);
          RESULT := InConst;
          END;
        NoKeepFields, KeepFields:
          KeepField.CREATE (LineNr, ColNr, Found = KeepFields);
          RESULT := KeepField;
          END;
        VarType:
          AttrType.CREATE (LineNr, ColNr);
          RESULT := AttrType;
          END;
        Error, Warning:
          Err.CREATE (LineNr, ColNr, Found = Error);
          RESULT := Err;
          END;
        Obsolete:
          Obsol.CREATE (LineNr, ColNr);
          RESULT := Obsol;
          END;
        InlineMethod:
          InMethod.CREATE (LineNr, ColNr);
          RESULT := InMethod;
          END;
        Publish:
          Publ.CREATE(LineNr, ColNr);
          RESULT := Publ;
          END;
       ELSE
        -- Default behaviour, do nothing.
        END;
      END CreatePragma;
    
    REDEFINE METHOD CREATE;
    BEGIN    
    IF Keywords = VOID THEN
      Keywords.CREATE (14);
      Keywords [CallBack] := Space.StoreString ("CallBack");
      Keywords [Include] := Space.StoreString ("Include");
      Keywords [InlineConst] := Space.StoreString ("InlineConst");
      Keywords [KeepFields] := Space.StoreString ("KeepFields");
      Keywords [NoKeepFields] := Space.StoreString ("NoKeepFields");
      Keywords [VarType] := Space.StoreString ("VarType");
      Keywords [Error] := Space.StoreString ("Error");
      Keywords [Warning] := Space.StoreString ("Warning");
      Keywords [Obsolete] := Space.StoreString ("Obsolete");
      Keywords [InlineMethod] := Space.StoreString ("InlineMethod");
      Keywords [Publish] := Space.StoreString("Publish");
      END;
    END CREATE;
    
  END PragmaCreator;
--------------------------------------
  CLASS StreamCreator;
    REDEFINE METHOD CREATE;
      BEGIN
      END CREATE;
      
    METHOD CreateStreamLookAhead(Input: InputStream;
                                 KeepComments: BOOLEAN): StreamLookAhead;
      BEGIN
      RESULT.CREATE (Input, KeepComments);
      END CreateStreamLookAhead;
 
   METHOD CreateGC: YaflGC;                                 
      BEGIN
      RESULT.CREATE;
      END CreateGC;

 END StreamCreator;
---------------------------------------
  
  CLASS CodeGeneratorCreator;
  
    REDEFINE METHOD CREATE;
      BEGIN
      END CREATE;
    
    METHOD CreateGC(NT: NonTerminal): GC; 
      BEGIN
      WHAT NT OF
        IN ImplementationModule:
          RESULT := CreateImplModuleCG(TAG); 
          END;
        IN DefinitionModule:
          RESULT := CreateDefModuleCG(TAG); 
          END;
        IN ClassImplementation:
          RESULT := CreateClassImplCG(TAG); 
          END;
        IN InstClassDefinition:
          RESULT := CreateClassDefCG(TAG); 
          END;
        IN MethodImplementation:
          RESULT := CreateMethImplCG(TAG); 
          END;
        IN MethodDefinition:
          RESULT := CreateMethodDefCG(TAG); 
          END;
        IN VirtualClassDecl:
          RESULT := CreateVirtualClassDeclCG(TAG); 
          END;
        IN InstClassDefinition:
          RESULT := CreateInstClassDefCG(TAG); 
          END;
        IN PredefClass:
          RESULT := CreatePredefClassCG(TAG); 
          END;
        IN ImportClause:
          RESULT := CreateImportClauseCG(TAG); 
          END;
        IN ConstDeclaration:
          RESULT := CreateConstDeclCG(TAG); 
          END;
        IN SingleDataItem:
          RESULT := CreateSingleDataItemCG(TAG); 
          END;
        IN PredefMethod:
          RESULT := CreatePredefMethCG(TAG); 
          END;
        IN PreCondition:
          RESULT := CreatePreCondCG(TAG); 
          END;
        IN PostCondition:
          RESULT := CreatePostCondCG(TAG); 
          END;
        IN ClassInvariant:
          RESULT := CreateClassInvCG(TAG); 
          END;
        IN LoopInvariant:
          RESULT := CreateLoopInvCG(TAG); 
          END;
        IN OldExpression:
          RESULT := CreateOldExprCG(TAG); 
          END;
        IN NopStatement:
          RESULT := CreateNopStatementCG(TAG); 
          END;
        IN Assignment:
          RESULT := CreateAssignmentCG(TAG); 
          END;
        IN MethodInvStatement:
          RESULT := CreateMethInvStatCG(TAG); 
          END;
        IN DebugStatement:
          RESULT := CreateDebugStatCG(TAG); 
          END;
        IN AssertStatement:
          RESULT := CreateAssertStatCG(TAG); 
          END;
        IN InLineStatement:
          RESULT := CreateInLineStatCG(TAG); 
          END;
        IN LoopStatement:
          RESULT := CreateLoopStatCG(TAG); 
          END;
        IN IfStatement:
          RESULT := CreateIfStatCG(TAG); 
          END;
        IN IfAlt:
          RESULT := CreateElsIfCG(TAG); 
          END;
        IN CaseStatement:
          RESULT := CreateCaseStatCG(TAG); 
          END;
        IN CaseAlt:
          RESULT := CreateCaseAltCG(TAG); 
          END;
        IN CaseTag:
          RESULT := CreateCaseTagCG(TAG); 
          END;
        IN WhatStatement:
          RESULT := CreateWhatStatCG(TAG); 
          END;
        IN WhatAlt:
          RESULT := CreateWhatAltCG(TAG); 
          END;
        IN WhatTag:
          RESULT := CreateWhatTagCG(TAG); 
          END;
        IN StatementList:
          RESULT := CreateStatListCG(TAG); 
          END;
        IN IntegerLiteral:
          RESULT := CreateIntLiteralCG(TAG); 
          END;
        IN BooleanLiteral:
          RESULT := CreateBooleanLiteralCG(TAG); 
          END;
        IN RealLiteral:
          RESULT := CreateRealLiteralCG(TAG); 
          END;
        IN StringLiteral:
          RESULT := CreateStringLiteralCG(TAG); 
          END;
        IN Void:
          RESULT := CreateVoidLitCG(TAG); 
          END;
        IN Expression:
          RESULT := CreateExpressionCG(TAG); 
          END;
        IN Actual:
          RESULT := CreateActualCG(TAG); 
          END;
        IN InstType:
          RESULT := CreateInstTypeCG(TAG); 
          END;
        IN DesigElement:
          RESULT := CreateDesigElementCG(TAG); 
          END;
        IN Desig:
          RESULT := CreateDesigCG(TAG); 
          END;
        IN Quantifier:
          RESULT := CreateQuantifierCG(TAG);
          END;
        IN SetSpecification:
          RESULT := CreateSetSpecCG(TAG);
          END;
       ELSE
        StdOut.WriteString("CreateGC undefined : " + NT.WhatAmI);    
        StdOut.WriteLn;
        END;  
      END CreateGC;
    
    METHOD WhatAmI: ARRAY OF CHAR;
      BEGIN
      RESULT := "Generic code generation";
      ASSERT FALSE;
      END WhatAmI;
  END CodeGeneratorCreator;            
  
  CLASS CodeGeneratorCreatorList;
    INHERITS List(CodeGeneratorCreator);
   
    END CodeGeneratorCreatorList;

---------------------------------------
    
  ONCE CLASS Creators;
    VAR
      ThePragma: PragmaCreator;
      TheStream: StreamCreator;
      TheObject: ObjectCreator;
      TheGC:     CodeGeneratorCreator; 
    
    REDEFINE METHOD CREATE;
      VAR
        Tmp: CCodeGeneratorCreator;
      BEGIN
      ThePragma.CREATE;
      TheStream.CREATE;
      TheObject.CREATE;
      Tmp.CREATE;
      TheGC := Tmp;
      END CREATE;      
     
    METHOD Pragma: PragmaCreator;
      BEGIN
      RESULT := ThePragma;
      END Pragma;
      
    METHOD Stream: StreamCreator;
      BEGIN
      RESULT := TheStream;
      END Stream;       
      
    METHOD Object: ObjectCreator;
      BEGIN
      RESULT := TheObject;
      END Object;
 
    METHOD DefaultCodeGenerator: CodeGeneratorCreator;
      BEGIN
      RESULT.CREATE;
      END DefaultCodeGenerator;
      
    METHOD CodeGenerator: CodeGeneratorCreator;
      BEGIN
      RESULT := TheGC;
      END CodeGenerator;
      
    METHOD SetPragma (TheCreator: PragmaCreator);
      BEGIN
      ThePragma := TheCreator;
      ASSERT ThePragma <> VOID;
      END SetPragma;
      
    METHOD SetStream (TheCreator: StreamCreator);
      BEGIN
      TheStream := TheCreator;
      ASSERT TheStream <> VOID;
      END SetStream;
      
    METHOD SetObject (TheCreator: ObjectCreator);
      BEGIN
      TheObject := TheCreator;
      ASSERT TheObject <> VOID;
      END SetObject;      

    METHOD SetCodeGenerator (TheCreator: CodeGeneratorCreator);
      BEGIN
      TheGC := TheCreator;
      END SetCodeGenerator;
      
  END Creators;

END YaflCreator;

