123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989 |
- { This is a test-program for the fcl-passrc package (except writer-class).
- Please notice that i have done this to find out how good the parser workes,
- it is not thought to be a good example to use the fcl-passrc package but
- may give you hints on using it.
- It is done to test the source of these units for usability, completeness and
- bugs. It is base on the fcl-passrc exampe.
- It workes like a pretty-printer to compare the output of this program with
- the original code, but is not thought to be a real pretty-printer as
- e.g. the semicolons can sometimes not be set at the place they sould be
- (this imformation is not available from the parsing-engine, as a parser
- should only give you a positiv result if the source is valid, otherwise
- you get a negative result).
- Also the output is not always in the same order as in input as this
- information is not available easily.
-
- !!!Do not expect this program to produce executeable output!!!
- Status: -workes with one Unit or Program
- -Some type declarations missing
- -string[n] the [n] part missing -> missing in parser
- -array of const -> missing in parser
- -Hints deprecated, etc. missing sometimes
- -the parser splits x,y:atype
- x:atype
- y:atype
- i tryed to put them together again
- - () missing in statements: () expression and typecast
- -missing forward class declaration like x=class
- -incomplete !
- parser: -ugly ''' quotation from scanner, why not #39 ?
- -see comments in the program for hints
- -incomplete !
- Usage: call with one complete filename of a Unit or Program
- defaults for the parser are 'linux' and 'i386'
- Output: is 'pretty-printed' to stdout or unformated
- The unformated output is thought to be diffed with the original
- source to see differences caused by the parser (a tool to unformat
- a souce file is in progress but not finished jet).
- Bugs: 1. In case of unimplemented statements (like up to now asm) the parser
- cause a excemtion to abort the program hard.
- 2. Missing implementaion in this program should not print out anything
- or result in not pascal conform output.
- Hit: The parser uses directives given in the source file.
- Hints to read the code:
- There are comments in the code with hints and marks of possible bugs.
- During development some code was modified for true order output but the
- old code is still available as a comment as it is easier to understand.
- This is programmed using 'recursive' calls. Most options in functions are
- for printing the output.
- There is no writer-class used to keep it simple and see what is done.
- All output is produced by direct writing to stdout, this cause problems in
- furter development; a function result as string may be more usable.
- The parser was written to be used for unit interface and was expanded to
- work with program and implementation too. It does nearly no seperate
- things for programs, they are adapted to the unit scheme (see main).
- The order will change in following case:
- -function with forward declaration (also overloading etc.)
- Inheritance (only the important ones):
- TInterfaceSection, TImplementationSection, TProgramSection
- |
- TPasSection
- |
- TPasDeclarations
- |
- TPasElement
- |
- TPasElementBase
- |
- TObject
- TInitializationSection, TFinalizationSection
- |
- TPasImplBlock
- |
- TPasImplElement
- |
- TPasElement
- |
- TPasElementBase
- |
- TObject
- TPasProgram
- |
- TPasModule
- |
- TPasElement
- |
- TPasElementBase
- |
- TObject
- Dependance Structure :
- TPasPackage = class(TPasElement)
- |
- Modules: TFPList;
- TPasModule = class(TPasElement)
- |-InterfaceSection: TInterfaceSection;
- | |-Declarations -> forward part, unit only
- |
- |-ImplementationSection: TImplementationSection;
- | |-Declarations -> full declaration, unit and program
- | |-Functions: TFPList;
- | |-TPasFunction = class(TPasProcedureBase)
- | |-Body: TProcedureBody;
- | |-Declarations -> declaration and sub function
- | |-Body: TPasImplBlock; -> procedure block
- |
- |-InitializationSection: TInitializationSection;
- | |-TPasImplBlock.Elements: TFPList; -> main block
- |
- |-FinalizationSection: TFinalizationSection;
- |-TPasImplBlock.Elements: TFPList; -> unit only
- Declarations = class(TPasElement)
- |-Declarations: TFPList; -> the following are all in here
- |-ResStrings: TFPList;
- |-Types: TFPList;
- |-Consts: TFPList;
- |-Classes: TFPList;
- |-Functions: TFPList;
- |-Variables: TFPList;
- |-Properties: TFPList;
- }
- program test_parser1;
- {$mode objfpc}{$H+}
- uses SysUtils, Classes, PParser, PasTree;
- //# types the parser needs
- type
- { We have to override abstract TPasTreeContainer methods.
- See utils/fpdoc/dglobals.pp for an implementation of TFPDocEngine,
- a "real" engine. }
- TSimpleEngine = class(TPasTreeContainer)
- public
- function CreateElement(AClass: TPTreeElement; const AName: String;
- AParent: TPasElement; AVisibility: TPasMemberVisibility;
- const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
- override;
- function FindElement(const AName: String): TPasElement; override;
- end;
- function TSimpleEngine.CreateElement(AClass: TPTreeElement; const AName: String;
- AParent: TPasElement; AVisibility: TPasMemberVisibility;
- const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
- begin
- Result := AClass.Create(AName, AParent);
- Result.Visibility := AVisibility;
- Result.SourceFilename := ASourceFilename;
- Result.SourceLinenumber := ASourceLinenumber;
- end;
- function TSimpleEngine.FindElement(const AName: String): TPasElement;
- begin
- { dummy implementation, see TFPDocEngine.FindElement for a real example }
- Result := nil;
- end;
- //# main var
- var
- M: TPasModule;
- E: TPasTreeContainer;
- I: Integer;
- cmdl, TargetOS, TargetCPU : string;
- isim, //is Impleamentation, only for GetTPasProcedureBody
- Unformated:boolean; // no Formating in output
-
- //# tools
- function GetIndent(indent:integer):String;
- var i:integer;
- begin
- Result:='';
- if not Unformated then
- for i:=1 to indent do Result:=Result+' ';
- end;
- //delete ugly quoting '''STRING'''
- function DelQuot(s:String):String;
- var i:integer;
- const s1=#39#39#39;
- begin
- Result:='';
- i:=pos(s1,s);
- while i > 0 do
- begin
- if i > 0 then delete(s,i,2);
- i:=pos(s1,s);
- end;
- //if i > 0 then delete(s,i,2);
- Result:=s;
- end;
- //LeadingSpace only valid if Formated output (as this will be one line in output)
- //UnFormated: all is printed in a new line
- procedure WriteFmt(LeadingSpace:boolean; s:String; Semicolon:boolean);
- begin
- if Semicolon then s:=s+';';
- if Unformated then writeln(s)
- else if LeadingSpace then write(' ',s)
- else write(s);
- end;
- //# parsing output
- function GetTPasImplBlock(lb:TPasImplBlock; indent,declistby:integer;
- LastNoSem,NoFirstIndent:boolean):boolean; forward;
- function GetTPasImplElement(le:TPasImplElement; lindent:integer;
- lLastNoSem,NoFirstIndent:boolean):boolean; forward;
- procedure GetDecls(Decl:TPasDeclarations; indent:integer); forward;
- //procedure PrintDecls(Decl:TPasDeclarations; indent:integer); forward;
- //# most is for implementation or implblocks except the expr things
- function ReturnTPasMemberHints(h:TPasMemberHints):String;
- begin
- Result:='';
- if hDeprecated in h then Result:=' deprecated';
- if hLibrary in h then Result:=Result+' library';
- if hPlatform in h then Result:=Result+' platform';
- if hExperimental in h then Result:=Result+' experimental';
- if hUnimplemented in h then Result:=Result+' unimplemented';
- end;
-
- function GetTPasMemberHints(h:TPasMemberHints):Boolean;
- begin
- Result:=false;
- if hDeprecated in h then begin write(' deprecated'); Result:=true; end;
- if hLibrary in h then begin write(' library'); Result:=true; end;
- if hPlatform in h then begin write(' platform'); Result:=true; end;
- if hExperimental in h then begin write(' experimental'); Result:=true; end;
- if hUnimplemented in h then begin write(' unimplemented'); Result:=true; end;
- end;
- function GetTPasExprKind(lpek:TPasExprKind):String;
- begin
- Result:='';
- case lpek of
- pekIdent:Result:='ID';
- pekNumber:Result:='NUMBER';
- pekString:Result:='STRING';
- pekSet:Result:='SET';
- pekNil:Result:='NIL';
- pekBoolConst:Result:='BOOL';
- pekRange:Result:='RANGE';
- pekUnary:Result:='UNARY';
- pekBinary:Result:='BINARY';
- pekFuncParams:Result:='FUNCPAR';
- pekArrayParams:Result:='ARRAYPAR';
- pekListOfExp:Result:='EXPLIST';
- end;
- end;
- procedure GetTPasExpr(lex:TPasExpr);
- var lex1:TpasExpr;
- lpe:TParamsExpr;
- l:integer;
- lbk,rbk,sep:string;
- lav:TArrayValues;
- lrv:TRecordValues;
- rvi:TRecordValuesItem;
- function GetExpKind(ek:TPasExprKind; var lbrak,rbrak:string):string;
- begin
- lbrak:='';
- rbrak:='';
- Result:='';
- case ek of
- pekIdent:Result:='ID';
- pekNumber:Result:='NU';
- pekString:begin lbrak:=#39; rbrak:=#39; Result:=#39; end;
- pekSet:begin lbrak:='['; rbrak:=']'; Result:=','; end;
- pekNil:Result:='NIL';
- pekBoolConst:Result:='';
- pekRange:Result:='..';
- pekUnary:Result:='';
- pekBinary:Result:='';
- pekFuncParams:begin lbrak:='('; rbrak:=')'; Result:=','; end;
- pekArrayParams:begin lbrak:='['; rbrak:=']'; Result:=','; end;
- pekListOfExp:Result:=',';
- pekInherited:Result:=' InheriteD';
- pekSelf:Result:=' SelF';
- end;
- end;
- function GetOp(lop:TExprOpCode):string;
- begin
- Result:='';
- case lop of
- eopNone:Result:='';
- eopAdd:Result:='+';
- eopSubtract:Result:='-';
- eopMultiply:Result:='*';
- eopDivide:Result:='/';
- eopDiv:Result:=' div ';
- eopMod:Result:=' mod ';
- eopPower:Result:='^';
- eopShr:Result:=' shr ';
- eopSHl:Result:=' shl ';
- eopNot:Result:=' not ';
- eopAnd:Result:=' and ';
- eopOr:Result:=' or ';
- eopXor:Result:=' xor ';
- eopEqual:Result:='=';
- eopNotEqual:Result:='<>';
- eopLessThan:Result:='<';
- eopGreaterThan:Result:='>';
- eopLessthanEqual:Result:='<=';
- eopGreaterThanEqual:Result:='>=';
- eopIn:Result:=' in ';
- eopIs:Result:=' is ';
- eopAs:Result:=' as ';
- eopSymmetricaldifference:Result:='><';
- eopAddress:Result:='@';
- eopDeref:Result:='^';
- eopSubIdent:Result:='.';
- end;
- end;
- begin
- if lex is TBinaryExpr then //compined constants
- begin
- sep:=GetExpKind(lex.Kind,lbk,rbk);
- //write('|');
- write(lbk);
- GetTPasExpr(TBinaryExpr(lex).left);
- write(GetOp(TBinaryExpr(lex).OpCode));
- write(sep);
- GetTPasExpr(TBinaryExpr(lex).right);
- write(rbk);
- //write('|');
- //write(' [',lex.Name,' ',GetTPasExprKind(lex.Kind),']');
- end
- else
- begin
- //write('UNARY');
- if lex is TUnaryExpr then
- begin
- lex1:=TUnaryExpr(lex).Operand;
- if lex.OpCode = eopDeref then
- begin
- GetTPasExpr(lex1);
- write(GetOp(lex.OpCode)); //unary last, only: p^
- end
- else
- begin
- write(GetOp(lex.OpCode)); //unary first: -1
- GetTPasExpr(lex1);
- end;
- end;
- if lex is TPrimitiveExpr then write(TPrimitiveExpr(lex).Value) //simple constant
- else
- if lex is TBoolConstExpr then write(TBoolConstExpr(lex).Value)
- else
- if lex is TNilExpr then write('nil')
- else
- if lex is TInheritedExpr then write('Inherited ')
- else
- if lex is TSelfExpr then write('Self')
- else
- if lex is TParamsExpr then //writeln(param1,param2,..,paramn);
- begin
- //write(' PAREX ');
- lpe:=TParamsExpr(lex);
- GetTPasExpr(lpe.Value);
- if length(lpe.Params) >0 then
- begin
- sep:=GetExpKind(lpe.Kind,lbk,rbk);
- write(lbk); //write('(');
- for l:=0 to High(lpe.Params)-1 do
- begin
- GetTPasExpr(lpe.Params[l]);
- write(sep); //seperator
- end;
- GetTPasExpr(lpe.Params[High(lpe.Params)]);
- write(rbk);//write(')');
- end
- else
- begin //funcion()
- sep:=GetExpKind(lpe.Kind,lbk,rbk);
- write(lbk,rbk);
- end;
- end
- else if lex is TArrayValues then //const AnArrayConst: Array[1..3] of Integer = (1,2,3);
- begin
- write('(');
- lav:=TArrayValues(lex);
- if length(lav.Values) > 0 then
- begin
- for l:=0 to high(lav.Values)-1 do
- begin
- GetTPasExpr(TPasExpr(lav.Values[l]));
- write(',');
- end;
- GetTPasExpr(TPasExpr(lav.Values[high(lav.Values)]));
- end;
- write(')');
- end
- else if lex is TRecordValues then
- begin
- write('(');
- lrv:=TRecordValues(lex);
- if length(lrv.Fields) > 0 then
- begin
- for l:=0 to high(lrv.Fields)-1 do
- begin
- rvi:=TRecordValuesItem(lrv.Fields[l]);
- write(rvi.Name,':');
- GetTPasExpr(rvi.ValueExp);
- write(';');
- end;
- rvi:=TRecordValuesItem(lrv.Fields[high(lrv.Fields)]);
- write(rvi.Name,':');
- GetTPasExpr(rvi.ValueExp);
- end;
- write(')');
- end
- else
- begin
- //?
- //writeln('{ Unknown Expression: ');
- //if assigned(lex) then GetTPasExprKind(lex.Kind);
- //writeln('}');
- end;
- end;
- end;
- //NoFirstIndent only for block in case:
- procedure GetTPasSmt(lsmt:TPasImplStatement; lindent:integer; DoNoSem,NoFirstIndent:boolean);
- var l:integer;
- lics:TPasImplCaseStatement;
- DoSem:boolean;
- liwd:TPasImplWithDo;
- liwhd:TPasImplWhileDo;
- lieo:TPasImplExceptOn;
- lifl:TPasImplForLoop;
- lir:TPasImplRaise;
- s,s1:String;//s1 only first line of block statement
- begin
- DoSem:=true;
- s:=GetIndent(lindent);
- if NoFirstIndent then s1:=' ' else s1:=s;
- if lsmt is TPasImplSimple then
- begin
- write(s1); GetTPasExpr(TPasImplSimple(lsmt).expr);
- //DoSem:=true;
- end
- else if lsmt is TPasImplAssign then
- begin
- write(s1); GetTPasExpr(TPasImplAssign(lsmt).left);
- write(':= ');
- GetTPasExpr(TPasImplAssign(lsmt).right);
- //DoSem:=true;
- end
- else if lsmt is TPasImplCaseStatement then
- begin
- lics:=TPasImplCaseStatement(lsmt);
- if lics.Expressions.Count>0 then
- begin
- write(s);
- for l:=0 to lics.Expressions.Count-2 do
- write(DelQuot(TPasExpr(lics.Expressions[l]).GetDeclaration(True)),',');
- write(DelQuot(TPasExpr(lics.Expressions[lics.Expressions.Count-1]).GetDeclaration(True)),': '); // !!bug too much ' in expression
- //if not assigned(lics.Body) then writeln('TPasImplCaseStatement missing BODY');
- //if assigned(lics.Body) and (TPasImplBlock(lics.Body).Elements.Count >0) then
- // GetTPasImplBlock(TPasImplBlock(lics.Body),lindent+1,0,false,true)
- // else GetTPasImplBlock(TPasImplBlock(lics),lindent+1,0,false,true); // !!bug missing body, assigned but empty
- if assigned(lics.Body) then
- begin
- if not GetTPasImplElement(lics.Body,lindent+1,false,true) then ;//writeln(';');
- end
- else writeln(';');
- end;
- DoSem:=false;
- end
- else if lsmt is TPasImplWithDo then
- begin
- liwd:=TPasImplWithDo(lsmt); // !!Bug: missing with do at following with do !solved see Bug
- write(s1,'with ',liwd.Name);
- if liwd.Expressions.Count>0 then
- begin
- for l:=0 to liwd.Expressions.Count-2 do
- write(TPasExpr(liwd.Expressions[l]).GetDeclaration(true),',');
- write(TPasExpr(liwd.Expressions[liwd.Expressions.Count-1]).GetDeclaration(true));
- end;
- writeln(' do');
- //if TPasImplBlock(liwd.Body).Elements.Count >0 then
- //GetTPasImplBlock(TPasImplBlock(liwd.Body),0); // !!Bug: BODY Not used
- //else
- GetTPasImplBlock(TPasImplBlock(liwd),lindent+1,0,false,false);
- DoSem:=false;
- end
- else if lsmt is TPasImplWhileDo then
- begin
- liwhd:=TPasImplWhileDo(lsmt);
- writeln(s1,'while ',DelQuot(liwhd.Condition),' do');
- //if not GetTPasImplBlock(TPasImplBlock(liwhd.Body),0) then // !!Bug: BODY Not used
- GetTPasImplBlock(TPasImplBlock(liwhd),lindent,0,DoNoSem,false); //OK for all constructs
- DoNoSem:=false; //?
- DoSem:=false;
- end
- else if lsmt is TPasImplExceptOn then
- begin
- lieo:=TPasImplExceptOn(lsmt);
- writeln(s,'on ',lieo.VariableName,': ',lieo.TypeName,' do');
- if TPasImplBlock(lieo.Body) is TPasImplRaise then
- begin
- write(s,'raise ');//raise is in TPasImplBlock in this case
- GetTPasImplBlock(TPasImplBlock(lieo.Body),lindent+1,0,false,true);
- end
- else GetTPasImplBlock(TPasImplBlock(lieo.Body),lindent+1,0,false,false);
- DoSem:=false;
- end
- else if lsmt is TPasImplForLoop then
- begin
- lifl:=TPasImplForLoop(lsmt);
- //TODO variable
- write(s1,'for ',lifl.VariableName,':= ',lifl.StartValue,' ');
- if lifl.Down then write('down');
- writeln('to ',lifl.EndValue,' do');
- GetTPasImplBlock(TPasImplBlock(lifl),lindent+1,0,false,false);
- DoSem:=false;
- end
- else if lsmt is TPasImplRaise then
- begin
- write(s1,'raise ');
- lir:=TPasImplRaise(lsmt);
- if not GetTPasImplBlock(TPasImplBlock(lir),lindent,0,DoNoSem,true) then
- writeln(';');
- DoNoSem:=false;
- DoSem:=false;
- end
- else
- begin
- if assigned(lsmt.Elements) then
- begin
- writeln('{ Unknown SMT(s): '); //,lsmt.Name,' ',lsmt.ElementTypeName);
- for l:=0 to lsmt.Elements.Count-1 do
- write(s,' SMT ',l,' ',TPasElement(lsmt.Elements[l]).Name);
- writeln('}');
- end;
- DoSem:=false;
- end;
- if not DoNoSem then
- begin
- if DoSem then writeln(';');
- end
- else writeln;
- end;
- //result: result of TPasImplBlock or valid element
- //NoFirstIndent only for block in case:
- function GetTPasImplElement(le:TPasImplElement; lindent:integer;
- lLastNoSem,NoFirstIndent:boolean):boolean;
- var liie:TPasImplIfElse;
- lico:TPasImplCaseOf;
- lice:TPasImplCaseElse;
- liru:TPasImplRepeatUntil;
- lit:TPasImplTry;
- //lic:TPasImplCommand;
- s,s1:String;//s1 only first line of block statement
- begin
- Result:=true;
- s:=GetIndent(lindent);
- if NoFirstIndent then s1:=' ' else s1:=s;
- if le is TPasImplStatement then
- begin
- if NoFirstIndent then lindent:=0;
- GetTPasSmt(TPasImplStatement(le),lindent+1,lLastNoSem,NoFirstIndent);
- end
- else if le is TPasImplIfElse then
- begin
- liie:=TPasImplIfElse(le);
- write(s1,'if ',DelQuot(liie.Condition),' then ');
- if assigned(liie.ElseBranch) then
- begin
- writeln;
- GetTPasImplElement(liie.IfBranch,lindent+1,true,false);
- writeln(s,'else');// {if}');
- GetTPasImplElement(liie.ElseBranch,lindent+1,lLastNoSem,false);
- end
- else
- begin //no else part
- if assigned(liie.IfBranch) then
- begin
- writeln;
- if not GetTPasImplElement(liie.IfBranch,lindent+1,false,false) then
- writeln(';');
- end
- else writeln(';'); //empty if then;
- end;
- end
- else if le is TPasImplCaseOf then
- begin
- lico:=TPasImplCaseOf(le);
- writeln(s1,'case ',lico.Expression,' of ');
- if assigned(lico.ElseBranch) then //workaround duplicate bug
- begin //reduce count of CaseOf as CaseElse is in there
- lice:=lico.ElseBranch;
- GetTPasImplBlock(TPasImplBlock(lico),lindent+1,1,false,false);
- end
- else GetTPasImplBlock(TPasImplBlock(lico),lindent+1,0,false,false); // !! else duplicate in here
- if assigned(lico.ElseBranch) then
- begin
- writeln(s,'else');//' {case}');
- lice:=lico.ElseBranch;
- GetTPasImplBlock(TPasImplBlock(lice),lindent+1,0,false,false);
- end;
- if lLastNoSem then writeln(s,'end')//' {case}')
- else writeln(s,'end;');// {case}');
- //Result:=false; ??? GetTPasImplBlock
- end
- else if le is TPasImplRepeatUntil then
- begin
- liru:=TPasImplRepeatUntil(le);
- writeln(s1,'repeat');
- GetTPasImplBlock(TPasImplBlock(liru),lindent+1,0,false,false);
- write(s,'until ',DelQuot(liru.Condition));
- if lLastNoSem then writeln
- else writeln(';');
- end
- else if le is TPasImplTryFinally then
- begin
- writeln(s,'finally');
- GetTPasImplBlock(TPasImplBlock(le),lindent+1,0,false,false);
- end
- else if le is TPasImplTryExcept then
- begin
- writeln(s,'except');
- GetTPasImplBlock(TPasImplBlock(le),lindent+1,0,false,false);
- end
- else if le is TPasImplTryExceptElse then
- begin
- writeln(s,'else');// {try}');
- GetTPasImplBlock(TPasImplBlock(le),lindent+1,0,false,false);
- end
- else if le is TPasImplTry then
- begin
- lit:=TPasImplTry(le);
- writeln(s1,'try');
- GetTPasImplBlock(TPasImplBlock(le),lindent+1,0,false,false);
- if assigned(lit.FinallyExcept) then
- GetTPasImplElement(TPasImplElement(lit.FinallyExcept),lindent+1,false,false);
- if assigned(lit.ElseBranch) then
- GetTPasImplElement(TPasImplElement(lit.ElseBranch),lindent+1,false,false);
- if lLastNoSem then writeln(s,'end')// {try} ') //there is no ImplBeginBlock
- else writeln(s,'end;');// {try} ');
- end
- else if le is TPasImplCommand then
- begin
- //ignore because empty
- // lic:=TPasImplCommand(le);
- // writeln(' CMD ',lic.Command,' ',lic.Name,' ',lic.ElementTypeName);
- end
- else if le is TPasImplLabelMark then
- begin
- writeln(s1,'label ',TPasImplLabelMark(le).LabelId,';');
- end
- else if le is TPasImplBlock then
- begin
- //IfElse, case:
- Result:=GetTPasImplBlock(TPasImplBlock(le),lindent+1,0,lLastNoSem,NoFirstIndent);
- end
- else
- begin
- Result:=false;
- //writeln(s,';');
- //writeln(' EL ',l);//,' ',le.Name)//,' ',le.ElementTypeName,' ',le.FullName);
- end;
- end;
-
- // indent: indent from page left side
- // DecListBy: dec(elements.count) because of case duplicate else bug
- // LastNoSem: only true on last expr before else in a if clause
- // NoFirstIndent: if line was started by other block like in case at -> 1:Noindent;
- // Result: true if elements not empty
- function GetTPasImplBlock(lb:TPasImplBlock; indent,declistby:integer;
- LastNoSem,NoFirstIndent:boolean):boolean;
- var l,n:integer;
- lbe:TPasImplElement;
- NoSem:boolean;
- ls:String;
- begin
- Result:=false;
- NoSem:=false;
- ls:=GetIndent(indent);
- if not assigned(lb) then exit;
- //if lb is TPasImplRaise then writeln('RAISE');
- if assigned(lb.Elements) then
- begin
- if lb is TPasImplBeginBlock then
- begin
- NoSem:=LastNoSem;
- LastNoSem:=false;
- if NoFirstIndent then
- begin
- writeln('begin');////NFI');
- NoFirstIndent:=false;
- end
- else writeln(ls,'begin');
- inc(indent);
- end;
- if lb.Elements.Count >0 then
- begin
- Result:=true;
- n:=lb.Elements.Count-1;
- //workaround CaseOf duplicate bug
- if (declistby >0)and(lb.Elements.Count >declistby) then dec(n,declistby);
- for l:=0 to n do
- begin
- lbe:=TPasImplElement(lb.Elements[l]);
- //write(l:2,'/',n:2,' '); //No of curent element, max element
- if ((l = 0)and NoFirstIndent) then
- begin //index0
- if l=n then GetTPasImplElement(lbe,0,LastNoSem,false)
- else GetTPasImplElement(lbe,0,false,false)
- end
- else if l<>n then GetTPasImplElement(lbe,indent,false,false) //other index
- else GetTPasImplElement(lbe,indent,LastNoSem,false); //indexn
- end;
- end
- else
- begin //block is empty
- //write(ls,' {!EMPTY!}');
- {if not NoSem then
- begin
- if lb is TPasImplBeginBlock then writeln //empty compound need no ;
- else writeln(';')
- end
- else
- writeln;}
- end;
- if lb is TPasImplBeginBlock then
- if not NoSem then writeln(ls,'end;')// {Block}')
- else writeln(ls,'end');// {Block}');
- end
- else
- writeln(';'); //writeln(' {!empty!};')
- end;
- //# Declarations (type,var,const,..)
- procedure GetTPasArrayType(lpat:TPasArrayType);
- begin
- if lpat.IsPacked then write('packed ');
- write('Array');
- if lpat.IndexRange <> '' then write('[',lpat.IndexRange,']');
- if assigned(lpat.ElType) then write(' of ',lpat.ElType.Name);
- // BUG: of const missing in Procedure ConstArrayArgProc(A: Array of const); pparser: 643
- end;
- //write out one variable or constant declaration, also used in types
- //In spite of the use of GetPasVariables this is still used !
- procedure GetTPasVar(lpv:TPasVariable; lindent:integer; NoLF:boolean);//BUG string[] pparser: 482
- var i,j:integer;
- //lppt:TPasProcedureType;
- //lpa:TPasArgument;
- //lpat:TPasArrayType;
- s,s1:string;
- prct:TPasRecordType;
- begin
- if not Assigned(lpv) then exit;
- s:=GetIndent(lindent);
- write(s,lpv.Name);//,' ',lpv.value,' ',lpv.Modifiers,' ',lpv.AbsoluteLocation);
- if assigned(lpv.VarType) then
- begin
- //if TPasType(lpa.ArgType).ElementTypeName <>'unresolved type reference' then
- //,TPasType(lpa.ArgType).Name,' ');//,TPasType(lpa.ArgType).FullName,TPasType(lpa.ArgType).ElementTypeName)
- // PParser 2099: ArgType := nil; if IsUntyped then => Arg.ArgType := ArgType;
- // else write(':? ');
- write(': ');
- if lpv.VarType is TPasArrayType then
- begin
- GetTPasArrayType(TPasArrayType(lpv.VarType));
- end
- else if lpv.VarType is TPasSetType then
- begin
- write('set of ',TPasSetType(lpv.VarType).EnumType.Name);
- end
- else
- begin
- if lpv.VarType is TPasPointerType then
- write('^',TPasPointerType(lpv.VarType).DestType.Name)
- else if lpv.VarType is TPasRecordType then //var record
- begin
- j:=lindent+Length(lpv.Name)+4;
- s1:=GetIndent(j);
- prct:=TPasRecordType(lpv.VarType);
- if prct.IsBitPacked then write('bitpacked ');
- if prct.IsPacked then write('packed ');
- writeln('Record');
- for i:=0 to prct.Members.Count-1 do
- begin
- GetTPasVar(TPasVariable(prct.Members[i]),j+1,false);
- end;
- write(s1,'end');
- end
- else
- begin
- write(TPasType(lpv.VarType).Name);
- //if TPasType(lpv.VarType) is TPasAliasType then write(TPasAliasType(lpv.VarType).Name);
- end;
- end;
- end;
- if lpv.Value <> '' then write('=',lpv.Value);
- if assigned(lpv.Expr) then // var ?, const AnArrayConst : Array[1..3] of Integer = (1,2,3);
- begin
- write('=');
- GetTPasExpr(lpv.Expr);
- end;
-
- if lpv.Modifiers <>'' then //Modifiers starts with ;
- begin
- write(' ',lpv.Modifiers,';');
- if GetTPasMemberHints(lpv.Hints) then write(';');
- end
- else
- begin
- GetTPasMemberHints(lpv.Hints);
- write(';');
- end;
- if not NoLF then writeln;
- end;
-
- //write out a list of variables only
- //more compact than the output of seperate calls of GetTPasVar
- procedure GetPasVariables(vl:TFPList; lindent:integer; NoLF,NoSEM:boolean);
- var v,i,j:integer;
- s,s1:string;
- prct:TPasRecordType;
- lpv:TPasVariable;
-
- same:boolean;
- samestr,tmpstr:Ansistring;
- samevar:array of integer;
- svi:integer;
- begin
- if vl.Count <= 0 then exit;
- s:=GetIndent(lindent);
- //> compare all variable types as string to find the ones with same type
- samestr:='';
- svi:=0;
- SetLength(samevar,vl.count);
- for v:=0 to vl.count-1 do
- begin
- tmpstr:='';
- same:=true;
- lpv:=TPasVariable(vl[v]);
- //write(s,lpv.Name);
- if assigned(lpv.VarType) then
- begin
- tmpstr:=tmpstr+': ';
- if lpv.VarType is TPasArrayType then
- begin
- //GetTPasArrayType(TPasArrayType(lpv.VarType));
- tmpstr:=tmpstr+'array'+TPasArrayType(lpv.VarType).IndexRange;
- if assigned(TPasArrayType(lpv.VarType).ElType) then
- tmpstr:=tmpstr+TPasArrayType(lpv.VarType).ElType.Name;
- end
- else if lpv.VarType is TPasSetType then
- begin
- tmpstr:=tmpstr+'set of '+TPasSetType(lpv.VarType).EnumType.Name;
- end
- else
- begin
- if lpv.VarType is TPasPointerType then
- tmpstr:=tmpstr+'^'+TPasPointerType(lpv.VarType).DestType.Name
- else if lpv.VarType is TPasRecordType then //var record
- begin
- prct:=TPasRecordType(lpv.VarType);
- if prct.IsBitPacked then tmpstr:=tmpstr+'bitpacked ';
- if prct.IsPacked then tmpstr:=tmpstr+'packed ';
- tmpstr:=tmpstr+'Record ';
- for i:=0 to prct.Members.Count-1 do
- begin
- //todo
- //GetTPasVar(TPasVariable(prct.Members[i]),j+1,false);
- end;
- tmpstr:=tmpstr+'end';
- end
- else
- begin
- tmpstr:=tmpstr+TPasType(lpv.VarType).Name;
- end;
- end;
- end
- else same:=false;
- if lpv.Value <> '' then same:=false;//=
- if assigned(lpv.Expr) then // var ?, const AnArrayConst : Array[1..3] of Integer = (1,2,3);
- begin
- same:=false;//=
- end;
- if lpv.Modifiers <>'' then //Modifiers starts with ;
- begin
- tmpstr:=tmpstr+' '+lpv.Modifiers+';';
- tmpstr:=tmpstr+ReturnTPasMemberHints(lpv.Hints);
- end
- else
- begin
- tmpstr:=tmpstr+ReturnTPasMemberHints(lpv.Hints);
- end;
- //if v = 0 then begin samestr:=tmpstr; end;
- if (not same)or(samestr <> tmpstr) then
- begin
- samestr:=tmpstr;
- inc(svi);
- end;
- samevar[v]:=svi;
- end;
- //compare <
- //now print them
- svi:=-1;
- for v:=0 to vl.count-1 do
- begin
- lpv:=TPasVariable(vl[v]);
- if not Assigned(lpv) then continue;
- if svi <> samevar[v] then
- begin
- svi:=samevar[v];
- if v>0 then writeln;
- write(s,lpv.Name);//variblenname
- end
- else write(lpv.Name);
- if (v < vl.Count-1)and(samevar[v+1]=svi) then write(',')
- else
- begin
- if assigned(lpv.VarType) then
- begin
- write(': ');
- if lpv.VarType is TPasArrayType then
- begin
- GetTPasArrayType(TPasArrayType(lpv.VarType));
- end
- else if lpv.VarType is TPasSetType then
- begin
- write('set of ',TPasSetType(lpv.VarType).EnumType.Name);
- end
- else
- begin
- if lpv.VarType is TPasPointerType then
- write('^',TPasPointerType(lpv.VarType).DestType.Name)
- else if lpv.VarType is TPasRecordType then //var record
- begin
- j:=lindent+Length(lpv.Name)+4;
- s1:=GetIndent(j);
- prct:=TPasRecordType(lpv.VarType);
- if prct.IsBitPacked then write('bitpacked ');
- if prct.IsPacked then write('packed ');
- writeln('Record');
- {for i:=0 to prct.Members.Count-1 do
- begin
- GetTPasVar(TPasVariable(prct.Members[i]),j+1,false);
- end;}
- if prct.Members.Count > 0 then
- GetPasVariables(prct.Members,j+1,false,false);
- write(s1,'end');
- end
- else
- begin
- write(TPasType(lpv.VarType).Name);
- end;
- end;
- end;
- if lpv.Value <> '' then write('=',lpv.Value);
- if assigned(lpv.Expr) then // var ?, const AnArrayConst : Array[1..3] of Integer = (1,2,3);
- begin
- write('=');
- GetTPasExpr(lpv.Expr);
- end;
- if lpv.Modifiers <>'' then //Modifiers starts with ;
- begin
- write(' ',lpv.Modifiers,';');
- if GetTPasMemberHints(lpv.Hints) then write(';');
- end
- else
- begin
- GetTPasMemberHints(lpv.Hints);
- if (v < vl.Count-1) then write(';')
- else if (not NoSEM) then write(';');
- end;
- //if not NoLF then writeln;
- end;
- end;
- if not NoLF then writeln;
- end;
-
- function GetTPasArgumentAccess(acc:TArgumentAccess):String;
- begin
- Result:='';
- case acc of
- //argDefault:Result:='default'; //normal proccall is default
- argConst:Result:='const';
- argVar:Result:='var';
- argOut:Result:='out';
- end;
- end;
- procedure GetTPasProcedureType(lppt:TPasProcedureType; indent:integer);
- Var
- l : integer;
- lpa:TPasArgument;
- samevar:array of integer;//same index same type
- aktaa:TArgumentAccess;
- svi:integer;
- same:boolean;
- aktname,tmpname:String;
- begin
- if assigned(lppt.Args) and (lppt.Args.Count > 0) then
- begin
- write('(');
- if lppt.Args.Count > 0 then
- begin
- //produce more compact output than the commented block below
- //>find same declaration
- //look ahead what is the same
- SetLength(samevar,lppt.Args.Count);
- svi:=0;
- aktname:='';
- for l:=0 to lppt.Args.Count-1 do
- begin
- same:=true;
- tmpname:='';
- lpa:=TPasArgument(lppt.Args.Items[l]);
- if assigned(lpa.ArgType) then
- begin
- if lpa.ArgType is TPasArrayType then
- begin
- if assigned(TPasArrayType(lpa.ArgType).ElType) then tmpname:=TPasArrayType(lpa.ArgType).ElType.Name;
- end
- else tmpname:=TPasType(lpa.ArgType).Name;
- end;
- if l=0 then begin aktaa:=lpa.Access; aktname:=tmpname; end;
- if lpa.Access <> aktaa then begin same:=false; aktaa:=lpa.Access; end;//access type
- if (tmpname = '')or(tmpname <> aktname) then begin same:=false; aktname:=tmpname; end;//type name
- if lpa.Value <> '' then same:=false;//var=value
- if not same then inc(svi);
- samevar[l]:=svi;
- end;
- //find same declaration<
- svi:=-1;
- same:=false;
- for l:=0 to lppt.Args.Count-1 do
- begin
- lpa:=TPasArgument(lppt.Args.Items[l]);
- if svi <> samevar[l] then
- begin
- svi:=samevar[l];
- if lpa.Access <> argDefault then write(GetTPasArgumentAccess(lpa.Access),' ');
- write(lpa.Name);//variblenname
- end
- else write(lpa.Name);
- if (l < lppt.Args.Count-1)and(samevar[l+1]=svi) then write(',')
- else
- begin
- if assigned(lpa.ArgType) then
- begin
- write(': ');
- if lpa.ArgType is TPasArrayType then
- GetTPasArrayType(TPasArrayType(lpa.ArgType))
- else write(TPasType(lpa.ArgType).Name);
- end;
- if lpa.Value <> '' then write('=',lpa.Value);
- if l< lppt.Args.Count-1 then write('; ');
- end;
- end;
- write(')');
- end;
- end;
- if (lppt is TPasFunctionType) then
- write(': ',TPasFunctionType(lppt).ResultEl.ResultType.Name);
- if lppt.IsOfObject then
- write(' of Object');
- end;
- procedure GetTypes(pe:TPasElement; lindent:integer);
- var i,j,k:integer;
- s,s1,s2:string;
- pet:TPasEnumType;
- pev:TPasEnumValue;
- prt:TPasRangeType;
- prct:TPasRecordType;
- pv:TPasVariant;
- pst:TPasSetType;
- function GetVariantRecord(pe:TPasElement; lindent:integer):boolean;
- var i,j,k:integer;
- prct:TPasRecordType;
- pv:TPasVariant;
- s,s1:string;
- begin
- Result:=false;
- j:=lindent+Length(pe.Name)+2;
- s:=GetIndent(lindent);
- s1:=GetIndent(lindent+2);
- prct:=TPasRecordType(pe);
- {Now i use GetPasVariables for more compact output
- for i:=0 to prct.Members.Count-1 do
- begin
- GetTPasVar(TPasVariable(prct.Members[i]),1,true);
- end;}
- if prct.Members.Count > 0 then GetPasVariables(prct.Members,1,true,true);
- if assigned(prct.Variants) then
- begin
- Result:=true;
- writeln(';');
- write(s,'case ');
- if prct.VariantName <>'' then write(prct.VariantName,'=');
- write(TPasType(prct.VariantType).Name);
- writeln(' of');
- if assigned(prct.Variants)then
- if prct.Variants.Count >0 then
- begin
- for i:=0 to prct.Variants.Count-1 do
- begin
- pv:=TPasVariant(prct.Variants[i]);
- write(s1,pv.Name);
- for k:=0 to pv.Values.Count-1 do write(TPasElement(pv.Values[k]).GetDeclaration(true));
- write(': (');
- if GetVariantRecord(TPasElement(pv.Members),j+1) then
- writeln(s1,');')
- else writeln(');');
- end;
- end;
- end;
- end;
- begin
- s:=GetIndent(lindent);
- write(s,pe.Name,'=');
- if pe is TPasArrayType then
- begin
- GetTPasArrayType(TPasArrayType(pe));
- writeln(';');
- end
- else if pe is TPasEnumType then
- begin
- pet:=TPasEnumType(pe);
- write('(');
- if pet.Values.Count > 0 then
- begin
- for j:=0 to pet.Values.Count-2 do
- begin
- pev:=TPasEnumValue(pet.Values[j]);
- write(pev.name,',');
- //pev.Value ?
- //pev.AssignedValue ?
- //pev.IsValueUsed ?
- end;
- pev:=TPasEnumValue(pet.Values[pet.Values.Count-1]);
- write(pev.name);
- end;
- writeln(');');
- end
- else if pe is TPasFileType then
- begin
- writeln('file of ',TPasFileType(pe).ElType.Name,';');
- end
- else if pe is TPasProcedureType then
- begin
- if pe is TPasFunctionType then
- Write('function ')
- else
- Write('procedure ');
- GetTPasProcedureType(TPasProcedureType(pe), lindent);
- Writeln(';');
- end
- else if pe is TPasPointerType then
- begin
- //writeln('pointer');
- writeln('^',TPasPointerType(pe).DestType.Name,';');
- end
- else if pe is TPasRangeType then
- begin
- prt:=TPasRangeType(pe);
- writeln(prt.RangeStart,'..',prt.RangeEnd,';');
- end
- else if pe is TPasRecordType then
- begin
- j:=lindent+Length(pe.Name)+2;
- s1:=GetIndent(j);
- s2:=GetIndent(j+1);
- prct:=TPasRecordType(pe);
- if prct.IsBitPacked then write('bitpacket ');
- if prct.IsPacked then write('packet');
- writeln('record');
- {Now i use GetPasVariables for more compact output
- for i:=0 to prct.Members.Count-1 do
- begin
- GetTPasVar(TPasVariable(prct.Members[i]),j+1,false);
- end;}
- GetPasVariables(prct.Members,j+2,false,false);
- if assigned(prct.Variants) then
- begin
- write(s1,'case ');
- if prct.VariantName <>'' then write(prct.VariantName,'=');
- write(TPasType(prct.VariantType).Name);
- writeln(' of');
- if assigned(prct.Variants)then
- if prct.Variants.Count >0 then
- begin
- for i:=0 to prct.Variants.Count-1 do
- begin
- pv:=TPasVariant(prct.Variants[i]);
- write(s2,pv.Name);
- for k:=0 to pv.Values.Count-1 do write(TPasElement(pv.Values[k]).GetDeclaration(true));
- write(': (');
- if GetVariantRecord(TPasElement(pv.Members),j+2) then
- writeln(s2,');')
- else writeln(');');
- end;
- end;
- end;
- writeln(s1,'end;');
- end
- else if pe is TPasSetType then
- begin
- pst:=TPasSetType(pe);
- writeln('set of ',pst.EnumType.Name,';');
- end
- else if pe is TPasClassOfType then writeln('Class of ',TPasClassOfType(pe).DestType.Name,';')
- else if pe is tPasAliasType then
- begin
- pe:=tPasAliasType(PE).DestType;
- write(PE.name);
- if pe is tPasStringType then
- begin
- if (TPasStringType(PE).LengthExpr<>'') then
- Write('[',TPasStringType(PE).LengthExpr,']');
- end;
- Writeln(';');
- end
- else if pe is tPasUnresolvedTypeRef then writeln(TPasUnresolvedTypeRef(PE).name,';')
- else
- begin
-
- writeln('{ Unknown TYPE(s): ');
- writeln(s,pe.Name,' ',pe.classname);
- writeln('}');
- writeln;
- end;
- end;
- procedure GetTCallingConvention(cc:TCallingConvention); //TODO: test it
- begin
- case cc of
- //ccDefault:write(' default;'); //normal proccall is default
- ccRegister:WriteFmt(true,'Register;',false);
- ccPascal :WriteFmt(true,'Pascal;',false);
- ccCDecl :WriteFmt(true,'CDecl;',false);
- ccStdCall :WriteFmt(true,'StdCall;',false);
- ccOldFPCCall:WriteFmt(true,'OldFPCall;',false);
- ccSafeCall:WriteFmt(true,'SaveCall;',false);
- end;
- end;
-
- procedure GetHiddenModifiers(Mfs:TProcedureModifiers);
- begin
- if pmInline in Mfs then WriteFmt(true,'inline;',false);
- if pmAssembler in Mfs then WriteFmt(true,'assembler;',false);
- if pmVarargs in Mfs then WriteFmt(true,'varargs;',false);
- if pmCompilerProc in Mfs then WriteFmt(true,'compilerproc;',false);
- end;
- procedure GetTPasProcedure(lpp:TPasProcedure; indent:integer);
- var l:integer;
- lppt:TPasProcedureType;
- s:String;
-
- begin
- if not Assigned(lpp) then exit;
- s:=GetIndent(indent);
- if lpp is TPasConstructor then write(s,'Constructor ')
- else if TPasElement(lpp) is TPasConstructorImpl then write(s,'Constructor ')
- else if lpp is TPasDestructor then write(s,'Destructor ')
- else if TPasElement(lpp) is TPasDestructorImpl then write(s,'Destructor ')
- else if lpp is TPasClassProcedure then write(s,'Class Procedure ') //pparser.pp: 3221
- else if lpp is TPasClassFunction then write(s,'Class Function ')
- else if lpp is TPasFunction then write(s,'Function ')
- else write(s,'Procedure ');
- write(lpp.Name);//,' ',lpp.TypeName);
- if assigned(lpp.ProcType) then
- begin
- lppt:=lpp.ProcType;
- GetTPasProcedureType(lppt,Indent);
- end;
- //writeln(';');
- WriteFmt(false,'',true);
- if lpp.IsVirtual then WriteFmt(true,'virtual;',false);
- if lpp.IsOverload then WriteFmt(true,'overload;',false);
- if lpp.IsAbstract then WriteFmt(true,'abstract;',false);
- if lpp.IsDynamic then WriteFmt(true,'dynamic;',false);
- if lpp.IsOverride then WriteFmt(true,'override;',false);
- if lpp.IsExported then WriteFmt(true,'exported;',false);
- if lpp.IsExternal then WriteFmt(true,'external;',false);
- //pparser 2360: everyting behind external is ignored !!!
- if lpp.IsMessage then
- begin
- write('message ');
- if lpp.MessageType = pmtString then writeln(false,lpp.MessageName,true)
- else WriteFmt(false,lpp.MessageName,true);//pmtInteger
- end;
- if lpp.IsReintroduced then WriteFmt(true,'reintroduce;',false);
- if lpp.IsStatic then WriteFmt(true,'static;',false);
- if lpp.IsForward then WriteFmt(true,'forward;',false);
- GetHiddenModifiers(lpp.Modifiers);
- GetTCallingConvention(lpp.CallingConvention);
- if GetTPasMemberHints(TPasElement(lpp).Hints) then WriteFmt(false,'',true); //BUG ? missing hints
- if not Unformated then writeln;
- end;
- procedure GetTPasProcedureBody(pb:TProcedureBody; indent:integer);
- var j:integer;
- pd:TPasDeclarations;
- pib:TPasImplBlock;
- begin
- if assigned(pb) then
- begin
- if assigned(pb.Body)then
- begin
- if assigned(TPasDeclarations(pb).Functions)then
- begin
- pd:=TPasDeclarations(pb);
- if isim then
- begin
- //writeln;
- GetDecls(pd,indent+1); //~recursion
- //PrintDecls(pd,indent+1); //~recursion
- end
- else
- if pd.Functions.Count >0 then //sub-functions
- begin
- for j:=0 to pd.Functions.Count-1 do
- GetTPasProcedure(TPasProcedure(pd.Functions[j]),indent+1);
- end;
- end;
- pib:=TPasImplBlock(pb.Body);
- if assigned(pib) then
- begin
- GetTPasImplBlock(pib,indent,0,false,false); //indent depend on sub function level
- if not Unformated then writeln; //('//block');
- end;
- end;
- end;
- end;
- procedure GetTpasOverloadedProc(pop:TPasOverloadedProc; indent:integer);
- var pp:TPasProcedure;
- j:integer;
- begin
- if assigned(pop) then
- begin
- if pop.Overloads.Count >0 then
- begin
- for j:=0 to pop.Overloads.Count-1 do
- begin
- pp:=TPasProcedure(pop.Overloads[j]);
- GetTPasProcedure(pp,indent);
- GetTPasProcedureBody(pp.Body,indent);
- end;
- end;
- end;
- end;
- function GetVisibility(v:TPasMemberVisibility):String;
- begin
- Result:='';
- case v of
- //visDefault:Result:='default';
- visPrivate:Result:='private';
- visProtected:Result:='protected';
- visPublic:Result:='public';
- visPublished:Result:='published';
- visAutomated:Result:='automated';
- visStrictPrivate:Result:='strictprivate';
- visStrictProtected:Result:='strictprotected';
- end;
- end;
- procedure GetTPasClass(pc:TPasClassType; indent:integer);
- var j,l:integer;
- s,s1,s2:String;
- lpe:TPasElement;
- lpp:TPasProperty;
- lpa:TPasArgument;
- vis:TPasMemberVisibility;
- vars:TFPList;
- IsVar:boolean;
- procedure PrintVars;
- begin
- if vars.Count > 0 then GetPasVariables(vars,indent+1,false,false);
- IsVar:=False;
- vars.Clear;
- end;
- begin
- if assigned(pc) then
- begin
- s:=GetIndent(indent);
- if (pc.ObjKind=okGeneric) then
- begin
- write(s,'generic ',pc.Name);
- for l:=0 to pc.GenericTemplateTypes.Count-1 do
- begin
- if l=0 then
- Write('<')
- else
- Write(',');
- Write(TPasGenericTemplateType(pc.GenericTemplateTypes[l]).Name);
- end;
- Write('> = ');
- end
- else
- write(s,pc.Name,' = ');
- if pc.IsPacked then write('packed ');
- case pc.ObjKind of
- okObject:write('Object');
- okClass:write('Class');
- okInterface:write('Interface');
- okGeneric:write('class');
- okspecialize : write('specialize');
- end;
- if assigned(pc.AncestorType) and (pc.AncestorType.ElementTypeName <> '') then
- begin
- if pc.ObjKind<>okspecialize then
- write('(',pc.AncestorType.Name,')')
- else
- begin
- write(' ',pc.AncestorType.Name);
- for l:=0 to pc.GenericTemplateTypes.Count-1 do
- begin
- if l=0 then
- Write('<')
- else
- Write(',');
- Write(TPasGenericTemplateType(pc.GenericTemplateTypes[l]).Name);
- end;
- Write('>');
- end;
- end;
- if pc.IsForward or pc.IsShortDefinition then //pparser.pp: 3417 :class(anchestor); is allowed !
- begin
- writeln(';');
- exit;
- end;
- //Members: TFPList;
- //InterfaceGUID: String;
- //ClassVars: TFPList; //is this always empty ?
- //Modifiers: TStringList;
- //Interfaces: TFPList;
- s1:=GetIndent(indent+1);
- s2:=GetIndent(indent+2);
- if pc.Members.Count > 0 then
- begin
- writeln;
- vars:=TFPList.Create;
- IsVar:=false;
- for j:=0 to pc.Members.Count-1 do
- begin
- lpe:=TPasElement(pc.Members[j]);
- //Class visibility, written on change
- if j=0 then
- begin
- vis:=lpe.Visibility;
- if GetVisibility(vis) <> '' then writeln(s1,GetVisibility(vis));
- end
- else
- if vis <> lpe.Visibility then
- begin
- if IsVar then PrintVars;
- if lpe.Visibility <> visDefault then //Class Function = visDefault
- begin
- vis:=lpe.Visibility;
- if GetVisibility(vis) <> '' then writeln(s1,GetVisibility(vis));
- end;
- end;
- if lpe is TPasOverloadedProc then
- begin
- if IsVar then PrintVars;
- GetTPasOverloadedProc(TPasOverloadedProc(lpe),indent+2);
- end
- else if lpe is TPasProcedure then //TPasClassProcedure and
- begin //TPasClassFunction are both child of TPasProcedure
- if IsVar then PrintVars;
- GetTPasProcedure(TPasProcedure(lpe),indent+2);
- end
- else if lpe is TPasProperty then
- begin
- if IsVar then PrintVars;
- lpp:=TPasProperty(lpe);
- write(s2,'property ',lpp.Name);
- if lpp.Args.Count >0 then
- begin
- for l:=0 to lpp.Args.Count-1 do
- begin
- lpa:=TPasArgument(lpp.Args.Items[l]);
- if GetTPasArgumentAccess(lpa.Access) <> '' then
- write('[',GetTPasArgumentAccess(lpa.Access),' ',lpa.Name)
- else write('[',lpa.Name); //variblename
- if assigned(lpa.ArgType) then
- begin
- //if TPasType(lpa.ArgType).ElementTypeName <>'unresolved type reference' then
- //,TPasType(lpa.ArgType).Name,' ');
- //,TPasType(lpa.ArgType).FullName,TPasType(lpa.ArgType).ElementTypeName)
- // PParser 2099: ArgType := nil; if IsUntyped then => Arg.ArgType := ArgType;
- // else write(':? ');
- write(': ');
- if lpa.ArgType is TPasArrayType then
- begin
- GetTPasArrayType(TPasArrayType(lpa.ArgType));
- end
- else write(TPasType(lpa.ArgType).Name);
- end;
- if lpa.Value <> '' then write('=',lpa.Value);
- write(']');
- end;
- end;//args
- if assigned(lpp.VarType) then
- begin
- write(': ',TPasType(lpp.VarType).Name);
- end;
- if lpp.IndexValue <> '' then write(' Index ',lpp.IndexValue);
- if lpp.ReadAccessorName <> '' then write(' Read ',lpp.ReadAccessorName);
- if lpp.WriteAccessorName <> '' then write(' Write ',lpp.WriteAccessorName);
- if lpp.ImplementsName <> '' then write(' Implements ',lpp.ImplementsName);
- if lpp.IsDefault then write(' Default ',lpp.DefaultValue);
- if lpp.IsNodefault then write(' NoDefault');
- if lpp.StoredAccessorName <> '' then write(' Stored ',lpp.StoredAccessorName);
- GetTPasMemberHints(lpp.Hints);
- writeln(';');
- end
- else if lpe is TPasVariable then
- begin
- //this is done with printvars
- //GetTPasVar(TPasVariable(lpe),indent+1,false);
- IsVar:=true;
- vars.add(lpe);
- end
- else
- begin
- if IsVar then PrintVars;
- writeln('{ Unknown Declaration(s) in Class/Object/Interface: ');
- writeln(s,lpe.Name);
- writeln('}');
- end;
- end;
- //writeln(s,'end;');//'//class');
- if IsVar then PrintVars;
- vars.free;
- end
- else writeln;//(';'); //x=class(y);
- writeln(s,'end;');
- end;
- end;
- procedure GetDecls(Decl:TPasDeclarations; indent:integer);
- var i,j:integer;
- pe:TPasElement;
- pp:TPasProcedure;
- ps:TPasSection;
- s:string;
- x:(None,ResStrings,Types,Consts,Classes,Functions,Variables,Properties);
- l:TFPList;
- procedure PrintVars;
- begin
- if l.Count > 0 then GetPasVariables(l,indent+1,false,false);
- end;
- begin
- s:=GetIndent(indent);
- x:=None;
- if assigned(Decl)then
- begin
- l:=TFPList.Create;
- pe:=TPasElement(Decl);
- if pe is TPasSection then
- begin
- {(Decl is TInterfaceSection)or(Decl is TImplementationSection) or
- (Decl is TProgramSection}
- ps:=TPasSection(pe);
- if ps.UsesList.Count >0 then
- begin
- write(s,'uses ');
- ps:=TPasSection(Decl);
- if not Unformated then begin writeln; write(s,' '); end;
- for i:=0 to ps.UsesList.Count-2 do
- if UpCase(TPasElement(ps.UsesList[i]).Name) = 'SYSTEM' then continue //do not print system
- else write(TPasElement(ps.UsesList[i]).Name,','); //as it is added by parser
- writeln(TPasElement(ps.UsesList[ps.UsesList.Count-1]).Name,';');
- if not Unformated then writeln;
- end;
- end;
- if assigned(Decl.Declarations)and(Decl.Declarations.Count > 0) then
- for j:=0 to Decl.Declarations.Count-1 do
- begin
- pe:=TPasElement(Decl.Declarations[j]);
- if pe is TPasResString then
- begin
- if x = Variables then PrintVars;
- if x <> ResStrings then
- begin
- if not Unformated then writeln;
- writeln(s,'ResourceString');
- x:=ResStrings;
- end;
- writeln(s,pe.Name,'=',DelQuot(TPasResString(pe).Expr.GetDeclaration(false)),';'); //too much '''
- end
- else if pe is TPasConst then
- begin
- if x = Variables then PrintVars;
- if x <> Consts then
- begin
- if not Unformated then writeln;
- writeln(s,'const');
- x:=Consts;
- end;
- GetTPasVar(TPasVariable(pe),indent+1,false);
- end
- else if pe is TPasVariable then
- begin
- if x <> Variables then
- begin
- if not Unformated then writeln;
- writeln(s,'var');
- x:=Variables;
- l.Clear;
- end;
- l.Add(pe);
- //this is done with printvars
- //GetTPasVar(TPasVariable(pe),indent+1,false);
- end
- else if pe is TPasClassType then
- begin
- if x = Variables then PrintVars;
- if x <> Types then
- begin
- if not Unformated then writeln;
- writeln(s,'Type');
- x:=Types;
- end;
- GetTPasClass(TPasClassType(pe),indent+1);
- end
- else if pe is TPasType then
- begin
- if x = Variables then PrintVars;
- if x <> Types then
- begin
- if not Unformated then writeln;
- writeln(s,'Type');
- x:=Types;
- end;
- GetTypes(TPasElement(pe),indent+1);
- end
- else if pe is TPasProcedureBase then
- begin
- if x = Variables then PrintVars;
- if (x <> Functions)and not Unformated then writeln;
- x:=Functions;
- if pe is TPasOverloadedProc then
- begin
- GetTpasOverloadedProc(TPasOverloadedProc(pe),indent);
- end
- else
- begin
- pp:=TPasProcedure(pe);
- GetTPasProcedure(pp,indent);
- GetTPasProcedureBody(pp.Body,indent);
- end;
- end
- else
- begin
- if x = Variables then PrintVars;
- x:=None;
- writeln('{ Unknown Declaration: ',pe.Name,' }');
- end;
- end;
- if x = Variables then PrintVars;
- l.Free;
- end;
- end;
- {replaced by GetDecls
- this does the same but not in true order
- procedure PrintDecls(Decl:TPasDeclarations; indent:integer);
- var i:integer;
- pe:TPasElement;
- pp:TPasProcedure;
- ps:TPasSection;
- s:string;
- istype:boolean;
- begin
- istype:=false;
- s:=GetIndent(indent);
- if (Decl is TInterfaceSection)or(Decl is TImplementationSection) or
- (Decl is TProgramSection) then
- if TPasSection(Decl).UsesList.Count >0 then
- begin
- write(s,'uses ');
- ps:=TPasSection(Decl);
- if not Unformated then begin writeln; write(s,' '); end;
- for i:=0 to ps.UsesList.Count-2 do
- if UpCase(TPasElement(ps.UsesList[i]).Name) = 'SYSTEM' then continue //do not print system
- else write(TPasElement(ps.UsesList[i]).Name,','); //as it is added by parser
- writeln(TPasElement(ps.UsesList[ps.UsesList.Count-1]).Name,';');
- if not Unformated then writeln;
- end;
- if assigned(Decl.ResStrings) then
- if Decl.ResStrings.Count >0 then
- begin
- writeln('ResourceString');
- for i := 0 to Decl.ResStrings.Count - 1 do
- begin
- pe:=TPasElement(Decl.ResStrings[i]);
- writeln(s,pe.Name,'=',DelQuot(TPasResString(pe).Value),';'); //too much '''
- end;
- if not Unformated then writeln;
- end;
- if assigned(Decl.Consts)then
- if Decl.Consts.Count >0 then
- begin
- writeln(s,'const');
- for i:=0 to Decl.Consts.Count-1 do GetTPasVar(TPasVariable(Decl.Consts[i]),indent+1,false);
- if not Unformated then writeln;
- end;
- if assigned(Decl.Types) then
- if Decl.Types.Count >0 then
- begin
- writeln(s,'Type');
- for i := 0 to Decl.Types.Count - 1 do
- begin
- GetTypes(TPasElement(Decl.Types[i]),indent+1);
- end;
- if not Unformated then writeln;
- istype:=true;
- end;
- if assigned(Decl.Classes) then
- if Decl.Classes.Count >0 then
- begin
- if not istype then writeln('Type');
- for i := 0 to Decl.Classes.Count - 1 do
- begin
- pe:=TPasElement(Decl.Classes[i]);
- GetTPasClass(TPasClassType(pe),indent+1);
- if not Unformated then writeln;
- end;
- end;
- if assigned(Decl.Variables)then
- if Decl.Variables.Count >0 then
- begin
- writeln(s,'var');
- //Now i use GetPasVariables for more compact output
- //for i:=0 to Decl.Variables.Count-1 do GetTPasVar(TPasVariable(Decl.Variables[i]),indent+1,false);
- GetPasVariables(Decl.Variables,indent+1,false,false);
- if not Unformated then writeln;
- end;
- if assigned(Decl.Functions) then
- begin
- for i := 0 to Decl.Functions.Count - 1 do
- begin
- pe:=TPasElement(Decl.Functions[i]);
- if pe is TPasOverloadedProc then
- begin
- GetTpasOverloadedProc(TPasOverloadedProc(pe),indent);
- end
- else
- begin
- pp:=TPasProcedure(pe);
- GetTPasProcedure(pp,indent);
- GetTPasProcedureBody(pp.Body,indent);
- end;
- end;
- end;
- end; }
- //# parameter
- procedure PrintUsage;
- begin
- writeln('usage: test_parser1 <Options> <Commandline> File');
- writeln;
- writeln(' <Options> : Options for test_parser1');
- writeln(' -u : Unformated output');
- writeln(' -OS <os> : <os> = WINDOWS, LINUX (default), FREEBSD, NETBSD,');
- writeln(' SUNOS, BEOS, QNX, GO32V2');
- writeln(' -CPU <cpu> : <cpu> = i386 (default), x86_64');
- writeln(' <Commandline> : is the commandline for the parser');
- writeln(' -d<define> : <define> = Directive');
- writeln(' -Fi<include_path> : <include_path> = ?');
- writeln(' -I<include_path> : <include_path> = ?');
- writeln(' -Sd : mode delphi');
- writeln(' File : a pascal source file (Program or Unit)');
- end;
- procedure GetParam;
- begin
- if paramcount>0 then
- begin
- cmdl:='';
- i:=1;
- repeat
- if paramstr(i) = '-h' then
- begin
- PrintUsage;
- halt(0);
- end
- else if paramstr(i) = '-u' then Unformated:= true
- else if paramstr(i) = '-OS' then
- begin
- if i < paramcount then
- begin
- inc(i);
- TargetOS:=paramstr(i);
- if (TargetOS = '')or(TargetOS[1] = '-') then halt(1);
- end
- else halt(1);
- end
- else if paramstr(i) = '-CPU' then
- begin
- if i < paramcount then
- begin
- inc(i);
- TargetCPU:=paramstr(i);
- if (TargetCPU = '')or(TargetCPU[1] = '-') then halt(1);
- end
- else halt(1);
- end
- else
- cmdl:=cmdl+' '+paramstr(i);
- inc(i);
- until i > paramcount;
- end;
- if (Paramcount < 1)or(cmdl = '') then
- begin
- // remember to put the whole cmdline in quotes, and
- // to always add some path options. Even if only -Fu. -Fi.
- writeln('Error: No file for input given !');
- PrintUsage;
- halt(1);
- end;
- end;
- //# *** main ***
- begin
- isim:=false;
- Unformated:=false;//false to format output to be human readable
- TargetOS:='linux';
- TargetCPU:='i386';
- GetParam;
- //writeln(TargetOS,' ',TargetCPU,' ',cmdl);halt;
- E := TSimpleEngine.Create;
- try
- try
- M := ParseSource(E, cmdl ,TargetOS ,TargetCPU,False);
- except
- on excep:EParserError do
- begin
- writeln(excep.message,' line:',excep.row,' column:',excep.column,' file:',excep.filename);
- raise;
- end;
- end;
- if M is TPasProgram then
- begin
- writeln('Program ',M.Name,';');
- if not Unformated then writeln;
- if assigned(M.ImplementationSection) then
- begin
- isim:=true;
- if not Unformated then writeln;
- GetDecls(M.ImplementationSection as TPasDeclarations,0);
- //PrintDecls(M.ImplementationSection as TPasDeclarations,0);
- end;
- if assigned(M.InitializationSection) then // MAIN BLOCK
- begin
- isim:=false;
- if not Unformated then writeln;
- writeln('begin');//writeln('begin {Begin MAIN Program}')
- GetTPasImplBlock(M.InitializationSection as TPasImplBlock,1,0,false,false);
- end;
- end
- else
- begin
- { Cool, we successfully parsed the unit.
- Now output some info about it. }
- writeln('Unit ',M.Name,';');
- if not Unformated then writeln;
- Writeln('Interface');
- if not Unformated then writeln;
- GetDecls(M.InterfaceSection as TPasDeclarations,0);
- //PrintDecls(M.InterfaceSection as TPasDeclarations,0);
- if assigned(M.ImplementationSection) then
- begin
- isim:=true;
- if not Unformated then writeln;
- Writeln('Implementation');
- if not Unformated then writeln;
- GetDecls(M.ImplementationSection as TPasDeclarations,0);
- //PrintDecls(M.ImplementationSection as TPasDeclarations,0);
- if TPasElement(M.ImplementationSection) is TPasImplElement then writeln('{MAIN}');
- end;
- if assigned(M.InitializationSection) then //is this begin .. end. of a unit too ?
- begin
- isim:=true;
- if not Unformated then writeln;
- Writeln('Initialization');
- if not Unformated then writeln;
- GetTPasImplBlock(M.InitializationSection as TPasImplBlock,1,0,false,false);
- end;
-
- if assigned(M.FinalizationSection) then
- begin
- isim:=true;
- if not Unformated then writeln;
- Writeln('Finalization');
- if not Unformated then writeln;
- GetTPasImplBlock(M.FinalizationSection as TPasImplBlock,1,0,false,false);
- end;
- end;
- if not Unformated then writeln('end.')
- else
- begin
- writeln('end');
- writeln('.');
- end;
- FreeAndNil(M);
- finally
- FreeAndNil(E);
- end;
- end.
|