Adds objective-c parser from Skalogryz.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@370 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat
2008-03-04 23:34:41 +00:00
parent 0a3f2310db
commit b0eb94ed80
4 changed files with 864 additions and 0 deletions

View File

@ -0,0 +1,532 @@
unit ObjCParserTypes;
interface
{$ifdef fpc}{$mode delphi}{$endif fpc}
uses
Classes;
type
TTokenType = (tt_Ident, tt_Symbol, tt_None);
TCharSet = set of Char;
TTokenPair = record
Open : AnsiString;
Close : AnsiString;
end;
TTokenTable = class(TObject)
SpaceChars : TCharSet;
CmtBlock : array of TTokenPair;
CmtCount : Integer;
CmtLine : TStrings;
Symbols : TCharSet;
constructor Create;
destructor Destroy; override;
end;
TTextParser = class(TObject)
public
Buf : AnsiString;
Index : Integer;
TokenTable : TTokenTable;
function SkipComments: Boolean;
function FindNextToken(var Token: AnsiString; var TokenType: TTokenType): Boolean;
constructor Create;
end;
{ TEntity }
TEntity = class(TObject)
public
Items : TList;
constructor Create;
destructor Destroy; override;
procedure Parse(AParser: TTextParser); virtual; abstract;
end;
{ TParameterDef }
TResultTypeDef = class(TEntity)
_isRef : Boolean;
_TypeName : AnsiString;
procedure Parse(AParser: TTextParser); override;
end;
TParameterDef = class(TEntity)
_Res : TResultTypeDef;
_Name : AnsiString;
procedure Parse(AParser: TTextParser); override;
function GetResultType: TResultTypeDef;
end;
{ TParamDescr }
TParamDescr = class(TEntity)
public
_Descr : AnsiString;
procedure Parse(AParser: TTextParser); override;
end;
{ TClassMethodDef }
TClassMethodDef = class(TEntity)
_IsClassMethod : Boolean; // is class function as delphi would say
_CallChar : AnsiChar; // + or -
_Name : AnsiString;
procedure Parse(AParser: TTextParser); override;
function GetResultType: TResultTypeDef;
end;
{ TClassDef }
TClassDef = class(TEntity)
public
_ClassName : AnsiString;
_SuperClass : AnsiString;
_Category : AnsiString;
procedure Parse(AParser: TTextParser); override;
end;
{ TObjCHeader }
TObjCHeader = class(TEntity)
public
constructor Create;
procedure Parse(AParser: TTextParser); override;
end;
const
EoLnChars : TCharSet = [#10,#13];
InvsChars : TCharSet = [#32,#9];
procedure SkipLine(const s: AnsiString; var index: Integer);
procedure SetCComments(Table: TTokenTable);
procedure SetCSymbols(var ch: TCharSet);
function CreateObjCTokenTable: TTokenTable;
implementation
function CreateObjCTokenTable: TTokenTable;
begin
Result := TTokenTable.Create;
SetCComments(Result);
SetCSymbols(Result.Symbols);
Result.SpaceChars := EoLnChars + InvsChars;
end;
procedure SetCSymbols(var ch: TCharSet);
begin
ch := ['(',')', '{','}', ':', '-','+','<','>','*',';']
end;
procedure SetCComments(Table: TTokenTable);
begin
SetLength(Table.CmtBlock, 1);
Table.CmtCount := 1;
Table.CmtBlock[0].Open := '/*';
Table.CmtBlock[0].Close := '*/';
Table.CmtLine.Add('//');
end;
function ScanWhile(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
var
i : Integer;
begin
Result := '';
if (index <= 0) or (index > length(s)) then Exit;
for i := index to length(s) do
if not (s[i] in ch) then begin
if i = index then Result := ''
else Result := Copy(s, index, i - index);
index := i;
Exit;
end;
Result := Copy(s, index, length(s) - index + 1);
index := length(s) + 1;
end;
function ScanTo(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
var
i : Integer;
begin
Result := '';
if (index <= 0) or (index > length(s)) then Exit;
for i := index to length(s) do
if (s[i] in ch) then begin
if i = index then Result := ''
else Result := Copy(s, index, i - index);
index := i;
Exit;
end;
Result := Copy(s, index, length(s) - index + 1);
index := length(s) + 1;
end;
{ TTextParser }
function IsSubStr(const sbs, s: AnsiString; index: Integer): Boolean;
var
i : Integer;
j : Integer;
begin
Result := false;
if length(sbs) > length(s) - index then Exit;
j := index;
for i := 1 to length(sbs) do begin
if sbs[i] <> s[j] then Exit;
inc(j);
end;
Result := true;
end;
procedure SkipCommentBlock(const s: AnsiString; var index: Integer; const closecmt: AnsiString);
begin
if closecmt = '' then begin
index := length(s) + 1;
Exit;
end;
while index <= length(s) do begin
ScanTo(s, index, [closecmt[1]]);
if IsSubStr(closecmt, s, index) then begin
inc(index, length(closecmt));
Exit;
end else
inc(index);
end;
end;
procedure SkipLine(const s: AnsiString; var index: Integer);
begin
ScanTo(s, index, EoLnChars);
ScanWhile(s, index, EoLnChars);
end;
constructor TTextParser.Create;
begin
Index := 1;
end;
function TTextParser.FindNextToken(var Token: AnsiString; var TokenType: TTokenType): Boolean;
var
srch : TCharSet;
blck : TCharSet;
i : Integer;
t : AnsiString;
begin
Result := Index <= length(Buf);
if not Result then Exit;
srch := TokenTable.SpaceChars;
blck := [];
for i := 0 to TokenTable.CmtCount - 1 do begin
t := TokenTable.CmtBlock[i].Open[1];
if t <> '' then blck := blck + [t[1]];
end;
for i := 0 to TokenTable.CmtLine.Count - 1 do begin
t := TokenTable.CmtLine[i];
if t <> '' then blck := blck + [t[1]];
end;
srch := srch + blck;
Token := '';
Result := false;
TokenType := tt_Ident;
while (not Result) and (index <= length(Buf)) do begin
ScanWhile(Buf, index, TokenTable.SpaceChars);
if (Buf[index] in TokenTable.Symbols) then begin
if (not (Buf[index] in blck)) or (not SkipComments) then begin
Result := true;
TokenType := tt_Symbol;
Token := Buf[index];
inc(index);
Exit;
end;
end else begin
Token := Token + ScanTo(Buf, index, srch+TokenTable.Symbols);
if (Buf[index] in blck) then begin
Result := SkipComments;
Result := Result or (Buf[index] in TokenTable.SpaceChars);
if not Result then begin
Token := Token + Buf[index];
inc(index);
end;
end else
Result := true;
Result := Result and (Token <> '');
end;
end; {of while}
if not Result then TokenType := tt_None;
end;
function TTextParser.SkipComments: Boolean;
var
i : Integer;
begin
Result := false;
for i := 0 to TokenTable.CmtCount - 1 do
if IsSubStr(TokenTable.CmtBlock[i].Open, Buf, index) then begin
inc(index, length(TokenTable.CmtBlock[i].Open));
SkipCommentBlock(Buf, index, TokenTable.CmtBlock[i].Close);
Result := true;
Exit;
end;
for i := 0 to TokenTable.CmtLine.Count - 1 do
if IsSubStr(TokenTable.CmtLine[i], Buf, index) then begin
SkipLine(Buf, index);
Result := true;
Exit;
end;
end;
{ TTokenTable }
constructor TTokenTable.Create;
begin
CmtLine := TStringList.Create;
end;
destructor TTokenTable.Destroy;
begin
CmtLine.Free;
inherited;
end;
{ TEntity }
constructor TEntity.Create;
begin
inherited;
Items := TList.Create;
end;
destructor TEntity.Destroy;
begin
Items.Free;
inherited Destroy;
end;
{ TClassDef }
procedure TClassDef.Parse(AParser:TTextParser);
var
s : AnsiString;
tt : TTokenType;
cnt : Integer;
mtd : TClassMethodDef;
begin
AParser.FindNextToken(_ClassName, tt);
if (not AParser.FindNextToken(s, tt)) then Exit;
if tt = tt_Symbol then begin
if s[1] = ':' then
AParser.FindNextToken(_SuperClass, tt)
else if s[1] = '(' then begin
AParser.FindNextToken(_Category, tt);
AParser.FindNextToken(s, tt);
end else
Exit;
end;
cnt := 0;
repeat
if not AParser.FindNextToken(s, tt) then begin
s := '';
exit;
end;
if s = '{' then inc(cnt)
else if s = '}' then dec(cnt)
else if (cnt = 0) then begin
//todo: better parsing
if s[1] ='#' then SkipLine(AParser.buf, AParser.Index);
if (s = '+') or (s = '-') then begin
dec(AParser.Index ); // roll back a single character
mtd := TClassMethodDef.Create;
mtd.Parse(AParser);
Items.Add(mtd);
end;
end;
until (s = '@end') or (s = '');
end;
{ TObjCHeader }
constructor TObjCHeader.Create;
begin
inherited Create;
end;
procedure TObjCHeader.Parse(AParser:TTextParser);
var
s : AnsiString;
tt : TTokenType;
cl : TClassDef;
begin
while AParser.FindNextToken(s, tt) do begin
if s = '@interface' then begin
cl := TClassDef.Create;
cl.Parse(AParser);
Items.Add(cl);
end;
end;
end;
{ TClassMethodDef }
function TClassMethodDef.GetResultType: TResultTypeDef;
var
i : integer;
begin
for i := 0 to Items.Count - 1 do
if TObject(Items[i]) is TResultTypeDef then begin
Result := TResultTypeDef(Items[i]);
Exit;
end;
Result := nil;
end;
procedure TClassMethodDef.Parse(AParser:TTextParser);
var
s : AnsiString;
tt : TTokenType;
res : TResultTypeDef;
para : TParameterDef;
des : TParamDescr;
begin
AParser.FindNextToken(s, tt);
if (s <> '+') and (s <> '-') then Exit;
_CallChar := s[1];
_IsClassMethod := _CallChar = '+';
AParser.FindNextToken(s, tt);
if (tt = tt_Symbol) and(s = '(') then begin
// _Class methods can be with out type
dec(AParser.Index);
res := TResultTypeDef.Create;
res.Parse(AParser);
Items.Add(res);
end;
AParser.FindNextToken(_Name, tt);
if _Name = '_id' then
_Name := '_id';
while AParser.FindNextToken(s, tt) do begin
if s = ';' then
Exit
else if s = ':' then begin
para := TParameterDef.Create;
para.Parse(AParser);
Items.Add(para);
end else if tt = tt_Ident then begin
des := TParamDescr.Create;
des._Descr := s;
Items.Add(des)
end;
end;
// AParser.FindNextToken()
end;
{ TParameterDef }
function TParameterDef.GetResultType: TResultTypeDef;
begin
Result := _Res;
end;
procedure TParameterDef.Parse(AParser:TTextParser);
var
tt : TTokenType;
begin
_Res := TResultTypeDef.Create;
Items.Add(_Res);
_Res.Parse(AParser);
AParser.FindNextToken(_Name, tt)
end;
{ TResultTypeDef }
procedure TResultTypeDef.Parse(AParser: TTextParser);
var
s : AnsiString;
tt : TTokenType;
begin
AParser.FindNextToken(s, tt);
if (tt <> tt_Symbol) and (s <> '(') then Exit;
AParser.FindNextToken(_TypeName, tt);
if _TypeName = 'unsigned' then begin
AParser.FindNextToken(s, tt);
_TypeName := _TypeName + ' ' + s;
end;
if tt <> tt_Ident then Exit; // an error
AParser.FindNextToken(s, tt);
if (tt = tt_Symbol) and (s = '*') then begin
_isRef := true;
AParser.FindNextToken(s, tt);
end;
if s <> ')' then ; // an error
end;
{ TParamDescr }
procedure TParamDescr.Parse(AParser: TTextParser);
var
tt : TTokenType;
begin
AParser.FindNextToken(_Descr, tt);
end;
end.

View File

@ -0,0 +1,161 @@
H:\ObjectiveC\AppKit.h
H:\ObjectiveC\AppKitDefines.h
H:\ObjectiveC\AppKitErrors.h
H:\ObjectiveC\NSAccessibility.h
H:\ObjectiveC\NSActionCell.h
H:\ObjectiveC\NSAffineTransform.h
H:\ObjectiveC\NSAlert.h
H:\ObjectiveC\NSAnimation.h
H:\ObjectiveC\NSAppleScriptExtensions.h
H:\ObjectiveC\NSApplication.h
H:\ObjectiveC\NSApplicationScripting.h
H:\ObjectiveC\NSArrayController.h
H:\ObjectiveC\NSATSTypesetter.h
H:\ObjectiveC\NSAttributedString.h
H:\ObjectiveC\NSBezierPath.h
H:\ObjectiveC\NSBitmapImageRep.h
H:\ObjectiveC\NSBox.h
H:\ObjectiveC\NSBrowser.h
H:\ObjectiveC\NSBrowserCell.h
H:\ObjectiveC\NSButton.h
H:\ObjectiveC\NSButtonCell.h
H:\ObjectiveC\NSCachedImageRep.h
H:\ObjectiveC\NSCell.h
H:\ObjectiveC\NSCIImageRep.h
H:\ObjectiveC\NSClipView.h
H:\ObjectiveC\NSColor.h
H:\ObjectiveC\NSColorList.h
H:\ObjectiveC\NSColorPanel.h
H:\ObjectiveC\NSColorPicker.h
H:\ObjectiveC\NSColorPicking.h
H:\ObjectiveC\NSColorSpace.h
H:\ObjectiveC\NSColorWell.h
H:\ObjectiveC\NSComboBox.h
H:\ObjectiveC\NSComboBoxCell.h
H:\ObjectiveC\NSControl.h
H:\ObjectiveC\NSController.h
H:\ObjectiveC\NSCursor.h
H:\ObjectiveC\NSCustomImageRep.h
H:\ObjectiveC\NSDatePicker.h
H:\ObjectiveC\NSDatePickerCell.h
H:\ObjectiveC\NSDocument.h
H:\ObjectiveC\NSDocumentController.h
H:\ObjectiveC\NSDocumentScripting.h
H:\ObjectiveC\NSDragging.h
H:\ObjectiveC\NSDrawer.h
H:\ObjectiveC\NSEPSImageRep.h
H:\ObjectiveC\NSErrors.h
H:\ObjectiveC\NSEvent.h
H:\ObjectiveC\NSFileWrapper.h
H:\ObjectiveC\NSFont.h
H:\ObjectiveC\NSFontDescriptor.h
H:\ObjectiveC\NSFontManager.h
H:\ObjectiveC\NSFontPanel.h
H:\ObjectiveC\NSForm.h
H:\ObjectiveC\NSFormCell.h
H:\ObjectiveC\NSGlyphGenerator.h
H:\ObjectiveC\NSGlyphInfo.h
H:\ObjectiveC\NSGraphics.h
H:\ObjectiveC\NSGraphicsContext.h
H:\ObjectiveC\NSHelpManager.h
H:\ObjectiveC\NSImage.h
H:\ObjectiveC\NSImageCell.h
H:\ObjectiveC\NSImageRep.h
H:\ObjectiveC\NSImageView.h
H:\ObjectiveC\NSInputManager.h
H:\ObjectiveC\NSInputServer.h
H:\ObjectiveC\NSInterfaceStyle.h
H:\ObjectiveC\NSKeyValueBinding.h
H:\ObjectiveC\NSLayoutManager.h
H:\ObjectiveC\NSLevelIndicator.h
H:\ObjectiveC\NSLevelIndicatorCell.h
H:\ObjectiveC\NSMatrix.h
H:\ObjectiveC\NSMenu.h
H:\ObjectiveC\NSMenuItem.h
H:\ObjectiveC\NSMenuItemCell.h
H:\ObjectiveC\NSMenuView.h
H:\ObjectiveC\NSMovie.h
H:\ObjectiveC\NSMovieView.h
H:\ObjectiveC\NSNib.h
H:\ObjectiveC\NSNibConnector.h
H:\ObjectiveC\NSNibControlConnector.h
H:\ObjectiveC\NSNibDeclarations.h
H:\ObjectiveC\NSNibLoading.h
H:\ObjectiveC\NSNibOutletConnector.h
H:\ObjectiveC\NSObjectController.h
H:\ObjectiveC\NSOpenGL.h
H:\ObjectiveC\NSOpenGLView.h
H:\ObjectiveC\NSOpenPanel.h
H:\ObjectiveC\NSOutlineView.h
H:\ObjectiveC\NSPageLayout.h
H:\ObjectiveC\NSPanel.h
H:\ObjectiveC\NSParagraphStyle.h
H:\ObjectiveC\NSPasteboard.h
H:\ObjectiveC\NSPDFImageRep.h
H:\ObjectiveC\NSPersistentDocument.h
H:\ObjectiveC\NSPICTImageRep.h
H:\ObjectiveC\NSPopUpButton.h
H:\ObjectiveC\NSPopUpButtonCell.h
H:\ObjectiveC\NSPrinter.h
H:\ObjectiveC\NSPrintInfo.h
H:\ObjectiveC\NSPrintOperation.h
H:\ObjectiveC\NSPrintPanel.h
H:\ObjectiveC\NSProgressIndicator.h
H:\ObjectiveC\NSQuickDrawView.h
H:\ObjectiveC\NSResponder.h
H:\ObjectiveC\NSRulerMarker.h
H:\ObjectiveC\NSRulerView.h
H:\ObjectiveC\NSSavePanel.h
H:\ObjectiveC\NSScreen.h
H:\ObjectiveC\NSScroller.h
H:\ObjectiveC\NSScrollView.h
H:\ObjectiveC\NSSearchField.h
H:\ObjectiveC\NSSearchFieldCell.h
H:\ObjectiveC\NSSecureTextField.h
H:\ObjectiveC\NSSegmentedCell.h
H:\ObjectiveC\NSSegmentedControl.h
H:\ObjectiveC\NSShadow.h
H:\ObjectiveC\NSSimpleHorizontalTypesetter.h
H:\ObjectiveC\NSSlider.h
H:\ObjectiveC\NSSliderCell.h
H:\ObjectiveC\NSSound.h
H:\ObjectiveC\NSSpeechRecognizer.h
H:\ObjectiveC\NSSpeechSynthesizer.h
H:\ObjectiveC\NSSpellChecker.h
H:\ObjectiveC\NSSpellProtocol.h
H:\ObjectiveC\NSSpellServer.h
H:\ObjectiveC\NSSplitView.h
H:\ObjectiveC\NSStatusBar.h
H:\ObjectiveC\NSStatusItem.h
H:\ObjectiveC\NSStepper.h
H:\ObjectiveC\NSStepperCell.h
H:\ObjectiveC\NSStringDrawing.h
H:\ObjectiveC\NSTableColumn.h
H:\ObjectiveC\NSTableHeaderCell.h
H:\ObjectiveC\NSTableHeaderView.h
H:\ObjectiveC\NSTableView.h
H:\ObjectiveC\NSTabView.h
H:\ObjectiveC\NSTabViewItem.h
H:\ObjectiveC\NSText.h
H:\ObjectiveC\NSTextAttachment.h
H:\ObjectiveC\NSTextContainer.h
H:\ObjectiveC\NSTextField.h
H:\ObjectiveC\NSTextFieldCell.h
H:\ObjectiveC\NSTextList.h
H:\ObjectiveC\NSTextStorage.h
H:\ObjectiveC\NSTextStorageScripting.h
H:\ObjectiveC\NSTextTable.h
H:\ObjectiveC\NSTextView.h
H:\ObjectiveC\NSTokenField.h
H:\ObjectiveC\NSTokenFieldCell.h
H:\ObjectiveC\NSToolbar.h
H:\ObjectiveC\NSToolbarItem.h
H:\ObjectiveC\NSTreeController.h
H:\ObjectiveC\NSTypesetter.h
H:\ObjectiveC\NSUserDefaultsController.h
H:\ObjectiveC\NSUserInterfaceValidation.h
H:\ObjectiveC\NSView.h
H:\ObjectiveC\NSWindow.h
H:\ObjectiveC\NSWindowController.h
H:\ObjectiveC\NSWindowScripting.h
H:\ObjectiveC\NSWorkspace.h

View File

@ -0,0 +1,88 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<PathDelim Value="\"/>
<Version Value="5"/>
<General>
<Flags>
<MainUnitHasUsesSectionForAllUnits Value="False"/>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
</Flags>
<MainUnit Value="0"/>
<IconPath Value="./"/>
<TargetFileExt Value=".exe"/>
<ActiveEditorIndexAtStart Value="0"/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
<Language Value=""/>
<CharSet Value=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>
<IgnoreBinaries Value="False"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
<Units Count="3">
<Unit0>
<Filename Value="objcparser.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="Project1"/>
<CursorPos X="45" Y="70"/>
<TopLine Value="57"/>
<EditorIndex Value="0"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="ObjCParserUtils.pas"/>
<UnitName Value="ObjCParserUtils"/>
<CursorPos X="1" Y="1"/>
<TopLine Value="1"/>
<EditorIndex Value="2"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit1>
<Unit2>
<Filename Value="ObjCParserTypes.pas"/>
<UnitName Value="ObjCParserTypes"/>
<CursorPos X="1" Y="1"/>
<TopLine Value="1"/>
<EditorIndex Value="1"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit2>
</Units>
<JumpHistory Count="0" HistoryIndex="-1"/>
</ProjectOptions>
<CompilerOptions>
<Version Value="5"/>
<PathDelim Value="\"/>
<CodeGeneration>
<Generate Value="Faster"/>
</CodeGeneration>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<BreakPoints Count="2">
<Item1>
<Source Value="C:\Games\CodeTest2\Sources\examples\codecompletion.lpr"/>
<Line Value="47"/>
</Item1>
<Item2>
<Source Value="..\..\LazTest4\consolethreads.pas"/>
<Line Value="18"/>
</Item2>
</BreakPoints>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,83 @@
program Project1;
{$mode delphi}{$H+}
uses
Classes, SysUtils, ObjCParserUtils, ObjCParserTypes;
{ add your units here }
procedure ReadAndParseFile(const FileName: AnsiString; outdata: TStrings);
var
hdr : TObjCHeader;
txt : TTextParser;
s : AnsiString;
begin
if not FileExists(FileName) then Exit;
s := StrFromFile(FileName);
hdr := TObjCHeader.Create;
txt := TTextParser.Create;
txt.TokenTable := CreateObjCTokenTable;
try
txt.Buf := s;
try
hdr.Parse(txt);
except
end;
outdata.Add('');
outdata.Add('// ' + FileName);
outdata.Add('');
ReportHeader(hdr, outdata);
finally
hdr.Free;
txt.TokenTable.Free;
txt.Free;
end;
end;
procedure GetParams(var InpFile, OutFile: AnsiString);
begin
InpFile := ParamStr(1);
OutFile := ParamStr(2);
end;
var
inpf, outf : AnsiString;
f : Text;
st : TStrings;
fn : AnsiString;
i : integer;
begin
inpf := ''; outf := '';
GetParams(inpf, outf);
writeln('input file: ', inpf);
writeln('output file: ', outf);
if not FileExists(inpf) then begin
writeln('input file does not exists or anavailable');
Exit;
end;
st := TStringList.Create;
try
Assign(f, inpf); Reset(f);
while not eof(f) do begin
readln(f, fn);
try
ReadAndParseFile(fn, st);
except
end;
end;
Close(f);
Assign(f, outf); Rewrite(f);
try
for i := 0 to st.Count - 1 do
writeln(f, st[i]);
except
end;
Close(f);
finally
st.Free;
end;
end.