{{
 :     
 :  
 :          

            :
            1)    " "
            2)    "^"
            3)    "|"
            4)    "..."
            5)   
            6)        ( X, Y)
            7)   
            8)   -    
            9)  
            10)  
            11)  
            12)   'SUM'  'PROD'
            13)   'i'    'SUM'  'PROD'
}

//     :
//1)  :      .
//          ,    ,
//       ,     ,     .
//       ,      
//           ,     .
//              .
//           , ,
//     ""   .
//
//2)  :   ,  ,       .
//      ,            .
//           ,   
//               
//    (    ).          
//         .        .
//            ,      ,
//          , ,    ,  
//            .
//
//3) :     ,        ,
//     ,        .
//
//
//        F(x), x=(x1,, xn).
//
//      :
//  -    "::="      ;
//  -      (   ),    ,     "<"  ">";
//  -    -  ,    ;
//  -         ,        "|";
//  -     "["  "]" ,        ;
//  -     "{"  "}"    (, 0 );
//  -         "{/"  "/}"        ;
//  -     "("  ")"     ;
//  -     " "  : "< > ( ) |",      .
//  -      
//  -     ,   ,   
//
// :
// <> ::= |||D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|
//             a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
// <> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
// < > ::= {//}
// < > ::= < >.< > |
//                          < >[[.< >]E[-|+]< >] |
//                          .< >[E[-|+]< >]
// <> ::= < > | < >
// < > ::= X(< > | _i | _"("i  < >")")
//     : < >      "i"  
//                   .  SUM  PROD
// < > ::= i
//     : < >     .  SUM  PROD.
// <  > ::= U
//     : <  >   
//                  <  >
// < > ::= <>{<>}[< >]
//     :  < >    
//                   < >, <  >,
//                 <>  < >
// <> ::= < > | < >
// < > ::= <1>, ..., <2>
//     : <1>  <2> -      
//                     ,   <1>  
//                   <2>
// < > ::= <>{, <>} |
//                       {<>,}< >{,<>}
// < > ::= .  
// <> ::= < > "("< >")"
//     :   <> (, SUM  PROD)    
// <  > ::= Y< >
// < > ::= <  >"("< >")"
// <> ::= PI | DIM
//     : <> DIM     
// < > ::= IF | THEN | ELSE | NOT | AND | OR | BEGIN | END
// <> ::= <> | <> | < > |
//               <> | <> |
//               < > | <  >
// <> ::= + | - |  * |  |  | / | ^
// <  > ::= + | -
// <> ::= <> |
//                <  > <> |
//                <> [<>] <> |
//                "("<>")" |
//                "|"<>"|"
//     :     <>,    ,  
//                  
// <> ::= ; | < > | < >
// < > ::= < > = <> <>
// < > ::= = | "<" | ">" | "<>" | ">"= | "<"=
// <> ::= <> < > <> |
//              <> (AND|OR) <> |
//               "(" <> ")"
// <  > ::= <  > "("<  >")" = <>
//     : <>   <  >   :
//                 <>  .  SUM  PROD
// <> ::= < > | < >
// < > ::= BEGIN { <> } END
// < > ::= IF <> THEN < > | <>
//                           [ELSE < > | <>]
// <> ::= F
// < > ::= <> = <> < >
//     :     < >   
// <> :== "//" < > < >|
//                  "{"{< > [< >]}"}"
//                  "(*"< > [< >] "*)"
//     :  <>    
// <> ::= {<  > | <>} < >

unit optMathParser;

{ TODO 1 -okuaw -cparser :       : .< >[E[-|+]< >], ..           }
{ TODO 5 -okuaw -cparser :    Normalize    "Pi Cos",      - ,         }

interface

uses
 //  :
 SysUtils, Classes, Contnrs,
 //  :
 optCore;

type
 {{
    :
   ltUnknown      -  
   ltBuildIn      - ,  , , IF, THEN  ..
   ltIdentifier   - , , ,  ,   
   ltNumber       - 
   ltOperation    -  : + - * / ^
   ltCondition    -  : < > <= >= <>
   ltSymbol       - 
   ltComment      - }
 ToptLexemeType = (ltUnknown, ltBuildIn, ltIdentifier, ltNumber, ltOperation, ltCondition, ltSymbol, ltComment);

 {{
   :
   ltUnknown
    lstUnknown    -   

   ltBuildIn      :
    lstIf         - IF
    lstThen       - THEN
    lstElse       - ELSE
    lstAnd        - AND
    lstOr         - OR
    lstBegin      - BEGIN
    lstEnd        - END

   ltIdentifier
    lstResult     -  
    lstMathFx     -   ,  Sin(Arg), ...
    lstMathConst  - , , Pi, Dim
    lstLocalFx    -  
    lstLocalFxArg -   
    lstVarX       -   Xi
    lstVar        -  
    lstVarLoop    -  i   SUM  PROD

   ltNumber
    lstInteger    -  
    lstFloat      - 

   ltOperation
    lstPlus       - '+'
    lstMinus      - '-'
    lstMul        - '*', '', ''
    lstDiv        - '/'
    lstPower      - '^'

   ltCondition
    lstEqual      - '='
    lstLess       - '<'
    lstGreater    - '>'
    lstLessEq     - '<='
    lstGreaterEq  - '>='
    lstNotEqual   - '<>'

   ltSymbol
    lstLeftBr     - '('
    lstRightBr    - ')'
    lstModule     - '|'
    lstComma      - ','
    lstDots       - '...' ,          
                           , , Min(Z1,..., Z10)
    lstDelimiter  - ';' -  
    lstCRLF       -    ,      

   ltComment
     lstComment   -      ( ) 
 }
 ToptLexemeSubType = (lstUnknown,
                      lstIf, lstThen, lstElse, lstAnd, lstOr,
                      lstBegin, lstEnd,
                      lstResult, lstMathFx, lstMathConst,
                      lstLocalFx, lstLocalFxArg,
                      lstVarX, lstVar, lstVarLoop,
                      lstInteger, lstFloat,
                      lstPlus, lstMinus, lstMul, lstDiv, lstPower,
                      lstEqual, lstLess, lstGreater, lstLessEq, lstGreaterEq, lstNotEqual,
                      lstLeftBr, lstRightBr, lstModule,
                      lstComma, lstDots,
                      lstDelimiter, lstCRLF,
                      lstComment);

 //:        
 EoptMathParsingException = class(EoptCoreException);

 //:        
 ToptCoreParsingObject = class(ToptCoreObject)
 public
  constructor Create; override;
 end;

 //: 
 ToptLexeme = class(ToptCoreParsingObject)
 public
  lxXpos: integer;  // X -     
  lxYpos: integer;  // Y - 
  lxValue: string;  //  
  lxExtend: string; //    
  lxType: ToptLexemeType;       //  
  lxSubType: ToptLexemeSubType; //  

  constructor Create(const aValue, anExtend: string; aType: ToptLexemeType; aSubType: ToptLexemeSubType; aX: integer = -1; aY: integer = -1); reintroduce; overload;
  constructor Create; overload; override;

  procedure Assign(Source: ToptCoreObject); override;
  procedure CheckSubType;       // ,      
  function  Clone: ToptLexeme;  //    
  function  FullValue: string;  //  
 end;

 //:  ,    ,     FakeLex
 ToptLexemeList = class(TObjectList)
 private
  FakeLex: ToptLexeme; // ,       

  function GetItem(Index: integer): ToptLexeme;
 public
  curIndex: integer;

  constructor Create;
  destructor  Destroy; override;

  //  
  function  IsEmpty: boolean; //  ?
  function  IsBof:   boolean; //  ?
  function  IsEof:   boolean; //  ?

  function  First: ToptLexeme; //        
  function  Prev:  ToptLexeme; //       
  function  Next:  ToptLexeme; //       
  function  Last:  ToptLexeme; //        

  function  Current: ToptLexeme; //  
  function  Look(Delta: integer): ToptLexeme; // ""    [curIndex  Delta]
  function  AddLexeme(const aValue, anExtend: string; aType: ToptLexemeType; aSubType: ToptLexemeSubType; aX: integer = -1; aY: integer = -1): ToptLexeme; //    
  procedure InsLexeme(aLexeme: ToptLexeme); //     curIndex
  function  SkipUntil(lxSubType: ToptLexemeSubType): boolean; //            

  property Items[Index: integer]: ToptLexeme read GetItem; default;
 end;

 {{  :
     vtInput      -  
     vtAdditional -  
     vtInternal   -         SUM  PROD }
 ToptVariableType = (vtInput, vtAdditional, vtInternal);

 {{    :
     vitNone     -  
     vitInteger  -  
     vitLetter   -   }
 ToptVarIndexType = (vitNone, vitInteger, vitLetter);

 //: 
 ToptVariable = class(ToptCoreParsingObject)
 public
  VarName:  string;          //  ,  
  VarIndex: string;          //  
  VarType: ToptVariableType; //  
  IsUsed: boolean;           //      
  IsDeclared: boolean;       //  ,   

  constructor Create(const aVarName, aVarIndex: string; aVarType: ToptVariableType); reintroduce; overload;
  constructor Create(aVarLexeme: ToptLexeme); reintroduce;  overload;

  function VarIndexType: ToptVarIndexType; //     
  function IndexAsInteger: integer;        //    
  function FullName: string;               //   -    ,   
  function SourceCodeName: string;         //       
 end;

 //:  
 ToptVariableList = class(TObjectList)
 private
  function GetItem(Index: integer): ToptVariable;
 public
  //   :
  function FindVar(const aFullVarName: string): ToptVariable; overload;                 //  
  function FindVar(const aVarName: string; aVarIndex: integer): ToptVariable; overload; //   
  function FindVar(aVarLexeme: ToptLexeme): ToptVariable; overload;                     // 

  property Items[Index: integer]: ToptVariable read GetItem; default;
 end;

 //:  
 ToptLocalFx = class(ToptCoreParsingObject)
 public
  FxName: string;      //   
  IsUsed: boolean;     //      
  IsDeclared: boolean; //  ,   

  constructor Create(FxLexeme: ToptLexeme); reintroduce;
 end;

 //:   
 ToptLocalFxList = class(TObjectList)
 private
  function GetItem(Index: integer): ToptLocalFx;
 public
  //:    
  function FindFx(FxLexeme: ToptLexeme): ToptLocalFx;

  property Items[Index: integer]: ToptLocalFx read GetItem; default;
 end;

 //:   -     + 
 ToptMathParser = class(ToptCoreParsingObject)
 private
  offsetLen: integer;            //  
  offsetStr: string;             //  
  RawLexemes: ToptLexemeList;    //       
  ParsedLexemes: ToptLexemeList; //       
  VarList: ToptVariableList;     //    
  LocalFxList: ToptLocalFxList;  //   

  //:     
  procedure SetErrorPos(aLexeme: ToptLexeme);
  //:   
  procedure Clear;
  //:   :   ,     
  procedure Prepare;
  //:    -    ,     RawLexemes
  procedure DoLexicalAnalysis(const Src: string; IsSkipComments: boolean = true);
  //:    - ,    RawLexemes   ,     ParsedLexemes
  procedure DoSymanticAnalysis(Dim: integer);

  //:  
  procedure AdjustOffset(aLex: ToptLexeme; offsetDelta: integer = 3);
 public
  errX, errY: integer; //  
  Warnings: TStrings;  // 

  constructor Create; override;
  destructor  Destroy; override;

  //:     
  procedure Check(Dim: integer; const Src: string);
  //:     
  function  TranslateToSrcCode(Dim: integer; const Src: string): string;
  //:   
  function  NormalizeFxText(const Src: string): string;
  //:          MathExprDraw
  function  TranslateToMathExprDraw(Dim: integer; const Src: string): string;
 end;

----------------------- implementation skiped -----------------------------

