1
0
mirror of https://github.com/moparisthebest/Simba synced 2024-11-11 11:55:02 -05:00
Simba/Units/RUTIS/Rutis_Compiler_Delphi.pas

4179 lines
117 KiB
ObjectPascal
Raw Normal View History

2010-08-20 11:21:43 -04:00
{/==============================================================================
//==============================================================================
RUTIS-Engine (RunTimeScript-Engine)
RUTIS_Compiler_Delphi.pas (part of) RUTIS-Engine
--> This unit contains the RUTIS-Compiler for Pascal-Syntax code
//==============================================================================
Author : Bj<EFBFBD>rn Zeutzheim
E-Mail : bjoern@zeutzheim-boppard.de
//==============================================================================
License: Dieses Projekt (RUTIS-Engine) steht unter einer /
This project is licensed under the
Creative Commons 3.0 BY-NC-SA (German) License
Diese Lizens beinhaltet / This license includes:
-> Namensnennung / Attribution
-> Keine kommerzielle Nutzung / Noncommercial
-> Weitergabe unter gleichen Bedingungen / Share Alike
Ein ausformulierter Lizensvertrag ist <EFBFBD>ber folgende Adresse erreichbar:
The Legal Code (the full license) can be read at the following Address:
> http: //creativecommons.org/licenses/by-nc-sa/3.0/de/
//==============================================================================
//==============================================================================}
2010-08-27 08:41:55 -04:00
Unit Rutis_Compiler_Delphi;
2010-08-20 11:21:43 -04:00
Interface
{$i Delphi_Versions.inc}
{$IFDEF FPC}
{$mode objfpc}{$H+}
{$ENDIF}
Uses
Forms, Classes,
{$ifdef DELPHI_7_UP}Variants,{$endif}
SysUtils, Math,
Rutis_Defs, Rutis_Errors, RUTIS_Classes;
Type
//==============================================================================
//==============================================================================
TRutisSymbol = (sUnknown, sIdent, sInteger, sFloat, sString,
sPlus, sMinus, sStar, sSlash, sMod, sDiv, sNil,
sEqual, sSmaller, sBigger, sBiggerEqual, sSmallerEqual, sUnEqual,
sOpenBracket, sCloseBracket, sOpenBracketR, sCloseBracketR, sComma, sDot,
sSemiColon, sBecomes, sDopDot, sHook, sAt,
sPacked, sRecord,
sSet, sArray, sClass,
sTrue, sFalse,
sProgram, sUnit, sInterface, sImplement, sInitialization, sFinalization,
sUses, sType, sVar, sConst, sOf,
sProcedure, sFunction, sExternal,
sIf, sThen, sElseIf, sElse, sBegin, sEnd,
sWhile, sDo, SRepeat, sUntil, sfor,
sTo, sDownTo, sContinue, sBreak, sExit, sTerminate,
sopAnd, sopOr, sopXOr, sopNot,
sInc, sDec, sWrite, sLength, sHigh, sSetLength, sSizeOf,
sGenMem, sReallocMem, sFreeMem, sMemSize, sNew, sDispose,
sNop, sNone);
TRutisSymbols = Set Of TRutisSymbol;
Const
cSymbols : Array[TRutisSymbol] Of ShortString = ('', '', '', '', '',
'+', '-', '*', '/', 'MOD', 'DIV', 'NIL',
'=', '<', '>', '>=', '<=', '<>',
'(', ')', '[', ']', ',', '.',
';', ':=', ':', '^', '@',
'PACKED', 'RECORD',
'SET', 'ARRAY', 'CLASS',
'TRUE', 'FALSE',
'PROGRAM', 'UNIT', 'INTERFACE', 'IMPLEMENTATION', 'INITIALIZATION', 'FINALIZATION',
'USES', 'TYPE', 'VAR', 'CONST', 'OF',
'PROCEDURE', 'FUNCTION', 'EXTERNAL',
'IF', 'THEN', 'ELSEIF', 'ELSE', 'BEGIN', 'END',
'WHILE', 'DO', 'REPEAT', 'UNTIL', 'FOR',
'TO', 'DOWNTO', 'CONTINUE', 'BREAK', 'EXIT', 'TERMINATE',
'AND', 'OR', 'XOR', 'NOT',
'INC', 'DEC', 'WRITE', 'LENGTH', 'HIGH', 'SETLENGTH', 'SIZEOF',
'GENMEM', 'REALLOCMEM', 'FREEMEM', 'MEMSIZE', 'NEW', 'DISPOSE',
'NOP', '');
Const
errSymbols : Array[TRutisSymbol] Of ShortString =
('Unknown', 'Identifier', 'Integer', 'Float', 'String',
'+', '-', '*', '/', 'mod', 'div', 'nil',
'=', '<', '>', '>=', '<=', '<>',
'(', ')', '[', ']', 'Comma', 'Dot',
'Semicolon', ':=', ':', '^', '@',
'packed', 'RECORD',
'SET', 'ARRAY', 'CLASS',
'TRUE', 'FALSE',
'PROGRAM', 'UNIT', 'INTERFACE', 'IMPLEMENTATION', 'INITIALIZATION', 'FINALIZATION',
'USES', 'TYPE', 'VAR', 'CONST', 'OF',
'PROCEDURE', 'FUNCTION', 'EXTERNAL',
'IF', 'THEN', 'ElseIf', 'else', 'BEGIN', 'END',
'WHILE', 'DO', 'REPEAT', 'UNTIL', 'FOR',
'To', 'DownTo', 'Continue', 'Break', 'Exit', 'Terminate',
'AND', 'OR', 'XOR', 'NOT',
'inc', 'dec', 'write', 'length', 'high', 'SetLength', 'SizeOf',
'GenMem', 'ReallocMem', 'FreeMem', 'MemSize', 'New', 'Dispose',
'NOP', '!none!');
Type
TCompilerState = Record
CSScannerLine : Integer;
CSScannerStrPos : Integer;
CSScannerCh : Char;
CSIdentSym : TRutisSymbol;
CSCodePos : Integer;
End;
TRutisResStringInfo = Record
Address : Integer;
Value : AnsiString;
End;
TRutisCompilerDelphi = Class(TRutisCompiler)
Private
Protected
StackVarPos : Integer;
UnitNamespaces : Array Of AnsiString;
CompiledUnits : Array Of AnsiString;
ResStrings : Array Of TRutisResStringInfo;
CurrentNamespace : AnsiString;
CurrentUnit : AnsiString;
CompilingUnit : Boolean;
fCompilerLevel : Integer;
InitializationJmp,
FinalizationJmpPos : Integer;
fCompilingDefines : Boolean;
ExitParamsSize : Integer;
LoopDepth : Smallint;
//========================
ScannerLine : Integer;
ScannerStrPos : Integer;
LastScannerLine : Integer;
LastScannerStrPos : Integer;
ScannerCh : Char;
IdentSym : TRutisSymbol;
IdentStr : ShortString;
IdentNum : Variant;
ExprResult : TRutisTypeDecl;
//========================
PushScannerLine : Integer;
PushScannerStrPos : Integer;
PushScannerCh : Char;
PushIdentSym : TRutisSymbol;
CompilerStates : Array Of TCompilerState;
//========================
Procedure CompilerMessage(Const Msg : AnsiString; Const Args : Array Of Const; ErrorType : TRutisErrorType = etCompilerError); Overload;
Procedure CompilerMessage(Msg : AnsiString; ErrorType : TRutisErrorType = etCompilerError); Overload;
//========================
Procedure GetSym;
Procedure PushScanner;
Procedure PopScanner;
Procedure PopCompilerState;
Procedure PushCompilerState;
//========================
Procedure RaiseError(Const Msg : AnsiString); Overload;
Procedure RaiseError(Const Msg : AnsiString; Const Args : Array Of Const); Overload;
Procedure ErrorExpected(Expected : TRutisSymbols; Found : TRutisSymbol);
Function Expect(Expected : TRutisSymbols) : Boolean;
//========================
Function CheckRedefinition(Name : AnsiString) : Boolean;
Function GetDeclaration(Name : AnsiString) : TRutisDecl; Overload;
Function GetDeclaration(Name : AnsiString; Exclude : Array Of TRutisDecl) : TRutisDecl; Overload;
Function GetDeclarationID(Name : AnsiString) : Integer; Overload;
//========================
Procedure GenLoadSaveCode(AType : TIdentType; Address, Level, Size : Integer; DoLoad : Boolean); Overload;
Procedure GenLoadSaveCode(AType : TIdentType; Address, Level : Integer; AIntType : TRutisIntType; DoLoad : Boolean); Overload;
//========================
Procedure C_Program;
Procedure C_Unit;
Procedure C_Uses;
//=== Find / Analyse Types ===
Function GetPointerType(AType : TRutisTypeDecl; WantedName : AnsiString = '') : TRutisPointerType;
Function GetArrayType(AType : TRutisTypeDecl; WantedName : AnsiString = '') : TRutisArrayType;
Function GetSetType(AType : TRutisEnumType; WantedName : AnsiString = '') : TRutisSetType;
Function C_DeclTypeInline(NewTypeName : AnsiString = '') : TRutisTypeDecl;
//=== Declarations ===
Procedure C_DeclType;
Procedure C_DeclTypes;
Procedure C_DeclParams;
Procedure C_DeclVars;
Procedure C_DeclMethod;
Procedure C_DeclConsts;
Function C_DeclarationSeq : Boolean;
Procedure C_Declarations;
//========================
Function C_Method : Boolean;
Procedure C_Implementation;
//========================
Function C_AnalyzeIdent(IsExpression : Boolean; WantType : TRutisIntType; Var Inf : TAnalyzeIdentInfo) : TIdentType;
//========================
procedure C_Expression(WantType : TRutisTypeDecl);
//Function C_Expression(WantType : TRutisIntType; WantTypeDecl : TRutisTypeDecl = nil) : Boolean;
//procedure C_StrExpression;
//========================
Procedure C_StatementSequence;
Public
Constructor Create(AOwner : TRutisEngineBase);
Destructor Destroy; Override;
//========================
Procedure Compile; Override;
End;
//==============================================================================
//==============================================================================
Implementation
//==============================================================================
//============ TRutisCompilerDelphi ============================================
//==============================================================================
Constructor TRutisCompilerDelphi.Create(AOwner : TRutisEngineBase);
Begin
Inherited;
optArrangeFields := True;
optArrangeSize := 8;
End;
Destructor TRutisCompilerDelphi.Destroy;
Begin
Inherited;
End;
Procedure TRutisCompilerDelphi.Compile;
Var
oldDecimalSeparator : Char;
I, j : Integer;
tmpDecl : TRutisDecl;
Begin
Inherited Compile;
oldDecimalSeparator := DecimalSeparator;
DecimalSeparator := '.';
CurrentUnit := '';
ScriptData.CompilerLine := 0;
IdentNum := 0;
IdentStr := '';
ScannerCh := #0;
ScannerStrPos := 0;
ScannerLine := -1;
FinalizationJmpPos := -5;
fCompilerLevel := 0;
StackVarPos := 0;
LoopDepth := 0;
SetLength(CompiledUnits, 0);
SetLength(UnitNamespaces, 0);
SetLength(ResStrings, 0);
For I := 0 To ScriptData.DeclarationCount - 1 Do
If (ScriptData.DeclarationList[i] is TRutisExtMethodType) Then
Begin
tmpDecl := ScriptData.DeclarationList[i];
TRutisExtMethodType(tmpDecl).MethodTableID := -1;
TRutisExtMethodType(tmpDecl).MethodResult.TypeData := nil;
For j := 0 To high(TRutisExtMethodType(tmpDecl).Params) Do
TRutisExtMethodType(tmpDecl).Params[j].TypeData := nil;
End;
Try
{$ifdef DEBUG}OutputDebugString('TRutisCompilerDelphi.Compile - Compiling...');{$endif DEBUG}
C_Program;
Owner.CompilerMessage('Script sucessfully compiled!', etHint);
Owner.CompilerMessage('Raw CMD-count :' + IntToStr(length(ScriptData.Code)), etHint);
{$ifdef DEBUG}OutputDebugString('TRutisCompilerDelphi.Compile - Optimizing...');{$endif DEBUG}
Optimize;
Owner.CompilerMessage('Optimized CMD-count :' + IntToStr(length(ScriptData.Code)), etHint);
Finally
DecimalSeparator := oldDecimalSeparator;
End;
End;
//==============================================================================
Procedure TRutisCompilerDelphi.CompilerMessage(Const Msg : AnsiString; Const Args : Array Of Const; ErrorType : TRutisErrorType);
Begin
Try
CompilerMessage(Format(Msg, Args), ErrorType);
Except
on EConvertError Do
Begin
CompilerMessage('Wrong Arguments');
End;
End;
End;
Procedure TRutisCompilerDelphi.CompilerMessage(Msg : AnsiString; ErrorType : TRutisErrorType);
Begin
If ErrorType = etCompilerError Then
Msg := 'Error: ' + CurrentNamespace + '(' + IntToStr(ScriptData.CompilerLine + 1) + '): ' + Msg;
If ErrorType = etWarning Then
Msg := 'Warning: ' + CurrentNamespace + '(' + IntToStr(ScriptData.CompilerLine + 1) + '): ' + Msg;
If ErrorType = etHint Then
Msg := 'Hint: ' + CurrentNamespace + '(' + IntToStr(ScriptData.CompilerLine + 1) + '): ' + Msg;
Owner.CompilerMessage(Msg, ErrorType);
End;
Procedure TRutisCompilerDelphi.RaiseError(Const Msg : AnsiString; Const Args : Array Of Const);
Begin
Raise ERutisCompilerError.CreateFmt(Msg, Args, CurrentNamespace, LastScannerLine, LastScannerStrPos);
End;
Procedure TRutisCompilerDelphi.RaiseError(Const Msg : AnsiString);
Begin
Raise ERutisCompilerError.Create(Msg, CurrentNamespace, LastScannerLine, LastScannerStrPos);
End;
Procedure TRutisCompilerDelphi.ErrorExpected(Expected : TRutisSymbols; Found : TRutisSymbol);
Var
SymStr : AnsiString;
GotOne : Boolean;
sym : TRutisSymbol;
Begin
SymStr := '';
GotOne := False;
For sym := sUnknown To sNone Do
If sym in Expected Then
Begin
If GotOne Then
SymStr := SymStr + ''', ''' + errSymbols[sym]
Else
SymStr := errSymbols[sym];
End;
RaiseError(ERR_EXPECTED_FOUND, [SymStr, errSymbols[Found]]);
End;
Function TRutisCompilerDelphi.Expect(Expected : TRutisSymbols) : Boolean;
Begin
Result := True;
If IdentSym in Expected Then exit;
ErrorExpected(Expected, IdentSym);
Result := False;
End;
//==============================================================================
//==============================================================================
Procedure TRutisCompilerDelphi.GenLoadSaveCode(AType : TIdentType; Address, Level, Size : Integer; DoLoad : Boolean);
Begin
If DoLoad Then
Begin
Case AType Of
itVar : ScriptData.GenCode(_lod, Address, Level, Size);
itPVar : ScriptData.GenCode(_lodp, Address, Level, Size);
itConst : ScriptData.GenCode(_lodr, Address, Size, 0);
itError : RaiseError(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]);
itMethod :
Begin
//CompilerError(ERR_VAR_EXPECTED);
exit;
End;
End;
End
Else
Case AType Of
itVar : ScriptData.GenCode(_sto, Address, Level, Size);
itPVar : If Level < 0 Then
ScriptData.GenCode(_stop, Address - 3 - Size, Level, Size)
Else
ScriptData.GenCode(_stop, Address, Level, Size);
itConst : RaiseError(ERR_NO_CONST_ALLOWED);
itError : RaiseError(Format(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]));
itMethod : RaiseError(ERR_VAR_EXPECTED);
End;
End;
Procedure TRutisCompilerDelphi.GenLoadSaveCode(AType : TIdentType; Address, Level : Integer; AIntType : TRutisIntType; DoLoad : Boolean);
Var Size : Integer;
Begin
Size := IntTypeSizes[AIntType];
If Size < 0 Then RaiseError(ERR_UNEXPECTED_ERROR);
If DoLoad Then
Begin
Case AType Of
itVar : ScriptData.GenCode(_lod, Address, Level, Size);
itPVar : If Level < 0 Then
ScriptData.GenCode(_lodp, Address - 3, Level, Size)
Else
ScriptData.GenCode(_lodp, Address, Level, Size);
itConst : ScriptData.GenCode(_lodr, Address, Size, 0);
itError : RaiseError(Format(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]));
itMethod : RaiseError(ERR_VAR_EXPECTED);
End;
End
Else
Case AType Of
itVar : ScriptData.GenCode(_sto, Address, Level, Size);
itPVar : If Level < 0 Then
ScriptData.GenCode(_stop, Address - 3 - Size, Level, Size)
Else
ScriptData.GenCode(_stop, Address, Level, Size);
itConst : RaiseError(ERR_NO_CONST_ALLOWED);
itError : RaiseError(Format(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]));
itMethod : RaiseError(ERR_VAR_EXPECTED);
End;
End;
//==============================================================================
Procedure TRutisCompilerDelphi.C_Program;
Var
str : AnsiString;
Namespace : TRutisNamespace;
Begin
GetSym;
If IdentSym = sUnit Then
Begin
InitializationJmp := -1;
ScannerStrPos := 0;
ScriptData.CompilerLine := 0;
C_Unit;
If not optCanCompileUnits then
SetLength(ScriptData.Code, 0);
exit;
End;
Expect([sProgram]);
GetSym;
Expect([sIdent]);
If CurrentUnit <> '' Then
If UpperCase(CurrentUnit) <> UpperCase(IdentStr) Then
Begin
CompilerMessage(ERR_FILENAME_NOT_UNITNAME, etWarning);
exit;
End;
CurrentUnit := IdentStr;
CurrentNamespace := CurrentUnit;
ScriptData.ScriptName := IdentStr;
Namespace := ScriptData.GetNamespace(CurrentUnit);
If Namespace = nil Then
Begin
Namespace := TRutisNamespace.Create;
SetLength(ScriptData.Namespaces, Length(ScriptData.Namespaces) + 1);
ScriptData.Namespaces[high(ScriptData.Namespaces)] := Namespace;
Namespace.Name := UpperCase(CurrentUnit);
Namespace.CodeFile := CurrentUnit;
Namespace.CodeStart := 0;
End;
SetLength(UnitNamespaces, 1);
UnitNamespaces[0] := CurrentNamespace;
GetSym;
Expect([sSemiColon]);
GetSym;
Expect([sInterface]);
GetSym;
ScriptData.CompilerLine := ScannerLine;
ScriptData.GenCode(_gen, 0, 0, 0);
ScriptData.GenCode(_jmp, 0, 0, 0);
InitializationJmp := high(ScriptData.Code);
str := ScriptData.ScriptName;
C_Uses;
ScriptData.ScriptName := str;
fCompilingDefines := True;
C_Declarations;
fCompilingDefines := False;
ScriptData.CompilerLine := ScannerLine;
Expect([sImplement]);
GetSym;
ScriptData.CompilerLine := ScannerLine;
C_Implementation;
ScriptData.Code[0].P1 := StackVarPos;
ScriptData.CompilerLine := ScannerLine;
Expect([sBegin]);
GetSym;
ScriptData.Code[InitializationJmp].P1 := Length(ScriptData.Code);
C_StatementSequence;
ScriptData.CompilerLine := ScannerLine;
Expect([sEnd]);
GetSym;
Expect([sDot]);
//Und Ende...
ScriptData.GenCode(_jmp, FinalizationJmpPos, 0, 0);
Namespace.CodeEnd := Length(ScriptData.Code);
GetSym;
If IdentSym <> sNone Then
CompilerMessage(ERR_CODE_AFTER_PROGRAM_END, etHint);
{$ifdef DEBUG}OutputDebugString(PAnsiChar('TRutisCompilerDelphi.C_Program - Compiled Program ' + ScriptData.ScriptName));{$endif DEBUG}
End;
Procedure TRutisCompilerDelphi.C_Unit;
Var
int : Integer;
str : AnsiString;
Namespace : TRutisNamespace;
IsUnitApp : Boolean;
Begin
CompilingUnit := True;
If length(ScriptData.Code) = 0 Then
Begin
ScriptData.GenCode(_gen, 0, 0, 0);
ScriptData.GenCode(_jmp, 0, 0, 0);
InitializationJmp := high(ScriptData.Code);
IsUnitApp := true;
End
else
IsUnitApp := false;
GetSym;
Expect([sUnit]);
GetSym;
Expect([sIdent]);
If CurrentUnit <> '' Then
If UpperCase(CurrentUnit) <> UpperCase(IdentStr) Then
Begin
RaiseError(ERR_FILENAME_NOT_UNITNAME);
exit;
End;
CurrentUnit := IdentStr;
CurrentNamespace := CurrentUnit;
If IsUnitApp then
ScriptData.ScriptName := IdentStr;
Namespace := ScriptData.GetNamespace(CurrentUnit);
If Namespace = nil Then
Begin
Namespace := TRutisNamespace.Create;
SetLength(ScriptData.Namespaces, Length(ScriptData.Namespaces) + 1);
ScriptData.Namespaces[high(ScriptData.Namespaces)] := Namespace;
Namespace.Name := UpperCase(CurrentUnit);
Namespace.CodeFile := CurrentUnit;
Namespace.CodeStart := 0;
End;
SetLength(UnitNamespaces, 1);
UnitNamespaces[0] := CurrentNamespace;
GetSym;
Expect([sSemiColon]);
GetSym;
Expect([sInterface]);
GetSym;
//ScriptData.CompilerLine := ScannerLine;
//{!!}Owner.OnError(CurrentUnit + ': C_Unit -> C_Uses', etHint);
str := ScriptData.ScriptName;
C_Uses;
ScriptData.ScriptName := str;
//{!!}Owner.OnError(CurrentUnit + ': C_Unit -> C_Declarations', etHint);
fCompilingDefines := True;
C_Declarations;
fCompilingDefines := False;
//ScriptData.GenCode(_jmp, 0, 0, 0);
//InitializationJmp := high(ScriptData.Code);
Expect([sImplement]);
GetSym;
//{!!}Owner.OnError(CurrentUnit + ': C_Unit -> C_Implementation', etHint);
C_Implementation;
//{!!}Owner.OnError(CurrentUnit + ': C_Unit <- C_Implementation', etHint);
If IdentSym = sInitialization Then
Begin
GetSym;
ScriptData.Code[InitializationJmp].P1 := high(ScriptData.Code) + 1;
C_StatementSequence;
ScriptData.GenCode(_jmp, 0, 0, 0);
InitializationJmp := high(ScriptData.Code);
If IdentSym = sFinalization Then
Begin
GetSym;
int := high(ScriptData.Code) + 1;
C_StatementSequence;
ScriptData.GenCode(_jmp, FinalizationJmpPos, 0, 0);
FinalizationJmpPos := int;
End;
End;
ScriptData.Code[InitializationJmp].P1 := high(ScriptData.Code) + 1;
If IsUnitApp then
ScriptData.Code[0].P1 := StackVarPos;
Namespace.CodeEnd := Length(ScriptData.Code);
Expect([sEnd]);
GetSym;
Expect([sDot]);
GetSym;
If IdentSym <> sNone Then
CompilerMessage(ERR_CODE_AFTER_UNIT_END, etHint);
CompilingUnit := False;
{$ifdef DEBUG}OutputDebugString(PAnsiChar('TRutisCompilerDelphi.C_Unit - Compiled Unit ' + ScriptData.ScriptName));{$endif DEBUG}
End;
Procedure TRutisCompilerDelphi.C_Uses;
Var
i : Integer;
UName : AnsiString;
savCurrUnit : AnsiString;
savScriptCode : TStrings;
savScannerStrPos : Integer;
savLine : Integer;
savScannerLine : Integer;
savScannerCh : Char;
savIdentSym : TRutisSymbol;
savIdentStr : ShortString;
savIdentNum : Variant;
savUnitNamespaces : Array Of AnsiString;
UnitNames : Array Of AnsiString;
j : Integer;
Begin
If IdentSym = sUses Then
Begin
SetLength(savUnitNamespaces, Length(UnitNamespaces));
For i := 0 To high(UnitNamespaces) Do
savUnitNamespaces[i] := UnitNamespaces[i];
SetLength(UnitNames, 0);
Repeat
GetSym;
ScriptData.CompilerLine := ScannerLine;
Expect([sIdent]);
SetLength(UnitNames, Length(UnitNames) + 1);
UnitNames[high(UnitNames)] := IdentStr;
GetSym;
Until IdentSym <> sComma;
Expect([sSemiColon]);
GetSym;
ScriptData.CompilerLine := ScannerLine;
savCurrUnit := CurrentUnit;
savScriptCode := ScriptCode;
savScannerStrPos := ScannerStrPos;
savLine := ScriptData.CompilerLine;
savScannerLine := ScannerLine;
savScannerCh := ScannerCh;
savIdentSym := IdentSym;
savIdentStr := IdentStr;
savIdentNum := IdentNum;
ScriptCode := TStringList.Create;
Try
For i := 0 To high(UnitNames) Do
Begin
UnitNames[i] := lowerCase(UnitNames[i]);
For j := 0 To high(CompiledUnits) Do
If CompiledUnits[j] = UnitNames[i] Then
Break;
If j <= high(CompiledUnits) Then
If CompiledUnits[j] = UnitNames[i] Then
Continue;
SetLength(CompiledUnits, length(CompiledUnits) + 1);
CompiledUnits[high(CompiledUnits)] := UnitNames[i];
UName := Owner.UnitFileManager.SearchFile(UnitNames[i]);
If not FileExists(UName) Then
Begin
RaiseError(ERR_UNIT_NOT_FOUND, [UnitNames[i]]);
exit;
End;
ScriptCode.LoadFromFile(UName);
SetLength(UnitNamespaces, 0);
IdentSym := sNone;
IdentStr := '';
IdentNum := 0;
ScannerCh := #0;
ScannerStrPos := 0;
ScriptData.CompilerLine := 0;
ScannerLine := -1;
CurrentUnit := ExtractFileName(UName);
If Pos('.', CurrentUnit) > 0 Then
CurrentUnit := copy(CurrentUnit, 1, Pos('.', CurrentUnit) - 1);
C_Unit;
End;
Finally
ScriptCode.Free;
End;
ScriptCode := savScriptCode;
ScannerStrPos := savScannerStrPos;
ScriptData.CompilerLine := savLine;
ScannerLine := savScannerLine;
ScannerCh := savScannerCh;
IdentSym := savIdentSym;
IdentStr := savIdentStr;
IdentNum := savIdentNum;
CurrentUnit := savCurrUnit;
CurrentNamespace := CurrentUnit;
SetLength(UnitNamespaces, Length(UnitNames) + Length(savUnitNamespaces));
For i := 0 To high(UnitNames) Do
UnitNamespaces[i] := UnitNames[i];
For i := 0 To high(savUnitNamespaces) Do
UnitNamespaces[i + length(UnitNames)] := savUnitNamespaces[i];
End;
End;
//==============================================================================
//==============================================================================
Function TRutisCompilerDelphi.GetPointerType(AType : TRutisTypeDecl; WantedName : AnsiString) : TRutisPointerType;
Var
i, j : Integer;
Begin
For i := 0 To high(ScriptData.Namespaces) Do
For j := 0 To high(ScriptData.Namespaces[i].Declarations) Do
If ScriptData.Namespaces[i].Declarations[j] is TRutisPointerType Then
If TRutisPointerType(ScriptData.Namespaces[i].Declarations[j]).PointerType = AType Then
Begin
Result := TRutisPointerType(ScriptData.Namespaces[i].Declarations[j]);
exit;
End;
// No matching Pointer-Type found so create one
Result := TRutisPointerType.Create;
If (WantedName = '') Then
Result.Name := 'P' + AType.Name + '_auto'
Else
Result.Name := WantedName;
Result.PointerType := AType;
Result.ExplicitCast := False;
ScriptData.AddDeclaration(Result, '$SYSTEM');
End;
Function TRutisCompilerDelphi.GetArrayType(AType : TRutisTypeDecl; WantedName : AnsiString) : TRutisArrayType;
Var
i, j : Integer;
Begin
For i := 0 To high(ScriptData.Namespaces) Do
For j := 0 To high(ScriptData.Namespaces[i].Declarations) Do
If ScriptData.Namespaces[i].Declarations[j] is TRutisArrayType Then
If TRutisArrayType(ScriptData.Namespaces[i].Declarations[j]).ArrayType = AType Then
Begin
Result := TRutisArrayType(ScriptData.Namespaces[i].Declarations[j]);
exit;
End;
// No matching Pointer-Type found so create one
Result := TRutisArrayType.Create;
If (WantedName = '') Then
Result.Name := 'T' + AType.Name + 'Array_auto'
Else
Result.Name := WantedName;
Result.ArrayType := AType;
Result.ExplicitCast := True;
ScriptData.AddDeclaration(Result, '$SYSTEM');
End;
Function TRutisCompilerDelphi.GetSetType(AType : TRutisEnumType; WantedName : AnsiString) : TRutisSetType;
Var
i, j : Integer;
Begin
For i := 0 To high(ScriptData.Namespaces) Do
For j := 0 To high(ScriptData.Namespaces[i].Declarations) Do
If ScriptData.Namespaces[i].Declarations[j] is TRutisSetType Then
If TRutisSetType(ScriptData.Namespaces[i].Declarations[j]).EnumType = AType Then
Begin
Result := TRutisSetType(ScriptData.Namespaces[i].Declarations[j]);
exit;
End;
// No matching Pointer-Type found so create one
Result := TRutisSetType.Create;
If (WantedName = '') Then
Result.Name := 'T' + AType.Name + 's_auto'
Else
Result.Name := WantedName;
Result.EnumType := AType;
Result.ExplicitCast := True;
ScriptData.AddDeclaration(Result, '$SYSTEM');
Result.Size := 1;
For I := 0 To high(Result.EnumType.Enums) Do
If Result.EnumType.Enums[i].Value >= Result.Size * 8 Then
Begin
Case Result.Size Of
2 : Result.Size := 4;
4 : Result.Size := 8;
Else
Inc(Result.Size);
End;
End;
End;
//==============================================================================
Function TRutisCompilerDelphi.C_DeclTypeInline(NewTypeName : AnsiString = '') : TRutisTypeDecl;
Var
TypeDecl : TRutisTypeDecl;
ExplicitCast : Boolean;
Function GetEnumType : TRutisTypeDecl;
Var
int, i : Integer;
Bool : Boolean;
VarDecl : TRutisVarDecl;
Begin
GetSym;
Result := TRutisEnumType.Create;
If NewTypeName <> '' Then
Result.Name := NewTypeName
Else
Result.Name := 'TEnum_ID' + IntToStr(random(1024));
ScriptData.AddDeclaration(Result, CurrentNamespace);
Result.Size := 1;
With TRutisEnumType(Result) Do
Begin
While True Do
Begin
Expect([sIdent]);
If CheckRedefinition(IdentStr) Then
RaiseError(ERR_INDENT_REDEFINED, [IdentStr]);
VarDecl := TRutisVarDecl.Create;
VarDecl.Name := IdentStr;
ScriptData.AddDeclaration(VarDecl, CurrentNamespace);
VarDecl.IsConst := True;
VarDecl.Level := 0;
VarDecl.Address := ScriptData.Ressources.Top;
VarDecl.VarType := Result;
GetSym;
If IdentSym = sEqual Then
Begin
GetSym;
Expect([sInteger]);
int := 0;
For I := 0 To high(Enums) Do
If Enums[i].Value = int Then
RaiseError('The value %d already exists in this enumaration type', [int]);
End
Else
Begin
int := 0;
Repeat
Bool := True;
For I := 0 To high(Enums) Do
If Enums[i].Value = int Then
Begin
Bool := False;
Inc(int);
End;
Until Bool;
End;
If int < 0 Then
RaiseError('The enum-value ''%d'' is too low. It needs to be positive.', [int]);
If int >= 32 Then
RaiseError('The enum-value ''%d'' is too big. It needs to be lower than 32.', [int]);
SetLength(Enums, length(Enums) + 1);
Enums[high(Enums)].Name := VarDecl.Name;
Enums[high(Enums)].Value := int;
ScriptData.Ressources.PushByte(int);
If IdentSym = sCloseBracket Then break;
Expect([sComma]);
GetSym;
End;
End;
GetSym;
End;
Begin
Result := nil;
ExplicitCast := False;
If IdentSym = sType Then
Begin
ExplicitCast := True;
GetSym;
End;
// Enum-Types
If IdentSym = sOpenBracket Then
Begin
Result := GetEnumType;
exit;
End;
// Set-Types
If IdentSym = sSet Then
Begin
GetSym;
Expect([sOf]);
GetSym;
TypeDecl := C_DeclTypeInline();
If not (TypeDecl is TRutisEnumType) Then
RaiseError(ERR_NEEDED_FOUND, [RutisVarTypeTOString[intEnum], RutisVarTypeTOString[TypeDecl.InternalType]]);
Result := GetSetType(TRutisEnumType(TypeDecl), NewTypeName);
exit;
End;
If IdentSym = sArray Then
Begin
GetSym;
Expect([sOf]);
GetSym;
TypeDecl := C_DeclTypeInline();
Result := GetArrayType(TypeDecl, NewTypeName);
exit;
End;
If IdentSym = sHook Then
Begin
GetSym;
TypeDecl := C_DeclTypeInline();
Result := GetPointerType(TypeDecl, NewTypeName);
Result.ExplicitCast := ExplicitCast;
exit;
End;
Expect([sIdent]);
Result := TRutisTypeDecl(GetDeclaration(IdentStr));
If Result = nil Then
Begin
RaiseError(ERR_UNKNOWN_IDENT, [IdentStr]);
exit;
End;
If not (Result is TRutisTypeDecl) Then
Begin
RaiseError(ERR_TYPE_EXPECTED);
exit;
End;
GetSym;
If (NewTypeName <> '') and (NewTypeName <> Result.Name) Then
Begin
TypeDecl := TRutisTypeCopy.Create;
TypeDecl.Name := NewTypeName;
TypeDecl.ExplicitCast := ExplicitCast;
TRutisTypeCopy(TypeDecl).CopyType := Result;
TRutisTypeCopy(TypeDecl).Size := Result.Size;
//ScriptData.AddDeclaration(TypeDecl, '$SYSTEM');
ScriptData.AddDeclaration(TypeDecl, CurrentNamespace);
Result := TypeDecl;
End;
End;
Procedure TRutisCompilerDelphi.C_DeclType;
Var
int, i, j : Integer;
RasterSize : Byte;
TypeName : AnsiString;
VType : TRutisTypeDecl;
Parent : TRutisStructType;
StructType : TRutisStructType;
AClassType : TRutisClassType;
ParentClass : TRutisClassType;
VarNames : Array Of AnsiString;
fIsPacked : Boolean;
Begin
Expect([sIdent]);
TypeName := IdentStr;
If CheckRedefinition(TypeName) Then
Begin
i := ScriptData.GetDeclarationId(TypeName, '$STATIC');
If i >= 0 Then
Begin
{Repeat
GetSym;
If IdentSym = sRecord Then
Begin
Repeat
GetSym;
Until IdentSym in [sEnd, sNone, sUnknown];
End;
Until IdentSym in [sSemiColon, sNone, sUnknown];
GetSym;
exit; }
End
Else
Begin
RaiseError(ERR_INDENT_REDEFINED, [TypeName]);
exit;
End;
End;
GetSym;
Expect([sEqual]);
GetSym;
If IdentSym = sPacked Then
Begin
fIsPacked := True;
GetSym;
End
Else
fIsPacked := False;
If IdentSym = sExternal Then
Begin
GetSym;
Expect([sClass]);
GetSym;
StructType := TRutisStructType.Create;
ScriptData.AddDeclaration(StructType, CurrentNamespace);
With StructType Do
Begin
Name := TypeName + '_CLASSDATA';
IsPacked := fIsPacked;
If IdentSym = sOpenBracket Then
Begin
GetSym;
Expect([sIdent]);
ParentClass := GetDeclaration(IdentStr) as TRutisClassType;
If not (ParentClass is TRutisClassType) Then
Begin
RaiseError('Class-Type expected'); exit;
End;
GetSym;
Expect([sCloseBracket]);
GetSym;
End
Else
ParentClass := Owner.decl_TObject;
Parent := ParentClass.ClassStruct;
Size := Parent.Size;
fAlignSize := Parent.fAlignSize;
//IsPacked := Parent.IsPacked;
SetLength(StructTypes, Length(TRutisStructType(Parent).StructTypes));
For i := 0 To high(TRutisStructType(Parent).StructTypes) Do
Begin
StructTypes[i] := TRutisVarDecl.Create;
StructTypes[i].VarType := TRutisStructType(Parent).StructTypes[i].VarType;
StructTypes[i].Address := TRutisStructType(Parent).StructTypes[i].Address;
StructTypes[i].isConst := TRutisStructType(Parent).StructTypes[i].isConst;
StructTypes[i].Level := TRutisStructType(Parent).StructTypes[i].Level;
StructTypes[i].Name := TRutisStructType(Parent).StructTypes[i].Name;
End;
{
else
begin
SetLength(StructTypes, 1);
StructTypes[0] := TRutisVarDecl.Create;
StructTypes[0].VarType := Owner.decl_VMT;
StructTypes[0].Address := 0;
StructTypes[0].Name := 'VMT';
Size := 4;
end;
}
While True Do
Begin
SetLength(VarNames, 0);
While True Do
Begin
Expect([sIdent]);
SetLength(VarNames, Length(VarNames) + 1);
VarNames[High(VarNames)] := IdentStr;
GetSym;
If IdentSym <> scomma Then Break;
GetSym;
End;
Expect([sDopDot]);
GetSym;
VType := C_DeclTypeInline();
If VType = nil Then exit;
int := high(StructTypes);
SetLength(StructTypes, Length(StructTypes) + Length(VarNames));
If optArrangeFields and not IsPacked Then
Begin
RasterSize := Max(Min(VType.AlignSize, optArrangeSize), 1);
fAlignSize := max(AlignSize, RasterSize);
j := RasterSize - (Size mod RasterSize);
If j < RasterSize Then
Begin
//ScriptData.GenCode(_gen, j, 0, 0);
Size := Size + j;
End;
End;
For i := int + 1 To high(StructTypes) Do
Begin
StructTypes[i] := TRutisVarDecl.Create;
StructTypes[i].VarType := VType;
StructTypes[i].Address := Size;
StructTypes[i].Name := VarNames[i - int - 1];
Size := Size + VType.Size;
End;
//GetSym;
Expect([sSemiColon]);
GetSym;
If not (IdentSym in [sIdent, sSemiColon]) Then break;
End;
If optArrangeFields and not IsPacked Then
Begin
j := AlignSize - (Size mod AlignSize);
If j < AlignSize Then
Begin
//ScriptData.GenCode(_gen, j, 0, 0);
Size := Size + j;
End;
End;
Expect([sEnd]);
GetSym;
Expect([sSemiColon]);
GetSym;
End;
AClassType := TRutisClassType.Create;
AClassType.Name := TypeName;
AClassType.ClassStruct := StructType;
AClassType.IsExternal := True;
AClassType.ParentClass := ParentClass;
ScriptData.AddDeclaration(AClassType, CurrentNamespace);
exit;
End;
If fIsPacked Then
Expect([sRecord]);
If IdentSym = sRecord Then
Begin
GetSym;
StructType := TRutisStructType.Create;
ScriptData.AddDeclaration(StructType, CurrentNamespace);
With StructType Do
Begin
Name := TypeName;
Size := 0;
IsPacked := fIsPacked;
fAlignSize := 1;
If IdentSym = sOpenBracket Then
Begin
GetSym;
Expect([sIdent]);
Parent := TRutisStructType(GetDeclaration(IdentStr));
If not (Parent is TRutisStructType) Then
Begin
RaiseError('Struct-Type expected'); exit;
End;
Size := TRutisStructType(Parent).Size;
fAlignSize := TRutisStructType(Parent).fAlignSize;
//IsPacked := TRutisStructType(AParent).IsPacked;
SetLength(StructTypes, Length(TRutisStructType(Parent).StructTypes));
For i := 0 To high(TRutisStructType(Parent).StructTypes) Do
Begin
StructTypes[i] := TRutisVarDecl.Create;
StructTypes[i].VarType := TRutisStructType(Parent).StructTypes[i].VarType;
StructTypes[i].Address := TRutisStructType(Parent).StructTypes[i].Address;
StructTypes[i].isConst := TRutisStructType(Parent).StructTypes[i].isConst;
StructTypes[i].Level := TRutisStructType(Parent).StructTypes[i].Level;
StructTypes[i].Name := TRutisStructType(Parent).StructTypes[i].Name;
End;
GetSym;
Expect([sCloseBracket]);
GetSym;
End;
While True Do
Begin
SetLength(VarNames, 0);
While True Do
Begin
Expect([sIdent]);
SetLength(VarNames, Length(VarNames) + 1);
VarNames[High(VarNames)] := IdentStr;
GetSym;
If IdentSym <> scomma Then Break;
GetSym;
End;
Expect([sDopDot]);
GetSym;
VType := C_DeclTypeInline();
If VType = nil Then exit;
int := high(StructTypes);
SetLength(StructTypes, Length(StructTypes) + Length(VarNames));
If optArrangeFields and not IsPacked Then
Begin
RasterSize := Max(Min(VType.AlignSize, optArrangeSize), 1);
fAlignSize := max(AlignSize, RasterSize);
j := RasterSize - (Size mod RasterSize);
If j < RasterSize Then
Begin
//ScriptData.GenCode(_gen, j, 0, 0);
Size := Size + j;
End;
End;
For i := int + 1 To high(StructTypes) Do
Begin
StructTypes[i] := TRutisVarDecl.Create;
StructTypes[i].VarType := VType;
StructTypes[i].Address := Size;
StructTypes[i].Name := VarNames[i - int - 1];
Size := Size + VType.Size;
End;
//GetSym;
Expect([sSemiColon]);
GetSym;
If not (IdentSym in [sIdent, sSemiColon]) Then break;
End;
If optArrangeFields and not IsPacked Then
Begin
j := AlignSize - (Size mod AlignSize);
If j < AlignSize Then
Begin
//ScriptData.GenCode(_gen, j, 0, 0);
Size := Size + j;
End;
End;
Expect([sEnd]);
GetSym;
Expect([sSemiColon]);
GetSym;
End;
exit;
End;
If IdentSym = sProcedure Then
Begin
GetSym;
RaiseError(ERR_NOT_IMPLEMENTED_YET);
exit;
End;
// No record type so get "normal" type
C_DeclTypeInline(TypeName);
Expect([sSemiColon]);
GetSym;
End;
Procedure TRutisCompilerDelphi.C_DeclTypes;
Begin
While IdentSym = sIdent Do
Begin
C_DeclType;
End;
End;
Procedure TRutisCompilerDelphi.C_DeclVars;
Var
i, j : Integer;
VarDecl : TRutisVarDecl;
VType : TRutisTypeDecl;
VarNames : Array Of AnsiString;
RasterSize : Byte;
Begin
While True Do
Begin
SetLength(VarNames, 0);
While True Do
Begin
Expect([sIdent]);
If CheckRedefinition(IdentStr) Then
RaiseError(ERR_INDENT_REDEFINED, [IdentStr]);
for I := 0 to high(VarNames) do
If VarNames[i] = IdentStr then
RaiseError(ERR_INDENT_REDEFINED, [IdentStr]);
SetLength(VarNames, Length(VarNames) + 1);
VarNames[High(VarNames)] := IdentStr;
GetSym;
If IdentSym <> scomma Then Break;
GetSym;
End;
Expect([sDopDot]);
GetSym;
VType := C_DeclTypeInline();
If VType = nil Then exit;
For i := 0 To high(VarNames) Do
Begin
VarDecl := TRutisVarDecl.Create;
ScriptData.AddDeclaration(VarDecl, CurrentNamespace);
If optArrangeFields Then
Begin
RasterSize := Max(Min(VType.AlignSize, optArrangeSize), 1);
j := RasterSize - (StackVarPos mod RasterSize);
If j < RasterSize Then
Begin
//ScriptData.GenCode(_gen, j, 0, 0);
StackVarPos := StackVarPos + j;
End;
End;
VarDecl.Name := VarNames[i];
VarDecl.IsConst := False;
VarDecl.VarType := VType;
VarDecl.Level := fCompilerLevel;
VarDecl.Address := StackVarPos;
//ScriptData.GenCode(_gen, VType.Size, 0, 0);
StackVarPos := StackVarPos + VType.Size;
End;
//GetSym;
Expect([sSemiColon]);
While IdentSym = sSemiColon Do GetSym;
If not (IdentSym in [sIdent, sSemiColon]) Then break;
End;
End;
Procedure TRutisCompilerDelphi.C_DeclParams;
Var
i : Integer;
VarDecl : TRutisVarDecl;
VType : TRutisTypeDecl;
VarNames : Array Of AnsiString;
Begin
If IdentSym in [sSemiColon, sDopDot] Then exit;
Expect([sOpenBracket]);
GetSym;
If IdentSym = sCloseBracket Then
Begin
GetSym;
exit;
End;
While True Do
Begin
SetLength(VarNames, 0);
While True Do
Begin
Expect([sIdent]);
If CheckRedefinition(IdentStr) Then
Begin
RaiseError(ERR_INDENT_REDEFINED, [IdentStr]);
exit;
End;
SetLength(VarNames, Length(VarNames) + 1);
VarNames[High(VarNames)] := IdentStr;
GetSym;
If IdentSym <> scomma Then Break;
GetSym;
End;
Expect([sDopDot]);
GetSym;
VType := C_DeclTypeInline();
If VType = nil Then exit;
For i := 0 To high(VarNames) Do
Begin
VarDecl := TRutisVarDecl.Create;
ScriptData.AddDeclaration(VarDecl, CurrentNamespace);
VarDecl.Name := VarNames[i];
VarDecl.IsConst := False;
VarDecl.VarType := VType;
VarDecl.Level := fCompilerLevel;
End;
If IdentSym <> sSemiColon Then break;
While IdentSym = sSemiColon Do GetSym;
//GetSym;
End;
Expect([sCloseBracket]);
GetSym;
End;
Procedure TRutisCompilerDelphi.C_DeclConsts;
Var
VarDecl : TRutisVarDecl;
VarType : TRutisTypeDecl;
signum : Shortint;
//Str : PAnsiString;
Begin
While True Do
Begin
Expect([sIdent]);
If CheckRedefinition(IdentStr) Then
RaiseError(ERR_INDENT_REDEFINED, [IdentStr]);
VarDecl := TRutisVarDecl.Create;
ScriptData.AddDeclaration(VarDecl, CurrentNamespace);
VarDecl.Name := IdentStr;
VarDecl.IsConst := True;
VarDecl.Level := 0;
VarDecl.Address := ScriptData.Ressources.Top;
GetSym;
VarType := nil;
If IdentSym = sDopDot Then
Begin
GetSym;
Expect([sIdent]);
VarType := C_DeclTypeInline;
If VarType = nil Then
RaiseError(ERR_TYPE_EXPECTED);
End;
Expect([sEqual]);
GetSym;
If IdentSym = sMinus Then
Begin
GetSym;
signum := -1;
End
Else
signum := 1;
If not (IdentSym in [sInteger..sString, sTrue, sFalse]) Then exit;
Case IdentSym Of
sString :
Begin
If length(IdentStr) = 1 Then
Begin
// Save Ressource
ScriptData.Ressources.PushByte(Byte(IdentStr[1]));
VarDecl.ConstVal := IdentStr[1];
// Get Ressource-Type
If VarType <> nil Then
Begin
If VarType.Size <> 1 Then
RaiseError(ERR_INCOMPATIBLE_TYPES, [VarType.Name, Owner.decl_AChar.Name]);
VarDecl.VarType := VarType;
End
Else
VarDecl.VarType := TRutisTypeDecl(Owner.decl_AChar);
End
Else
Begin
// Save Ressource
VarDecl.Address := ScriptData.Ressources.Top + 4;
IdentStr := IdentStr;
ScriptData.Ressources.PushAStringData(IdentStr);
VarDecl.ConstVal := IdentStr;
// Get Ressource-Type
If VarType <> nil Then
Begin
//If VarType.Size <> 4 then
RaiseError(ERR_INCOMPATIBLE_TYPES, [VarType.Name, Owner.decl_AString.Name]);
End
Else
VarDecl.VarType := TRutisTypeDecl(Owner.decl_AString);
End;
If (VarDecl.VarType = nil) or
(not (VarDecl.VarType is TRutisTypeDecl)) Then
Begin
RaiseError(ERR_NOT_AVAILABLE);
exit;
End;
End;
sInteger :
Begin
// Save Ressource
IdentNum := signum * IdentNum;
VarDecl.ConstVal := IdentNum;
// Get Ressource-Type
If VarType <> nil Then
Begin
VarDecl.VarType := VarType;
If VarType.InternalType = intByte Then
Begin
If (IdentNum < 0) or (IdentNum >= 256) Then
RaiseError('Value must be between 0 and 255');
ScriptData.Ressources.PushByte(IdentNum);
End
Else
If VarType.InternalType = intShortInt Then
Begin
If (IdentNum <= -128) or (IdentNum >= 128) Then
RaiseError('Value must be between -127 and 127');
ScriptData.Ressources.PushShortInt(IdentNum);
End
Else
If VarType.InternalType = intWord Then
Begin
If (IdentNum < 0) or (IdentNum >= 65536) Then
RaiseError('Value must be between 0 and 65535');
ScriptData.Ressources.PushWord(IdentNum);
End
Else
If VarType.InternalType = intSmallint Then
Begin
If (IdentNum <= -32768) or (IdentNum >= 32768) Then
RaiseError('Value must be between -32767 and 32767');
ScriptData.Ressources.PushSmallint(IdentNum);
End
Else
If VarType.InternalType = intCardinal Then
ScriptData.Ressources.PushCardinal(IdentNum)
Else
If VarType.InternalType = intInteger Then
ScriptData.Ressources.PushInteger(IdentNum)
Else
RaiseError(ERR_INCOMPATIBLE_TYPES, [VarType.Name, Owner.decl_Integer.Name]);
End
Else
Begin
ScriptData.Ressources.PushCardinal(Cardinal(IdentNum));
VarDecl.VarType := Owner.decl_Integer;
End;
End;
sFloat :
Begin
// Save Ressource
IdentNum := signum * IdentNum;
VarDecl.ConstVal := IdentNum;
// Get Ressource-Type
If VarType <> nil Then
Begin
VarDecl.VarType := VarType;
If VarType.InternalType = intSingle Then
ScriptData.Ressources.PushSingle(IdentNum)
Else
If VarType.InternalType = intDouble Then
ScriptData.Ressources.PushDouble(IdentNum)
Else
If VarType.InternalType = intExtended Then
ScriptData.Ressources.PushExtended(IdentNum)
Else
RaiseError(ERR_INCOMPATIBLE_TYPES, [VarType.Name, Owner.decl_Integer.Name]);
End
Else
Begin
ScriptData.Ressources.PushSingle(IdentNum);
VarDecl.VarType := Owner.decl_Single;
End;
End;
sTrue, sFalse :
Begin
// Save Ressource
VarDecl.ConstVal := Boolean(IdentSym = sTrue);
ScriptData.Ressources.PushByte(Byte(IdentSym = sTrue));
// Get Ressource-Type
VarDecl.VarType := Owner.decl_Boolean;
If VarType <> nil Then
Begin
If VarType.Size <> 1 Then
RaiseError(ERR_INCOMPATIBLE_TYPES, [VarType.Name, VarDecl.VarType.Name]);
VarDecl.VarType := VarType;
End;
End;
Else
RaiseError(ERR_NOT_AVAILABLE_C_TYPE);
exit;
End;
{!! Arrange Res-Fields}
while ScriptData.Ressources.Top mod 4 <> 0 do
ScriptData.Ressources.PushByte(0);
GetSym;
Expect([sSemiColon]);
GetSym;
While IdentSym = sSemiColon Do GetSym;
If not (IdentSym = sIdent) Then break;
End;
End;
Procedure TRutisCompilerDelphi.C_DeclMethod;
Var
bool : Boolean;
MethodDecl : TRutisMethodType;
DllMethodDecl : TRutisDllMethodType;
MethodVar : TRutisVarDecl;
I : Integer;
Function GetMethodParams : Boolean;
Var
i : Integer;
isVar : Boolean;
VType : TRutisTypeDecl;
VarNames : Array Of AnsiString;
Begin
Result := False;
If IdentSym <> sOpenBracket Then
Begin
Result := True;
MethodDecl.ParamsSize := 0;
exit;
End;
GetSym;
While True Do
Begin
isVar := True;
If IdentSym = sVar Then
Begin
isVar := True;
GetSym;
End;
SetLength(VarNames, 0);
While True Do
Begin
Expect([sIdent]);
If CheckRedefinition(IdentStr) Then
Begin
RaiseError(ERR_INDENT_REDEFINED, [IdentStr]);
exit;
End;
SetLength(VarNames, Length(VarNames) + 1);
VarNames[High(VarNames)] := IdentStr;
GetSym;
If IdentSym <> scomma Then Break;
GetSym;
End;
Expect([sDopDot]);
GetSym;
VType := C_DeclTypeInline();
If VType = nil Then exit;
For i := 0 To high(VarNames) Do
Begin
SetLength(MethodDecl.Params, Length(MethodDecl.Params) + 1);
With MethodDecl.Params[high(MethodDecl.Params)] Do
Begin
TypeData := VType;
isVarParam := isVar;
End;
MethodDecl.ParamsSize := MethodDecl.ParamsSize + VType.Size;
End;
If IdentSym <> sSemiColon Then break;
While IdentSym = sSemiColon Do GetSym;
End;
Expect([sCloseBracket]);
GetSym;
Result := True;
End;
Begin
If not (IdentSym in [sProcedure, sFunction]) Then exit;
bool := IdentSym = sFunction;
GetSym;
Expect([sIdent]);
If CheckRedefinition(IdentStr) Then
Begin
RaiseError(ERR_INDENT_REDEFINED, [IdentStr]);
exit;
End;
MethodVar := TRutisVarDecl.Create;
ScriptData.AddDeclaration(MethodVar, CurrentNamespace);
MethodVar.Name := IdentStr;
MethodVar.IsConst := True;
MethodVar.Level := 0;
MethodVar.VarType := TRutisMethodType.Create;
MethodDecl := TRutisMethodType(MethodVar.VarType);
MethodVar.Address := ScriptData.Ressources.Top;
ScriptData.Ressources.PushCardinal(Cardinal(high(ScriptData.Code) + 1));
Try
With MethodDecl Do
Begin
ParamsSize := 0;
IsFunction := bool;
If IsFunction Then
Name := 'function'
Else
Name := 'procedure';
GetSym;
If not GetMethodParams Then
Begin
MethodDecl.Free; exit;
End;
If IsFunction Then
Begin
Expect([sDopDot]);
GetSym;
MethodResult.TypeData := TRutisTypeDecl(GetDeclaration(IdentStr));
If (MethodResult.TypeData = nil) or (not (MethodResult.TypeData is TRutisTypeDecl)) Then
Begin
RaiseError(ERR_TYPE_EXPECTED);
MethodDecl.Free;
exit;
End;
GetSym;
End;
Expect([sSemiColon]);
GetSym;
End;
Except
MethodDecl.Free;
Raise;
End;
//function MeineFunc(...); external 'MeineDll.dll' name 'MeinFunc';
If IdentSym = sExternal Then
Begin
GetSym;
DllMethodDecl := TRutisDllMethodType.Create;
DllMethodDecl.Method_Name := MethodDecl.Method_Name;
DllMethodDecl.Description := MethodDecl.Description;
DllMethodDecl.Params := MethodDecl.Params;
DllMethodDecl.ParamsSize := MethodDecl.ParamsSize;
DllMethodDecl.IsFunction := MethodDecl.IsFunction;
DllMethodDecl.MethodResult.TypeData := MethodDecl.MethodResult.TypeData;
DllMethodDecl.Declarations := MethodDecl.Declarations;
DllMethodDecl.Size := MethodDecl.Size;
DllMethodDecl.Name := MethodDecl.Name;
MethodVar.VarType := DllMethodDecl;
MethodDecl.Free;
ScriptData.AddDeclaration(DllMethodDecl, CurrentNamespace);
If IdentSym = sIdent Then
Begin
RaiseError('DLL-Name and Method-Name can not be Variables or Constants. Only Strings with '' '' are usable'); exit;
End;
Expect([sString]);
DllMethodDecl.DllName := IdentStr;
GetSym;
Expect([sIdent]);
If IdentStr <> 'NAME' Then
Begin
RaiseError(ERR_EXPECTED_FOUND, ['name', IdentStr]);
exit;
End;
GetSym;
If IdentSym = sIdent Then
Begin
RaiseError('DLL-Name and Method-Name can not be Variables or Constants. Only Strings with '' '' are usable'); exit;
End;
Expect([sString]);
DllMethodDecl.ProcName := IdentStr;
GetSym;
Expect([sSemiColon]);
GetSym;
For I := 0 To high(DllMethodDecl.Params) Do
If DllMethodDecl.Params[i].isVarParam Then
Begin
DllMethodDecl.ParamsSize := DllMethodDecl.ParamsSize -
DllMethodDecl.Params[i].TypeData.Size + 4;
DllMethodDecl.Params[i].TypeData :=
GetPointerType(DllMethodDecl.Params[i].TypeData);
//DllMethodDecl.Params[i].isVarParam := false;
End;
exit;
End;
ScriptData.AddDeclaration(MethodDecl, CurrentNamespace);
exit;
End;
Function TRutisCompilerDelphi.C_DeclarationSeq : Boolean;
Begin
Result := False;
If IdentSym = sType Then
Begin
Result := True;
GetSym;
C_DeclTypes;
exit;
End;
If IdentSym = sVar Then
Begin
Result := True;
GetSym;
C_DeclVars;
exit;
End;
If (IdentSym in [sProcedure, sFunction]) and fCompilingDefines Then
Begin
Result := True;
C_DeclMethod;
exit;
End;
If IdentSym = sConst Then
Begin
Result := True;
GetSym;
C_DeclConsts;
exit;
End;
End;
Procedure TRutisCompilerDelphi.C_Declarations;
Begin
Repeat Until not C_DeclarationSeq;
End;
//==============================================================================
Function TRutisCompilerDelphi.C_Method : Boolean;
Var
i, j : Integer;
bool : Boolean;
MethodDecl : TRutisMethodType;
MethodVar : TRutisVarDecl;
VarDecl : TRutisVarDecl;
OldStackVarPos : Integer;
OldNamespace : AnsiString;
Namespace : TRutisNamespace;
MethodInitAddr : Integer;
Begin
Result := False;
If not (IdentSym in [sProcedure, sFunction]) Then exit;
bool := IdentSym = sFunction;
GetSym;
Expect([sIdent]);
If CheckRedefinition(IdentStr) Then
Begin
RaiseError(ERR_INDENT_REDEFINED, [IdentStr]);
exit;
End;
//{!!}Owner.OnError('-> C_Method ' + IdentStr, etHint);
If fCompilerLevel > 0 Then
Begin
ScriptData.GenCode(_jmp, 0, 0, 0);
MethodInitAddr := high(ScriptData.Code);
End
Else
MethodInitAddr := -1;
Inc(fCompilerLevel);
MethodVar := TRutisVarDecl.Create;
ScriptData.AddDeclaration(MethodVar, CurrentNamespace);
MethodVar.Name := IdentStr;
MethodVar.IsConst := True;
MethodVar.Level := fCompilerLevel;
MethodVar.VarType := TRutisMethodType.Create;
MethodVar.Address := ScriptData.Ressources.Top;
ScriptData.Ressources.PushCardinal(Cardinal(high(ScriptData.Code) + 1));
MethodDecl := TRutisMethodType(MethodVar.VarType);
// Create Namespace...
OldNamespace := CurrentNamespace;
CurrentNamespace := UpperCase(CurrentNamespace + '.' + MethodVar.Name);
Namespace := TRutisNamespace.Create;
Namespace.Name := CurrentNamespace;
Namespace.CodeFile := CurrentUnit;
Namespace.CodeStart := length(ScriptData.Code);
SetLength(ScriptData.Namespaces, length(ScriptData.Namespaces) + 1);
ScriptData.Namespaces[high(ScriptData.Namespaces)] := Namespace;
// ... and add it to the Current-Uses List
SetLength(UnitNamespaces, length(UnitNamespaces) + 1);
UnitNamespaces[high(UnitNamespaces)] := CurrentNamespace;
OldStackVarPos := StackVarPos;
StackVarPos := 0;
VarDecl := nil;
Try
With MethodDecl Do
Begin
ParamsSize := 0;
IsFunction := bool;
MethodResult.TypeData := nil;
If IsFunction Then
Name := 'function'
Else
Name := 'procedure';
GetSym;
If IsFunction Then
Begin
VarDecl := TRutisVarDecl.Create;
ScriptData.AddDeclaration(VarDecl, Namespace.Name);
With VarDecl Do
Begin
Name := 'RESULT';
IsConst := False;
Address := StackVarPos;
Level := fCompilerLevel;
End;
Inc(StackVarPos);
End;
If IdentSym = sOpenBracket Then
C_DeclParams;
If IsFunction Then
Begin
Expect([sDopDot]);
GetSym;
MethodResult.TypeData := TRutisTypeDecl(GetDeclaration(IdentStr));
VarDecl.VarType := MethodResult.TypeData;
If (VarDecl.VarType = nil) or
(not (VarDecl.VarType is TRutisTypeDecl)) Then
Begin
RaiseError(ERR_TYPE_EXPECTED);
MethodDecl.Free;
exit;
End;
GetSym;
End;
//Get Parameters
If IsFunction Then
i := 1
Else
i := 0;
ParamsSize := 0;
SetLength(Params, 0);
For i := i To high(Namespace.Declarations) Do
If Namespace.Declarations[i] is TRutisVarDecl Then
Begin
ParamsSize := ParamsSize + TRutisVarDecl(Namespace.Declarations[i]).VarType.Size;
SetLength(Params, length(Params) + 1);
Params[high(Params)].TypeData := TRutisVarDecl(Namespace.Declarations[i]).VarType;
End;
//Get Parameter-Addresses
j := -ParamsSize;
If IsFunction Then
j := j - MethodResult.TypeData.Size;
For i := 0 To high(Namespace.Declarations) Do
If Namespace.Declarations[i] is TRutisVarDecl Then
Begin
TRutisVarDecl(Namespace.Declarations[i]).Address := j;
j := j + TRutisVarDecl(Namespace.Declarations[i]).VarType.Size;
End;
StackVarPos := 0;
Expect([sSemiColon]);
GetSym;
End;
Repeat
bool := C_DeclarationSeq or C_Method;
Until not bool;
Expect([sBegin]);
GetSym;
ExitParamsSize := MethodDecl.ParamsSize;
// MethodenfCode ======
If StackVarPos > 0 Then
Begin
ScriptData.GenCode(_gen, StackVarPos, 0, 0);
StackVarPos := 0;
End;
C_StatementSequence;
ScriptData.GenCode(_ret, MethodDecl.ParamsSize, 0, 0);
If MethodInitAddr >= 0 Then
ScriptData.Code[MethodInitAddr].P1 := high(ScriptData.Code) + 1;
Expect([sEnd]);
GetSym;
Expect([sSemiColon]);
GetSym;
// Reset Namespace
Namespace.CodeEnd := high(ScriptData.Code);
SetLength(UnitNamespaces, length(UnitNamespaces) - 1);
CurrentNamespace := OldNamespace;
//Reset StackVarPos and CurrentNamespace and decrement CompilerLevel
StackVarPos := OldStackVarPos;
Dec(fCompilerLevel);
bool := False;
For i := 0 To ScriptData.DeclarationCount - 1 Do
If ScriptData.DeclarationList[i].ClassType = TRutisMethodType Then
With TRutisMethodType(ScriptData.DeclarationList[i]) Do
Begin
If (IsFunction <> MethodDecl.IsFunction) Then Continue;
If (length(Params) <> length(MethodDecl.Params)) Then Continue;
If (ParamsSize <> MethodDecl.ParamsSize) Then Continue;
If (MethodResult.TypeData <> MethodDecl.MethodResult.TypeData) Then Continue;
bool := True;
For j := 0 To high(Params) Do
If Params[j].TypeData <> MethodDecl.Params[j].TypeData Then
Begin
bool := False;
Break;
End;
If not bool Then Continue;
Break;
End;
If bool Then
Begin
MethodDecl.Free;
MethodVar.VarType := TRutisMethodType(ScriptData.DeclarationList[i]);
End
Else
ScriptData.AddDeclaration(MethodDecl, '$SYSTEM');
Except
MethodDecl.Free;
Raise;
End;
//{!!}Owner.OnError('<- C_Method ' + MethodVar.Name, etHint);
Result := True;
End;
Procedure TRutisCompilerDelphi.C_Implementation;
Begin
Repeat
C_Declarations;
Until not C_Method;
End;
//==============================================================================
Function TRutisCompilerDelphi.C_AnalyzeIdent(IsExpression : Boolean; WantType : TRutisIntType; Var Inf : TAnalyzeIdentInfo) : TIdentType;
Var
HadPointer : Boolean;
HadAt : Boolean;
ExcludeList : Array Of TRutisDecl;
Procedure AnalyzeVar;
Var id : Integer;
Begin //AnalyzeVar
With Inf Do
Begin
//===========================================
// Copy-Types
//===========================================
While (Inf.TypeData is TRutisTypeCopy) Do
Begin
Inf.TypeData := TRutisTypeCopy(Inf.TypeData).CopyType;
End;
//===========================================
// Analyze Arrays
//===========================================
If (Inf.TypeData is TRutisArrayType) and (IdentSym = sOpenBracketR) Then
Begin
GetSym;
If HadPointer Then
Begin
If (Inf.Adr <> 0) Then
Begin
ScriptData.GenCode(_gen4, Inf.Adr, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
End;
ScriptData.GenCode(_lodp, -4, -1, 4);
End
Else
ScriptData.GenCode(_lod, Inf.Adr, Inf.Lvl, 4);
C_Expression(Owner.decl_Integer);
ScriptData.GenCode(_gen4, TRutisArrayType(Inf.TypeData).ArrayType.Size, 0, 0);
ScriptData.GenCodeV(_mult, intInteger, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
If optArrayRangeCheck Then
ScriptData.GenCodeV(_CPtr, 0, 0, 0);
HadPointer := True;
Inf.Adr := 0;
Inf.Lvl := -1;
Inf.TypeData := TRutisArrayType(Inf.TypeData).ArrayType;
Inf.InternalType := TypeData.InternalType;
Expect([sCloseBracketR]);
GetSym;
Result := itPVar;
AnalyzeVar;
exit;
End;
//===========================================
// Analyze Strings with Index
//===========================================
Inf.InternalType := TypeData.InternalType;
If (Inf.InternalType = intAString) and (IdentSym = sOpenBracketR) Then
Begin
GetSym;
//PChar(Pointer(PCardinal(PPointer(fLastAdress)^)^ + 0))^
If Result = itConst Then
Begin
ScriptData.GenCode(_lodr, Inf.Adr, 1, 0);
ScriptData.GenCode(_at, 0, 0, 0);
ScriptData.GenCode(_lodp, -4, -1, 4);
//ScriptData.GenCode(_lodp, -4, -1, 4);
End
Else
Begin
If HadPointer Then
Begin
If (Inf.Adr <> 0) Then
Begin
ScriptData.GenCode(_gen4, Inf.Adr, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
End;
ScriptData.GenCode(_lodp, -4, -1, 4);
End
Else
ScriptData.GenCode(_lod, Inf.Adr, Inf.Lvl, 4);
//ScriptData.GenCode(_lodp, -4, -1, 4);
End;
C_Expression(Owner.decl_Integer);
ScriptData.GenCode(_gen4, 1, 0, 0);
ScriptData.GenCodeV(_Sub, intInteger, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
HadPointer := True;
Inf.Adr := 0;
Inf.Lvl := -1;
TypeData := Owner.decl_AChar;
Inf.InternalType := TypeData.InternalType;
Expect([sCloseBracketR]);
GetSym;
Result := itPVar;
//AnalyzeVar;
//exit;
End;
If (Inf.InternalType = intWString) and (IdentSym = sOpenBracketR) Then
Begin
GetSym;
If Result = itConst Then
Begin
ScriptData.GenCode(_lodr, Inf.Adr, 1, 0);
ScriptData.GenCode(_at, 0, 0, 0);
ScriptData.GenCode(_lodp, -4, -1, 4);
//ScriptData.GenCode(_lodp, -4, -1, 4);
End
Else
Begin
If HadPointer Then
Begin
If (Inf.Adr <> 0) Then
Begin
ScriptData.GenCode(_gen4, Inf.Adr, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
End;
ScriptData.GenCode(_lodp, -4, -1, 4);
End
Else
ScriptData.GenCode(_lod, Inf.Adr, Inf.Lvl, 4);
//ScriptData.GenCode(_lodp, -4, -1, 4);
End;
C_Expression(Owner.decl_Integer);
ScriptData.GenCode(_gen4, 1, 0, 0);
ScriptData.GenCodeV(_Sub, intInteger, 0, 0);
ScriptData.GenCode(_gen4, 2, 0, 0);
ScriptData.GenCodeV(_Mult, intInteger, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
HadPointer := True;
Inf.Adr := 0;
Inf.Lvl := -1;
TypeData := Owner.decl_WChar;
Inf.InternalType := TypeData.InternalType;
Expect([sCloseBracketR]);
GetSym;
Result := itPVar;
//AnalyzeVar;
//exit;
End;
If IdentSym = sOpenBracketR Then
Begin
RaiseError(ERR_NEEDED_FOUND, ['Array or AnsiString', RutisVarTypeTOString[TypeData.InternalType]]); exit;
End;
//===========================================
// Analyze Pointers
//===========================================
If (TypeData is TRutisPointerType) Then
If IdentSym in [sHook, sDot] Then
Begin
If IdentSym = sHook Then GetSym;
If HadPointer Then
Begin
If Inf.Adr <> 0 Then
Begin
ScriptData.GenCode(_gen4, Inf.Adr, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
End;
ScriptData.GenCode(_lodp, -4, Inf.Lvl, 4);
End
Else
ScriptData.GenCode(_lod, Inf.Adr, Inf.Lvl, 4);
Inf.Adr := 0;
Inf.Lvl := -1;
HadPointer := True;
Result := itPVar;
TypeData := TRutisPointerType(TypeData).PointerType;
AnalyzeVar;
exit;
End;
If IdentSym = sHook Then
Begin
RaiseError(ERR_NEEDED_FOUND, ['Pointer', RutisVarTypeTOString[TypeData.InternalType]]); exit;
End;
//===========================================
// Analyze Classes
//===========================================
If (TypeData is TRutisClassType) Then
If IdentSym = sDot Then
Begin
If HadPointer Then
Begin
If Inf.Adr <> 0 Then
Begin
ScriptData.GenCode(_gen4, Inf.Adr, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
End;
ScriptData.GenCode(_lodp, -4, Inf.Lvl, 4);
End
Else
ScriptData.GenCode(_lod, Inf.Adr, Inf.Lvl, 4);
Inf.Adr := 0;
Inf.Lvl := -1;
HadPointer := True;
Result := itPVar;
TypeData := TRutisClassType(TypeData).ClassStruct;
PushScanner;
GetSym;
If (IdentSym = sIdent) and
((IdentStr = 'CLASSNAME') or
(IdentStr = 'INSTANCESIZE') or
(IdentStr = 'CLASSPARENT')) Then
Begin
TypeData := TRutisStructType(TypeData).StructTypes[0].VarType;
ScriptData.GenCode(_lodp, -4, Inf.Lvl, 4);
TypeData := TRutisPointerType(TypeData).PointerType;
id := TRutisStructType(TypeData).VarID(IdentStr);
Inf.Adr := Inf.Adr + TRutisStructType(TypeData).StructTypes[id].Address;
TypeData := TRutisStructType(TypeData).StructTypes[id].VarType;
If (IdentStr = 'CLASSNAME') Then
Begin
If Inf.Adr <> 0 Then
Begin
ScriptData.GenCode(_gen4, Inf.Adr, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
End;
ScriptData.GenCode(_lodp, -4, Inf.Lvl, 4);
Inf.Adr := 0;
TypeData := TRutisPointerType(TypeData).PointerType;
End;
GetSym;
End
Else
PopScanner;
AnalyzeVar;
exit;
End;
If IdentSym = sHook Then
Begin
RaiseError(ERR_NEEDED_FOUND, ['Pointer', RutisVarTypeTOString[TypeData.InternalType]]); exit;
End;
//===========================================
// Analyze Record-Structures
//===========================================
If (TypeData is TRutisStructType) and (IdentSym = sDot) Then
Begin
GetSym;
Expect([sIdent]);
id := TRutisStructType(TypeData).VarID(IdentStr);
If id = -1 Then
Begin
RaiseError(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]); exit;
End;
GetSym;
Inf.Adr := Inf.Adr + TRutisStructType(TypeData).StructTypes[id].Address;
TypeData := TRutisStructType(TypeData).StructTypes[id].VarType;
AnalyzeVar;
exit;
End;
If IdentSym = sDot Then
Begin
RaiseError(ERR_NEEDED_FOUND, ['Record', RutisVarTypeTOString[TypeData.InternalType]]); exit;
End;
If HadPointer Then
Begin
If (Inf.Adr <> 0) Then
Begin
ScriptData.GenCode(_gen4, Inf.Adr, 0, 0);
ScriptData.GenCodeV(_add, intInteger, 0, 0);
End;
Inf.Adr := -4;
Inf.Lvl := -1;
Result := itPVar;
exit;
End;
Inf.InternalType := TypeData.InternalType;
End;
End;
Procedure CallVarMethod;
Begin
GenLoadSaveCode(Inf.IdentType, Inf.Adr, Inf.Lvl, Inf.TypeData.Size, True);
Result := itMethod;
Inf.IdentType := Result;
{If isFunction and IsExpression Then
Begin
Inf.Lvl := -1;
Inf.Adr := 0;
Result := itFixVal;
//AnalyzeVar;
End;}
ScriptData.GenCode(_call, -1, 0, 0);
End;
Procedure CallExtMethod;
Var
TempType : TRutisExtMethodType;
i : Integer;
Begin
TempType := TRutisExtMethodType(Inf.TypeData);
With TempType Do
Begin
If IsExpression and not IsFunction Then
Begin
RaiseError(ERR_EXPECTED_FOUND, ['Function', 'Procedure']); exit;
End;
If IsFunction Then
Begin
If MethodResult.TypeData = nil Then
Begin
MethodResult.TypeData := TRutisTypeDecl(GetDeclaration(MethodResult.Name));
If (MethodResult.TypeData = nil) Then
RaiseError(ERR_UNKNOWN_TYPE, [MethodResult.Name]);
If not (MethodResult.TypeData is TRutisTypeDecl) Then
RaiseError(ERR_TYPE_EXPECTED);
MethodResult.Size := MethodResult.TypeData.Size;
MethodResult.InternalType := MethodResult.TypeData.InternalType;
End;
Inf.TypeData := MethodResult.TypeData;
ScriptData.GenCode(_gen, Inf.TypeData.Size, 0, 0);
End;
ParamsSize := 0;
If length(Params) > 0 Then
Begin
Expect([sOpenBracket]);
For i := 0 To high(Params) Do
Begin
If Params[i].TypeData = nil Then
Begin
Params[i].TypeData := TRutisTypeDecl(GetDeclaration(Params[i].Name));
If (Params[i].TypeData = nil) Then
RaiseError(ERR_UNKNOWN_TYPE, [Params[i].Name]);
If not (Params[i].TypeData is TRutisTypeDecl) Then
RaiseError(ERR_TYPE_EXPECTED);
End;
Params[i].Size := Params[i].TypeData.Size;
Params[i].InternalType := Params[i].TypeData.InternalType;
ParamsSize := ParamsSize + Params[i].TypeData.Size;
If Params[i].isVarParam Then
IdentSym := sAt
Else
GetSym;
C_Expression(Params[i].TypeData);
If (i < high(Params)) Then
Begin
If IdentSym = sCloseBracket Then
Begin
RaiseError(ERR_NOT_ENOUGH_PARAMETERS); exit;
End;
Expect([sComma]);
End;
End;
If IdentSym = sComma Then
Begin
RaiseError(ERR_TOO_MANY_PARAMETERS);
exit;
End;
Expect([sCloseBracket]);
GetSym;
End
Else
If IdentSym = sOpenBracket Then
Begin
GetSym;
Expect([sCloseBracket]);
End;
If MethodTableID < 0 Then
Begin
SetLength(ScriptData.MethodTable, Length(ScriptData.MethodTable) + 1);
ScriptData.MethodTable[high(ScriptData.MethodTable)] := TempType;
MethodTableID := high(ScriptData.MethodTable);
End;
If not IsExpression and IsFunction Then
ScriptData.GenCodeV(_ext, MethodTableID, 1, 0)
Else
ScriptData.GenCodeV(_ext, MethodTableID, 0, 0);
Result := itMethod;
If isFunction and IsExpression Then
Begin
Inf.Lvl := -1;
Inf.Adr := 0;
Result := itFixVal;
//AnalyzeVar;
End;
Inf.IdentType := Result;
exit;
End;
End;
Procedure CallRutisMethod;
Var
TempType : TRutisMethodType;
i : Integer;
Begin
TempType := TRutisMethodType(Inf.TypeData);
With TempType Do
Begin
If IsExpression and not IsFunction Then
Begin
RaiseError(ERR_EXPECTED_FOUND, ['Function', 'Procedure']); exit;
End;
If IsFunction Then
Begin
Inf.TypeData := MethodResult.TypeData;
ScriptData.GenCode(_gen, Inf.TypeData.Size, 0, 0);
End;
If length(Params) > 0 Then
Begin
Expect([sOpenBracket]);
For i := 0 To high(Params) Do
Begin
GetSym;
C_Expression(Params[i].TypeData);
If (i < high(Params)) Then
Begin
If IdentSym = sCloseBracket Then
Begin
RaiseError(ERR_NOT_ENOUGH_PARAMETERS); exit;
End;
Expect([sComma]);
End;
End;
If IdentSym = sComma Then
Begin
RaiseError(ERR_TOO_MANY_PARAMETERS);
exit;
End;
Expect([sCloseBracket]);
GetSym;
End
Else
If IdentSym = sOpenBracket Then
Begin
GetSym;
Expect([sCloseBracket]);
End;
//Prozeduraufruf
// ScriptData.GenCode(_lodr, Inf.Adr, 4, 0);
// ScriptData.GenCode(_call, -1, Inf.Lvl, 0);
ScriptData.GenCode(_call, ScriptData.Ressources.GetCardinal(Inf.Adr)^, Inf.Lvl, 0);
If not IsExpression and IsFunction Then
ScriptData.GenCode(_pupo, -Inf.TypeData.Size, 0, 0);
Result := itMethod;
If isFunction and IsExpression Then
Begin
Inf.Lvl := -1;
Inf.Adr := 0;
Result := itFixVal;
//AnalyzeVar;
End;
Inf.IdentType := Result;
exit;
End;
End;
Var
CastInf : TAnalyzeIdentInfo;
Decl : TRutisDecl;
Begin
Result := itError;
//==================================================================
Inf.TypeData := nil;
Inf.VarDecl := nil;
Inf.Adr := 0;
Inf.Lvl := 0;
Inf.IdentType := Result;
HadPointer := False;
HadAt := False;
If IdentSym = sAt Then
Begin
HadAt := True;
GetSym;
End;
Decl := GetDeclaration(IdentStr);
If Decl = nil Then
RaiseError(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]);
If (Decl is TRutisTypeDecl) Then
Begin
GetSym;
Expect([sOpenBracket]);
GetSym;
// C_Expression(nil);
// If not ExprResult.ConvertTo(TRutisTypeDecl(Decl), ScriptData) Then
// If ExprResult.Size <> TRutisTypeDecl(Decl).Size Then
// RaiseError(ERR_INCOMPATIBLE_TYPES, [TRutisTypeDecl(Decl).Name, ExprResult.Name]);
// Inf.TypeData := TRutisTypeDecl(Decl);
// Inf.Adr := -Inf.TypeData.Size;
// Inf.Lvl := 0;
// Inf.IdentType := itFixVal;
Expect([sIdent]);
C_AnalyzeIdent(True, intNone, CastInf);
If not CastInf.TypeData.ConvertTo(TRutisTypeDecl(Decl), ScriptData) Then
If CastInf.TypeData.Size <> TRutisTypeDecl(Decl).Size Then
RaiseError(ERR_INCOMPATIBLE_TYPES, [TRutisTypeDecl(Decl).Name, CastInf.TypeData.Name]);
Inf := CastInf;
Inf.TypeData := TRutisTypeDecl(Decl);
Expect([sCloseBracket]);
End
Else
Begin
If not (Decl is TRutisVarDecl) Then
RaiseError(ERR_VAR_EXPECTED, [IdentStr]);
Inf.VarDecl := TRutisVarDecl(Decl);
Inf.TypeData := Inf.VarDecl.VarType;
Inf.Adr := Inf.VarDecl.Address;
Inf.Lvl := Inf.VarDecl.Level;
Result := itVar;
End;
// Get next symbol after Ident
GetSym;
//==================================================================
//==================================================================
If HadAt Then
Begin
AnalyzeVar;
If (Inf.VarDecl.isConst) Then
Begin
If not (Inf.TypeData is TRutisMethodType) Then
Begin
RaiseError(ERR_VAR_EXPECTED); exit;
End;
If (TRutisMethodType(Inf.TypeData).IsFunction) or (TRutisMethodType(Inf.TypeData).ParamsSize > 0) Then
Begin
RaiseError(ERR_ONLY_PARAMLESS_PROCS); exit;
End;
Result := itConst;
ScriptData.GenCode(_lodr, Inf.Adr, 4, 0);
Inf.TypeData := Owner.decl_Method;
Result := itFixVal;
Inf.IdentType := Result;
Inf.InternalType := Inf.TypeData.InternalType;
exit;
End;
If not IsExpression Then
Begin
RaiseError(ERR_UNALLOWED_STATEMENT); exit;
End;
Case Result Of
itVar :
Begin
//If Inf.Adr < 0 Then
// ScriptData.GenCode(_ptr, Inf.Adr - 3, Inf.Lvl, 1)
//Else
ScriptData.GenCode(_ptr, Inf.Adr, Inf.Lvl, 1);
End;
itPVar :;
itConst :
Begin
If (Inf.TypeData is TRutisMethodType) Then
ScriptData.GenCode(_lodr, Inf.Adr, 4, 0)
Else
Begin
ScriptData.GenCode(_lodr, Inf.Adr, 1, 0);
ScriptData.GenCode(_at, 0, 0, 0);
End;
End;
Else
RaiseError(ERR_POINTER_ONLY_FOR_VAR); exit;
End;
Inf.TypeData := Owner.decl_Pointer;
Result := itFixVal;
Inf.IdentType := Result;
Inf.InternalType := Inf.TypeData.InternalType;
exit;
End;
//==================================================================
//==================================================================
If (Inf.TypeData is TRutisMethodType) Then
Begin
If TRutisMethodType(Inf.TypeData).Overloaded Then
Begin
SetLength(ExcludeList, 0);
While True Do
Begin
PushCompilerState;
SetLength(ExcludeList, length(ExcludeList) + 1);
ExcludeList[high(ExcludeList)] := Inf.VarDecl;
Try
If (Inf.TypeData is TRutisExtMethodType) or
(Inf.TypeData is TRutisDllMethodType) Then
CallExtMethod
Else
CallRutisMethod;
Except
Inf.VarDecl := TRutisVarDecl(GetDeclaration(Inf.VarDecl.Name, ExcludeList));
Inf.TypeData := Inf.VarDecl.VarType;
If Inf.VarDecl = nil Then
RaiseError(ERR_NO_OVERLOADED_FUNC);
PopCompilerState;
Continue;
End;
exit;
End;
End
Else
Begin
If (Inf.TypeData is TRutisExtMethodType) or
(Inf.TypeData is TRutisDllMethodType) Then
CallExtMethod
Else
CallRutisMethod;
exit;
End;
End;
//==================================================================
//==================================================================
//If IdentPos >= 0 Then
Begin
Result := itVar;
If inf.VarDecl.isConst and not IsExpression Then
Begin
RaiseError(ERR_VAR_EXPECTED); exit;
End;
If inf.VarDecl.isConst Then
Begin
Result := itConst;
If inf.VarDecl.VarType.InternalType = intAString Then
Begin
ScriptData.GenCode(_rstr, Inf.Adr, 0, 0);
Result := itFixVal;
End;
End;
AnalyzeVar;
Inf.IdentType := Result;
Inf.InternalType := Inf.TypeData.InternalType;
If (IdentSym <> sBecomes) and (Inf.InternalType = intMethod) Then
CallVarMethod;
exit;
End;
End;
procedure TRutisCompilerDelphi.C_Expression(WantType : TRutisTypeDecl);
Var
OldWantType : TRutisTypeDecl;
gotStr : Boolean;
// LastIntTypes : Array of TRutisIntType;
Procedure Term;
Var
FactorType : TRutisTypeDecl;
Procedure Factor;
Var
Inf : TAnalyzeIdentInfo;
bool : Boolean;
//PAnsiStr : PAnsiString;
ConvPos, i : Integer;
Decl : TRutisDecl;
Begin (*Factor*)
FactorType := nil;
ConvPos := high(ScriptData.Code);
Case IdentSym Of
sIdent, sAt :
Begin
C_AnalyzeIdent(True, WantType.InternalType, Inf);
FactorType := Inf.TypeData;
If FactorType = nil Then
RaiseError(ERR_VAR_EXPECTED);
GenLoadSaveCode(Inf.IdentType, Inf.Adr, Inf.Lvl, FactorType.Size, True);
End;
sSizeOf :
Begin
GetSym;
Expect([sOpenBracket]);
GetSym;
Decl := GetDeclaration(IdentStr);
If Decl is TRutisTypeDecl Then
Begin
ScriptData.GenCode(_Gen4, TRutisTypeDecl(Decl).Size, 0, 0);
GetSym;
End
Else
Begin
i := length(ScriptData.Code);
C_AnalyzeIdent(False, intNone, Inf);
SetLength(ScriptData.Code, i);
ScriptData.GenCode(_Gen4, Inf.TypeData.Size, 0, 0);
End;
FactorType := Owner.decl_Integer;
Expect([sCloseBracket]);
GetSym;
End;
sLength,
sHigh : With Inf Do
Begin
bool := IdentSym = sHigh;
FactorType := Owner.decl_Integer;
GetSym;
Expect([sOpenBracket]);
GetSym;
If IdentSym = sString Then
Begin
ScriptData.GenCode(_gen4, length(IdentStr), 0, 0);
If bool Then
Begin
ScriptData.GenCode(_gen4, 1, 0, 0);
ScriptData.GenCodeV(_sub, intInteger, 0, 0);
End;
GetSym;
Expect([sCloseBracket]);
GetSym;
End
Else
Begin
Expect([sIdent]);
//AllowedIdents := [vString, vArray];
C_AnalyzeIdent(True, intNone, Inf);
Case Inf.IdentType Of
itVar :
Begin
If Inf.TypeData is TRutisArrayType Then
Begin
ScriptData.GenCode(_lod, Adr, Lvl, 4);
ScriptData.GenCode(_mems, 0, 0, 1);
//If (TRutisArrayType(Inf.TypeData).ArrayType.Size > 1) Then
//Begin
// ScriptData.GenCode(_gen4, TRutisArrayType(Inf.TypeData).ArrayType.Size, 0, 0);
// ScriptData.GenCodeV(_div, intInteger, 0, 0);
//End;
End
Else
Begin
case Inf.TypeData.InternalType of
intAString:
begin
ScriptData.GenCode(_lod, Adr, Lvl, 4);
ScriptData.GenCode(_GASL, 0, 0, 0);
end;
intWString:
begin
ScriptData.GenCode(_lod, Adr, Lvl, 4);
ScriptData.GenCode(_GWSL, 0, 0, 0);
end;
else
RaiseError(ERR_EXPECTED, ['AnsiString, WideString, Array']);
end;
End;
End;
itPVar :
Begin
If Inf.TypeData is TRutisArrayType Then
Begin
ScriptData.GenCode(_lodP, Adr, Lvl, 4);
ScriptData.GenCode(_mems, 0, 0, 1);
//If (TRutisArrayType(Inf.TypeData).ArrayType.Size > 1) Then
//Begin
// ScriptData.GenCode(_gen4, TRutisArrayType(Inf.TypeData).ArrayType.Size, 0, 0);
// ScriptData.GenCodeV(_div, intInteger, 0, 0);
//End;
End
Else
Begin
case Inf.TypeData.InternalType of
intAString:
begin
ScriptData.GenCode(_lodP, Adr, Lvl, 4);
ScriptData.GenCode(_GASL, 0, 0, 0);
end;
intWString:
begin
ScriptData.GenCode(_lodP, Adr, Lvl, 4);
ScriptData.GenCode(_GWSL, 0, 0, 0);
end;
else
RaiseError(ERR_EXPECTED, ['AnsiString, WideString, Array']);
end;
End;
End;
itConst :
Begin
{ If VarInf^.VTyp = vString Then
Begin
ScriptData.GenCode(_lodr, Adr, 1, 0);
ScriptData.GenCode(_GASL, 0, 0, 0);
End
Else }
RaiseError(ERR_EXPECTED, ['AnsiString, WideString, Array']);
End;
itMethod : RaiseError(ERR_VAR_EXPECTED);
itError : RaiseError(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]);
End;
If bool Then
Begin
ScriptData.GenCode(_gen4, 1, 0, 0);
ScriptData.GenCodeV(_sub, intInteger, 0, 0);
End;
Expect([sCloseBracket]);
GetSym;
End;
End;
sTrue, sFalse :
Begin
ScriptData.GenCode(_gen1, Integer(Boolean(IdentSym = sTrue)), 0, 0);
FactorType := Owner.decl_Boolean;
GetSym;
End;
sopAnd :
Begin
GetSym;
Factor;
If WantType = nil Then
RaiseError('ERROR - C_Expression - Term - Factor');
ScriptData.GenCodeV(_And, WantType.Size, 0, 0);
End;
sopOr :
Begin
GetSym;
Factor;
If WantType = nil Then
RaiseError('ERROR - C_Expression - Term - Factor');
ScriptData.GenCodeV(_Or, WantType.Size, 0, 0);
End;
sopXOr :
Begin
GetSym;
Factor;
If WantType = nil Then
RaiseError('ERROR - C_Expression - Term - Factor');
ScriptData.GenCodeV(_XOr, WantType.Size, 0, 0);
End;
sopNot :
Begin
GetSym;
Factor;
If WantType = nil Then
RaiseError('ERROR - C_Expression - Term - Factor');
If WantType.InternalType = intBoolean Then
ScriptData.GenCodeV(_Not, WantType.Size, 1, 0)
Else
ScriptData.GenCodeV(_Not, WantType.Size, 0, 0);
End;
sOpenBracket :
Begin
GetSym;
C_Expression(WantType);
FactorType := ExprResult;
Expect([sCloseBracket]);
GetSym;
End;
sOpenBracketR :
Begin
If WantType = nil then WantType := Owner.decl_Set4;
//If WantType.InternalType = intAString Then
// RaiseError(ERR_UNALLOWED_STRING_ACTION);
If not (WantType.InternalType in Internalintegers + [intSet]) Then
RaiseError(ERR_UNALLOWED_STRING_ACTION);
GetSym;
ScriptData.GenCode(_gen, WantType.Size, 0, 0);
If IdentSym <> sCloseBracketR Then
While True Do
Begin
C_Expression(Owner.decl_Enum);
ScriptData.GenCodeV(_ets, WantType.Size, 0, 0);
ScriptData.GenCodeV(_add, intSet, WantType.Size, 0);
If IdentSym = sCloseBracketR Then break;
Expect([sComma]);
GetSym;
End;
FactorType := Owner.decl_Set4;
Expect([sCloseBracketR]);
GetSym;
End;
sInteger :
Begin
//If WantType.InternalType = intAString Then
// RaiseError(ERR_UNALLOWED_STRING_ACTION);
If WantType.InternalType = intSingle then
begin
FactorType := Owner.decl_Single;
ScriptData.GenCodeV(_gen4, Single(IdentNum), 0, 0);
end
else
begin
FactorType := Owner.decl_Integer;
ScriptData.GenCode(_gen4, IdentNum, 0, 0);
end;
GetSym;
End;
sFloat :
Begin
FactorType := Owner.decl_Single;
ScriptData.GenCodeV(_gen4, Single(IdentNum), 0, 0);
GetSym;
End;
sNil :
Begin
FactorType := Owner.decl_Pointer;
ScriptData.GenCode(_gen4, 0, 0, 0);
GetSym;
End;
sString :
Begin
If (length(IdentStr) = 1) and (WantType.InternalType in [intAChar, intNone]) Then
Begin
ScriptData.GenCode(_Gen1, Ord(IdentStr[1]), 0, 0);
FactorType := Owner.decl_AChar;
End
Else
Begin
FactorType := Owner.decl_AString;
Bool := False;
For I := 0 To high(ResStrings) Do
If ResStrings[i].Value = IdentStr Then
Begin
ScriptData.GenCode(_rstr, ResStrings[i].Address, 0, 0);
Bool := True;
break;
End;
If not Bool Then
Begin
SetLength(ResStrings, length(ResStrings) + 1);
ResStrings[high(ResStrings)].Address := ScriptData.Ressources.Top + 4;
ResStrings[high(ResStrings)].Value := IdentStr;
ScriptData.GenCode(_rstr, ScriptData.Ressources.Top + 4, 0, 0);
ScriptData.Ressources.PushAStringData(IdentStr);
End;
End;
GetSym;
End;
Else
ErrorExpected([sInteger, sFloat, sString, sIdent, sOpenBracket], IdentSym);
End;
If (WantType = nil) Then
WantType := FactorType
Else
If (FactorType <> nil) and (WantType <> FactorType) Then
Begin
If (OldWantType.InternalType = intNone) and
(WantType.InternalType in InternalIntegers) and
(FactorType.InternalType in InternalFloats) Then
Begin
ScriptData.CodeInsertPos := ConvPos;
WantType.ConvertTo(FactorType, ScriptData);
ScriptData.CodeInsertPos := -1;
WantType := FactorType;
End
Else
If not FactorType.ConvertTo(WantType, ScriptData) Then
RaiseError(ERR_INCOMPATIBLE_TYPES,
[WantType.Name, FactorType.Name]);
End;
End;
(*Factor*)
Var
Operation : TRutisSymbol;
Begin(*Term*)
Factor;
If not gotStr then
begin
If (WantType.InternalType = intAString) Then
ScriptData.GenCode(_copyastr, 0, 0, 0);
If (WantType.InternalType = intWString) Then
ScriptData.GenCode(_copywstr, 0, 0, 0);
gotStr := True;
end;
While IdentSym in [sStar, sSlash, sMod, sopAnd, sopOr, sopXOr] Do
Begin
Operation := IdentSym;
GetSym;
Factor;
If (WantType.InternalType in [intAString, intWString]) {and (Operation in [sStar, sSlash])} Then
RaiseError(ERR_UNALLOWED_STRING_ACTION);
Case Operation Of
sStar : ScriptData.GenCodeV(_mult, WantType.InternalType, 0, 0);
sSlash : ScriptData.GenCodeV(_div, WantType.InternalType, 0, 0);
sMod :
Begin
If not (WantType.InternalType in InternalIntegers) Then
RaiseError(ERR_NEEDED_FOUND, ['ordinal type', WantType.Name]);
ScriptData.GenCodeV(_mod, WantType.InternalType, 0, 0);
End;
sopAnd : ScriptData.GenCodeV(_And, WantType.Size, 0, 0);
sopOr : ScriptData.GenCodeV(_Or, WantType.Size, 0, 0);
sopXOr : ScriptData.GenCodeV(_XOr, WantType.Size, 0, 0);
End;
End;
End;
(*Term*)
//==============================================================================
Var
Operation : TRutisSymbol;
TempCodepos : Integer;
Begin (*Expresion*)
gotStr := False;
OldWantType := WantType;
If WantType <> nil Then
If WantType.InternalType = intBoolean Then
WantType := nil;
If (IdentSym in [sPlus, sMinus]) Then
Begin
Operation := IdentSym;
TempCodepos := 0;
If Operation = sMinus Then
TempCodepos := ScriptData.GenCode(_gen, -1, 0, 0);
GetSym;
Term;
If Operation = sMinus Then
Begin
ScriptData.Code[TempCodepos].P1 := WantType.Size;
ScriptData.GenCodeV(_sub, WantType.InternalType, 0, 0);
End;
End
Else
Term;
While (IdentSym in [sPlus, sMinus]) Do
Begin
Operation := IdentSym;
GetSym;
Term;
Case Operation Of
sPlus : ScriptData.GenCodeV(_add, WantType.InternalType, WantType.Size, 0);
sMinus : ScriptData.GenCodeV(_sub, WantType.InternalType, WantType.Size, 0);
End;
End;
If (IdentSym in [sEqual..sUnEqual]) Then
Begin
If not (OldWantType.InternalType in [intNone, intBoolean]) Then
RaiseError(
ERR_INCOMPATIBLE_TYPES,
[OldWantType.Name, Owner.decl_Boolean.Name]);
Operation := IdentSym;
GetSym;
//C_Expression(nil);
C_Expression(WantType);
If (ExprResult.InternalType in [intNone, intRecord, intShortString]) Then
RaiseError('Value expected');
Case Operation Of
sEqual : ScriptData.GenCodeV(_opr, ocEqual, WantType.InternalType, ExprResult.InternalType);
sBigger : ScriptData.GenCodeV(_opr, ocGreater, WantType.InternalType, ExprResult.InternalType);
sSmaller : ScriptData.GenCodeV(_opr, ocLess, WantType.InternalType, ExprResult.InternalType);
sBiggerEqual : ScriptData.GenCodeV(_opr, ocGEqual, WantType.InternalType, ExprResult.InternalType);
sSmallerEqual : ScriptData.GenCodeV(_opr, ocLEqual, WantType.InternalType, ExprResult.InternalType);
sUnEqual : ScriptData.GenCodeV(_opr, ocUnequal, WantType.InternalType, ExprResult.InternalType);
End;
WantType := Owner.decl_Boolean;
End;
ExprResult := WantType;
End; (*Expression*)
Procedure TRutisCompilerDelphi.C_StatementSequence;
Procedure Statement;
Var
Inf : TAnalyzeIdentInfo;
//================================
(*Condition*)
Procedure IfStruct;
Var
FailJumpPos, fCodePosition2 : Integer;
Begin
GetSym;
C_Expression(Owner.decl_Boolean);
Expect([sThen]);
GetSym;
ScriptData.GenCodeV(_JZ, 0, intBoolean, 0);
FailJumpPos := high(ScriptData.Code);
Statement;
If IdentSym <> sSemicolon Then
Begin
ScriptData.GenCode(_jmp, 0, 0, 0);
fCodePosition2 := high(ScriptData.Code);
ScriptData.Code[FailJumpPos].P1 := high(ScriptData.Code) + 1;
While IdentSym = sElseIf Do
Begin
GetSym;
C_Expression(Owner.decl_Boolean);
Expect([sThen]);
GetSym;
ScriptData.GenCodeV(_JZ, 0, intBoolean, 0);
FailJumpPos := high(ScriptData.Code);
Statement;
ScriptData.GenCode(_jmp, 0, 0, 0);
ScriptData.Code[fCodePosition2].P1 := high(ScriptData.Code);
fCodePosition2 := high(ScriptData.Code);
ScriptData.Code[FailJumpPos].P1 := high(ScriptData.Code) + 1;
End;
If IdentSym = sElse Then
Begin
GetSym;
Statement;
End
Else
If IdentSym <> sElseIf Then
RaiseError('If-Semicolon');
ScriptData.Code[fCodePosition2].P1 := high(ScriptData.Code) + 1;
End
Else
ScriptData.Code[FailJumpPos].P1 := high(ScriptData.Code) + 1;
End;
//================================
Procedure WhileStruct;
Var
StartPos,
EndPos, i : Integer;
Begin
GetSym;
StartPos := high(ScriptData.Code) + 1;
//==== Check Loop-Condition
C_Expression(Owner.decl_Boolean);
Expect([sDo]);
GetSym;
ScriptData.GenCodeV(_JZ, 0, intBoolean, 0);
EndPos := high(ScriptData.Code);
//==== Loop-Code
Inc(LoopDepth);
Statement;
Dec(LoopDepth);
//==== Jump to Loop-Start
ScriptData.GenCode(_jmp, StartPos, 0, 0);
ScriptData.Code[EndPos].P1 := high(ScriptData.Code) + 1;
//==== Continue / Break Jumps
For i := EndPos + 1 To high(ScriptData.Code) Do
Begin
If (ScriptData.Code[i].Cmd = _jmp) and
(ScriptData.Code[i].P1 = -10) Then
ScriptData.Code[i].P1 := StartPos;
If (ScriptData.Code[i].Cmd = _jmp) and
(ScriptData.Code[i].P1 = -20) Then
ScriptData.Code[i].P1 := high(ScriptData.Code) + 1;
End;
End;
Procedure RepeatStruct;
Var
StartPos, i : Integer;
Begin
GetSym;
StartPos := high(ScriptData.Code) + 1;
//==== Loop-Code
Inc(LoopDepth);
C_StatementSequence;
Dec(LoopDepth);
Expect([sUntil]);
GetSym;
//==== Check Loop-Condition
C_Expression(Owner.decl_Boolean);
ScriptData.GenCodeV(_JZ, StartPos, intBoolean, 0);
//==== Continue / Break Jumps
For i := StartPos To high(ScriptData.Code) Do
Begin
If (ScriptData.Code[i].Cmd = _jmp) and
(ScriptData.Code[i].P1 = -10) Then
ScriptData.Code[i].P1 := StartPos;
If (ScriptData.Code[i].Cmd = _jmp) and
(ScriptData.Code[i].P1 = -20) Then
ScriptData.Code[i].P1 := high(ScriptData.Code) + 1;
End;
End;
Procedure ForStruct;
Var
i,
StartPos : Integer;
downtoloop : Boolean;
IdentVar : TRutisVarDecl;
Begin
GetSym;
Expect([sIdent]);
IdentVar := TRutisVarDecl(GetDeclaration(IdentStr));
If (IdentVar = nil) Then
Begin
RaiseError(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]);
exit;
End;
If not (IdentVar is TRutisVarDecl) Then
Begin
RaiseError(ERR_VAR_EXPECTED);
exit;
End;
If not (IdentVar.VarType is TRutisVarType) Then
Begin
RaiseError(ERR_VAR_EXPECTED);
exit;
End;
If not (IdentVar.VarType.InternalType in InternalIntegers) Then
Begin
RaiseError(ERR_EXPECTED, ['Integer']);
exit;
End;
GetSym;
Expect([sBecomes]);
GetSym;
//==== Loop-Start Value
C_Expression(IdentVar.VarType);
With IdentVar Do
ScriptData.GenCode(_sto, Address, Level, IdentVar.VarType.Size);
downtoloop := IdentSym = sDownTo;
If not downtoloop and not Expect([sTo]) Then exit;
GetSym;
//==== Loop-End Value
C_Expression(IdentVar.VarType);
case IntTypeSizes[IdentVar.VarType.InternalType] of
1 : ScriptData.GenCode(_gen1, 1, 0, 0);
2 : ScriptData.GenCode(_gen2, 1, 0, 0);
4 : ScriptData.GenCode(_gen4, 1, 0, 0);
else
RaiseError(ERR_UNEXPECTED_ERROR);
end;
ScriptData.GenCodeV(_add, IdentVar.VarType.InternalType, 0, 0);
Expect([sDo]);
GetSym;
StartPos := high(ScriptData.Code) + 1;
//==== Check Loop-End
With IdentVar Do
Begin
ScriptData.GenCode(_lod, -VarType.Size, 0, VarType.Size);
ScriptData.GenCode(_lod, Address, Level, VarType.Size);
ScriptData.GenCodeV(_sub, VarType.InternalType, 0, 0);
If downtoloop Then
ScriptData.GenCodeV(_JGZ, 0, VarType.InternalType, 0)
Else
ScriptData.GenCodeV(_JLZ, 0, VarType.InternalType, 0);
End;
//==== Loop-Code
Inc(LoopDepth);
Statement;
Dec(LoopDepth);
//==== i := i + 1 // i := i - 1
If downtoloop Then
ScriptData.GenCode(_gen4, -1, 0, 0)
Else
ScriptData.GenCode(_gen4, 1, 0, 0);
With IdentVar Do
ScriptData.GenCode(_inc, Address, Level, Word(VarType.InternalType)); //}
//==== Jump to Loop-Start
ScriptData.GenCode(_jmp, StartPos, 0, 0);
ScriptData.Code[StartPos + 3].P1 := high(ScriptData.Code) + 1;
//==== Continue / Break Jumps
For i := StartPos To high(ScriptData.Code) Do
Begin
If (ScriptData.Code[i].Cmd = _jmp) and
(ScriptData.Code[i].P1 = -10) Then
ScriptData.Code[i].P1 := high(ScriptData.Code) - 2;
If (ScriptData.Code[i].Cmd = _jmp) and
(ScriptData.Code[i].P1 = -20) Then
ScriptData.Code[i].P1 := high(ScriptData.Code) + 1;
End;
ScriptData.GenCode(_pupo, -IdentVar.VarType.Size, 0, 0);
End;
//================================
Procedure IdentFoundHandler;
Var
InsertPos : Integer;
Begin
If IdentStr = '' Then exit;
With Inf Do
Begin
InsertPos := high(ScriptData.Code) + 1;
Case C_AnalyzeIdent(False, intNone, Inf) Of
itVar :
Begin
Expect([sBecomes]);
GetSym;
case Inf.TypeData.InternalType of
intAString: ScriptData.GenCode(_StoAStr, Adr, Lvl, 0);
intWString: ScriptData.GenCode(_StoWStr, Adr, Lvl, 0);
Else
ScriptData.GenCode(_sto, Adr, Lvl, Inf.TypeData.Size);
end;
// Insert expression code before store-statements
ScriptData.CodeInsertPos := InsertPos;
C_Expression(Inf.TypeData);
End;
itPVar :
Begin
Expect([sBecomes]);
GetSym;
If Lvl = -1 Then Adr := -4;
case Inf.TypeData.InternalType of
intAString: ScriptData.GenCode(_StoAStr, Adr, Lvl, 1);
intWString: ScriptData.GenCode(_StoWStr, Adr, Lvl, 1);
Else
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
end;
// Insert expression code before store-statements
ScriptData.CodeInsertPos := InsertPos;
C_Expression(Inf.TypeData);
End;
itConst : RaiseError(ERR_NO_CONST_ALLOWED);
itError : RaiseError(ERR_UNKNOWN_IDENT, [LowerCase(IdentStr)]);
End;
// Reset Insert-Pos
ScriptData.CodeInsertPos := -1;
End;
End;
//================================
Procedure Code_SetLength;
Begin
With Inf Do
Begin
GetSym;
Expect([sOpenBracket]);
GetSym;
//AllowedIdents := [VArray, VString];
C_AnalyzeIdent(False, intNone, Inf);
If not (Inf.TypeData.InternalType in [intArray, intAString]) Then
Begin
RaiseError(ERR_EXPECTED, ['Array, AnsiString']);
exit;
End;
Case Inf.IdentType Of
itVar : ScriptData.GenCode(_lod, Adr, Lvl, Inf.TypeData.Size);
itPVar :
Begin
If Lvl = -1 Then
ScriptData.GenCode(_lod, Adr, Lvl, Inf.TypeData.Size);
ScriptData.GenCode(_lodp, Adr, Lvl, Inf.TypeData.Size);
End;
Else
RaiseError('ERROR - SetLength');
exit;
End;
Expect([sComma]);
GetSym;
C_Expression(Owner.decl_Integer);
If not (ExprResult.InternalType in InternalIntegers) Then
RaiseError(ERR_EXPECTED_FOUND, ['Integer', ExprResult.Name]);
Expect([sCloseBracket]);
GetSym;
If TypeData is TRutisArrayType Then
Begin
ScriptData.GenCode(_gen4, TRutisArrayType(TypeData).ArrayType.Size, 0, 0);
ScriptData.GenCode(_smem, 0, 0, 0);
End
Else
Begin
If Inf.TypeData.InternalType = intAString Then
Begin
ScriptData.GenCode(_SASL, 0, 0, 0);
End
Else
Begin
RaiseError('ERROR'); exit;
End;
End;
Case IdentType Of
itVar : ScriptData.GenCode(_sto, Adr, Lvl, Inf.TypeData.Size);
itPVar :
Begin
If Lvl = -1 Then
Begin
ScriptData.GenCode(_lod, -8, -1, 4);
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
ScriptData.GenCode(_pupo, -4, 0, 0);
End
Else
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
End;
End;
//If MethodResult.TypeData = VArray then
//begin
//end;
End;
End;
Procedure Code_ReallocMem;
Begin
With Inf Do
Begin
GetSym;
Expect([sOpenBracket]);
GetSym;
C_AnalyzeIdent(False, intPointer, Inf);
If not (Inf.TypeData.InternalType in [intPointer, intArray]) Then
Begin
RaiseError(ERR_EXPECTED, ['Pointer']);
exit;
End;
Case Inf.IdentType Of
itVar : ScriptData.GenCode(_lod, Adr, Lvl, Inf.TypeData.Size);
itPVar :
Begin
If Lvl = -1 Then
ScriptData.GenCode(_lod, Adr, Lvl, Inf.TypeData.Size);
ScriptData.GenCode(_lodp, Adr, Lvl, Inf.TypeData.Size);
End;
Else
RaiseError('ERROR - ReallocMem');
exit;
End;
Expect([sComma]);
GetSym;
C_Expression(Owner.decl_Integer);
If not (ExprResult.InternalType in InternalIntegers) Then
RaiseError(ERR_EXPECTED_FOUND, ['Integer', ExprResult.Name]);
Expect([sCloseBracket]);
GetSym;
ScriptData.GenCode(_gen4, 1, 0, 0);
ScriptData.GenCode(_smem, 0, 0, 0);
Case IdentType Of
itVar : ScriptData.GenCode(_sto, Adr, Lvl, Inf.TypeData.Size);
itPVar :
Begin
If Lvl = -1 Then
Begin
ScriptData.GenCode(_lod, -8, -1, 4);
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
ScriptData.GenCode(_pupo, -4, 0, 0);
End
Else
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
End;
End;
End;
End;
Procedure Code_New;
Begin
With Inf Do
Begin
GetSym;
Expect([sOpenBracket]);
GetSym;
C_AnalyzeIdent(False, intPointer, Inf);
If not (Inf.TypeData is TRutisPointerType) Then
Begin
RaiseError(ERR_EXPECTED, ['typed Pointer']);
exit;
End;
Case Inf.IdentType Of
itVar : ScriptData.GenCode(_lod, Adr, Lvl, Inf.TypeData.Size);
itPVar :
Begin
If Lvl = -1 Then
ScriptData.GenCode(_lod, Adr, Lvl, Inf.TypeData.Size);
ScriptData.GenCode(_lodp, Adr, Lvl, Inf.TypeData.Size);
End;
Else
RaiseError('ERROR - New');
exit;
End;
Expect([sCloseBracket]);
GetSym;
ScriptData.GenCode(_gen4, TRutisPointerType(Inf.TypeData).PointerType.Size, 0, 0);
ScriptData.GenCode(_gen4, 1, 0, 0);
ScriptData.GenCode(_smem, 0, 0, 0);
Case IdentType Of
itVar : ScriptData.GenCode(_sto, Adr, Lvl, Inf.TypeData.Size);
itPVar :
Begin
If Lvl = -1 Then
Begin
ScriptData.GenCode(_lod, -8, -1, 4);
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
ScriptData.GenCode(_pupo, -4, 0, 0);
End
Else
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
End;
End;
End;
End;
Procedure Code_Dispose;
Begin
With Inf Do
Begin
GetSym;
Expect([sOpenBracket]);
GetSym;
C_AnalyzeIdent(False, intPointer, Inf);
If not (Inf.TypeData.InternalType in [intPointer, intArray]) Then
Begin
RaiseError(ERR_EXPECTED, ['Pointer']);
exit;
End;
Case Inf.IdentType Of
itVar : ScriptData.GenCode(_lod, Adr, Lvl, Inf.TypeData.Size);
itPVar :
Begin
If Lvl = -1 Then
ScriptData.GenCode(_lod, Adr, Lvl, Inf.TypeData.Size);
ScriptData.GenCode(_lodp, Adr, Lvl, Inf.TypeData.Size);
End;
Else
RaiseError('ERROR - New');
exit;
End;
Expect([sCloseBracket]);
GetSym;
ScriptData.GenCode(_gen4, 0, 0, 0);
ScriptData.GenCode(_gen4, 0, 0, 0);
ScriptData.GenCode(_smem, 0, 0, 0);
Case IdentType Of
itVar : ScriptData.GenCode(_sto, Adr, Lvl, Inf.TypeData.Size);
itPVar :
Begin
If Lvl = -1 Then
Begin
ScriptData.GenCode(_lod, -8, -1, 4);
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
ScriptData.GenCode(_pupo, -4, 0, 0);
End
Else
ScriptData.GenCode(_stop, Adr, Lvl, Inf.TypeData.Size);
End;
End;
End;
End;
//================================
Var
i : Integer;
sym : TRutisSymbol;
Begin (*Statement*)
If CompilingUnit Then
ScriptData.CompilerLine := -1
Else
ScriptData.CompilerLine := ScannerLine;
sym := IdentSym;
Case sym Of
sIdent : IdentFoundHandler;
sIf : IfStruct;
sWhile : WhileStruct;
sRepeat : RepeatStruct;
sFor : ForStruct;
sWrite :
Begin
GetSym;
C_Expression(nil);
ScriptData.GenCodeV(_wri, ExprResult.InternalType, 0, 0);
End;
sNop :
Begin
ScriptData.GenCode(_nocmd, 0, 0, 0);
GetSym;
End;
sTerminate :
Begin
ScriptData.GenCode(_jmp, -5, 0, 0);
GetSym;
End;
sInc,
sDec :
Begin
GetSym;
Expect([sOpenBracket]);
GetSym;
If sym = sInc Then
ScriptData.GenCode(_Gen4, 1, 0, 0)
Else
ScriptData.GenCode(_Gen4, -1, 0, 0);
i := high(ScriptData.Code);
C_AnalyzeIdent(False, intNone, Inf);
If IdentSym = sComma Then
Begin
GetSym;
If i < high(ScriptData.Code) Then
Begin
RaiseError('ERROR - Statement'); exit;
End;
SetLength(ScriptData.Code, length(ScriptData.Code) - 1);
If sym = sDec Then
ScriptData.GenCode(_Gen4, 0, 0, 0);
C_Expression(Owner.decl_Integer);
If sym = sDec Then
ScriptData.GenCodeV(_Sub, intInteger, 0, 0);
End;
With Inf Do
Case Inf.IdentType Of
itVar : ScriptData.GenCodeV(_inc, Adr, Lvl, Inf.TypeData.InternalType);
//itPVar : ScriptData.GenCode(_incp, Adr, Lvl, Inf.TypeData.Size);
Else
RaiseError('ERROR - Value expected'); exit;
exit;
End;
Expect([sCloseBracket]);
GetSym;
End;
sSetLength : Code_SetLength;
sReallocMem : Code_ReallocMem;
sNew : Code_New;
sDispose : Code_Dispose;
sContinue :
Begin
If LoopDepth <= 0 Then
Begin
RaiseError('Continue and Break can only be used in loops');
exit;
End;
ScriptData.GenCode(_jmp, -10, 0, 0);
GetSym;
End;
sBreak :
Begin
If LoopDepth <= 0 Then
Begin
RaiseError('Continue and Break can only be used in loops');
exit;
End;
ScriptData.GenCode(_jmp, -20, 0, 0);
GetSym;
End;
sExit :
Begin
ScriptData.GenCode(_ret, ExitParamsSize, 0, 0);
GetSym;
End;
sBegin :
Begin
GetSym;
C_StatementSequence;
If IdentSym <> sEnd Then
Begin
RaiseError(ERR_OP_OR_SEMI_EXPECTED);
exit;
End;
//Expect([sEnd]);
GetSym;
End;
Else
(*Der Fehler darf getrost ignoriert werden*)
//Error(ERR_UNALLOWED_STATEMENT)
End;
End; (*Statement*)
Begin (*Statement Sequence*)
Statement;
While IdentSym = sSemiColon Do
Begin
GetSym;
Statement;
End;
End; (*Statement Sequence*)
//==============================================================================
//==============================================================================
Function TRutisCompilerDelphi.GetDeclaration(Name : AnsiString) : TRutisDecl;
Var
i : Integer;
Begin
For i := high(UnitNamespaces) Downto 0 Do
Begin
Result := ScriptData.GetDeclaration(Name, UnitNamespaces[i]);
If Result <> nil Then exit;
End;
Result := ScriptData.GetDeclaration(Name, '$SYSTEM');
If Result <> nil Then exit;
Result := ScriptData.GetDeclaration(Name, '$STATIC');
End;
Function TRutisCompilerDelphi.GetDeclaration(Name : AnsiString; Exclude : Array Of TRutisDecl) : TRutisDecl;
Var
i : Integer;
Begin
For i := high(UnitNamespaces) Downto 0 Do
Begin
Result := ScriptData.GetDeclaration(Name, UnitNamespaces[i], Exclude);
If Result <> nil Then exit;
End;
Result := ScriptData.GetDeclaration(Name, '$SYSTEM', Exclude);
If Result <> nil Then exit;
Result := ScriptData.GetDeclaration(Name, '$STATIC', Exclude);
End;
Function TRutisCompilerDelphi.GetDeclarationID(Name : AnsiString) : Integer;
Var
i : Integer;
Begin
For i := high(UnitNamespaces) Downto 0 Do
Begin
Result := ScriptData.GetDeclarationId(Name, UnitNamespaces[i]);
If Result <> -1 Then exit;
End;
Result := ScriptData.GetDeclarationId(Name, '$SYSTEM');
End;
Function TRutisCompilerDelphi.CheckRedefinition(Name : AnsiString) : Boolean;
Begin
Result := ScriptData.GetDeclarationId(Name, CurrentNamespace) <> -1;
If not Result Then
Result := ScriptData.GetDeclarationId(Name, '$SYSTEM') <> -1;
If not Result Then
Result := ScriptData.GetDeclarationId(Name, '$STATIC') <> -1;
//If Result Then
// RaiseError(ERR_INDENT_REDEFINED, [Name]);
End;
//==============================================================================
//==============================================================================
Procedure TRutisCompilerDelphi.PushScanner;
Begin
PushScannerLine := ScannerLine;
PushScannerStrPos := ScannerStrPos;
PushScannerCh := ScannerCh;
PushIdentSym := IdentSym;
End;
Procedure TRutisCompilerDelphi.PopScanner;
Begin
ScannerLine := PushScannerLine;
ScannerStrPos := PushScannerStrPos;
ScannerCh := PushScannerCh;
IdentSym := PushIdentSym;
End;
//==============================================================================
Procedure TRutisCompilerDelphi.PushCompilerState;
Begin
SetLength(CompilerStates, length(CompilerStates) + 1);
With CompilerStates[high(CompilerStates)] Do
Begin
CSScannerLine := ScannerLine;
CSScannerStrPos := ScannerStrPos;
CSScannerCh := ScannerCh;
CSIdentSym := IdentSym;
CSCodePos := length(ScriptData.Code);
End;
End;
Procedure TRutisCompilerDelphi.PopCompilerState;
Begin
With CompilerStates[high(CompilerStates)] Do
Begin
ScannerLine := CSScannerLine;
ScannerStrPos := CSScannerStrPos;
ScannerCh := CSScannerCh;
IdentSym := CSIdentSym;
SetLength(ScriptData.Code, CSCodePos);
End;
SetLength(CompilerStates, length(CompilerStates) - 1);
End;
//==============================================================================
Procedure TRutisCompilerDelphi.GetSym;
Var
doUpCase : Boolean;
Procedure GetCh;
Begin
If ScannerStrPos < 1 Then
ScannerStrPos := 1;
If ScannerLine > ScriptCode.Count - 1 Then
Begin
ScannerCh := #255;
exit;
End;
If ScannerLine < 0 Then
Begin
ScannerLine := 0;
ScannerStrPos := 1;
ScannerCh := ' ';
exit;
End;
If ScannerStrPos > length(ScriptCode[ScannerLine]) Then
Begin
Inc(ScannerLine);
ScannerStrPos := 1;
ScannerCh := ' ';
exit;
End;
ScannerCh := ScriptCode[ScannerLine][ScannerStrPos];
If doUpCase Then
ScannerCh := UpCase(ScannerCh); //Case in-sensitiVe
Inc(ScannerStrPos);
End;
Var
sym : TRutisSymbol;
Begin
LastScannerLine := ScannerLine;
LastScannerStrPos := ScannerStrPos;
doUpCase := True;
While True Do
Begin
IdentSym := sNone;
IdentStr := '';
While ScannerCh in [' ', #0, #13, #10] Do
GetCh;
Case ScannerCh Of
'A'..'Z', '_' : (*Ident/ReserVed Word*)
Begin
While ScannerCh in ['A'..'Z', '_', '0'..'9'] Do
Begin
IdentStr := IdentStr + ScannerCh;
GetCh;
End;
IdentSym := sIdent;
For sym := sUnknown To sNone Do
If IdentStr = cSymbols[sym] Then
Begin
IdentSym := sym;
Break;
End;
Exit;
End;
';', '+', '-', '=', ',', '.', '*', '(', ')', '^', '@', '[', ']' :
Begin (*IdentSyme die nur aus 1 Zeichen bestehen k<>nnen*)
IdentStr := ScannerCh;
IdentSym := sUnknown;
For sym := sUnknown To sNone Do
If IdentStr = cSymbols[sym] Then
Begin
IdentSym := sym;
Break;
End;
GetCh;
Exit;
End; (*IdentSyme die nur aus 1 Zeichen bestehen k<>nnen*)
':', '<', '>' :
Begin
IdentStr := ScannerCh;
GetCh;
If ScannerCh in ['=', '<', '>'] Then
Begin
IdentStr := IdentStr + ScannerCh;
GetCh;
End;
For sym := sUnknown To sNone Do
If IdentStr = cSymbols[sym] Then
Begin
IdentSym := sym;
Break;
End;
exit;
End;
'/' : (* Zeichen die ein naScannerChfolgendes Zeichen haben k<>nnen(in diesm Falle ein = )*)
Begin
IdentStr := ScannerCh;
GetCh;
If ScannerCh = '/' Then
Begin
Inc(ScannerLine);
ScannerStrPos := 1;
GetCh;
continue;
End
Else
Begin
IdentSym := sSlash;
exit;
End;
End;
'{' :
Begin
Repeat
GetCh;
Until (ScannerCh = '}') or (ScannerCh = #255);
GetCh;
continue;
End;
''''{'} :(*Strings*)
Begin
IdentSym := sString;
doUpCase := False;
GetCh;
IdentStr := '';
If (ScannerCh = '''') Then
GetCh
Else
While True Do
Begin
IdentStr := IdentStr + ScannerCh;
GetCh;
If (ScannerCh = '''') Then
Begin
GetCh;
If (ScannerCh <> '''') Then
Break;
End;
If ScannerCh = #255 Then
exit;
End;
doUpCase := True;
exit;
End;
'0'..'9', '$' : (*Zahlen*)
Begin
IdentSym := sInteger;
IdentStr := ScannerCh;
GetCh;
If (IdentStr = '$') Then
Begin
//HexZahl
While ScannerCh in ['0'..'9', 'A'..'F'] Do
Begin
IdentStr := IdentStr + ScannerCh;
GetCh;
End;
IdentNum := StrToInt(IdentStr);
Exit;
End
Else
Begin
//NormaleZahl
While ScannerCh in ['0'..'9', '.', 'E'] Do
Begin
IdentStr := IdentStr + ScannerCh;
If (ScannerCh = '.') or
(ScannerCh = 'E') Then
IdentSym := sFloat;
GetCh;
End;
If IdentSym = sInteger Then
IdentNum := StrToInt(IdentStr)
Else
IdentNum := StrToFloat(IdentStr);
Exit;
End;
End; (*Zahlen*)
#255 : exit;
Else
RaiseError(ERR_SCANNER_UNEXPECTED_CHAR + ': ''' + ScannerCh + '''');
exit;
End;
End;
End;
//==============================================================================
End.