8e8cc3ff1f4a490ffa65173c25536df843440fff
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE a_modes.inc}
19 interface
21 uses
25 // ////////////////////////////////////////////////////////////////////////// //
26 type
28 public
34 public
37 public
42 // ////////////////////////////////////////////////////////////////////////// //
43 type
45 private
51 public
60 // ////////////////////////////////////////////////////////////////////////// //
61 type
63 public
73 public
76 public
81 class procedure parseError (pr: TTextParser; const afmt: AnsiString; const args: array of const);
92 public
99 private
101 public
110 private
112 public
121 private
123 public
134 private
136 public
143 public
149 public
155 private
158 public
167 private
169 private
171 public
177 TBinExprAdd = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
178 TBinExprSub = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
179 TBinExprMul = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
180 TBinExprDiv = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
181 TBinExprMod = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
183 TBinExprLogAnd = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
184 TBinExprLogOr = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
186 TBinExprCmpLess = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
187 TBinExprCmpGreat = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
188 TBinExprCmpLessEqu = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
189 TBinExprCmpGreatEqu = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
190 TBinExprCmpEqu = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
191 TBinExprCmpNotEqu = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
193 TBinAssign = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
196 private
198 public
207 // ////////////////////////////////////////////////////////////////////////// //
211 implementation
213 uses
214 utils;
217 // ////////////////////////////////////////////////////////////////////////// //
219 begin
224 begin
229 // ////////////////////////////////////////////////////////////////////////// //
231 begin
232 if (pr <> nil) then begin tokLine := pr.tokLine; tokCol := pr.tokCol; end else begin tokLine := 0; tokCol := 0; end;
236 constructor TExomaParseException.CreateFmt (pr: TTextParser; const afmt: AnsiString; const args: array of const);
237 begin
238 if (pr <> nil) then begin tokLine := pr.tokLine; tokCol := pr.tokCol; end else begin tokLine := 0; tokCol := 0; end;
243 // ////////////////////////////////////////////////////////////////////////// //
245 begin
282 // ////////////////////////////////////////////////////////////////////////// //
283 (*
284 procedure dumpPublishedProperties (obj: TObject);
285 var
286 pt: PTypeData;
287 pi: PTypeInfo;
288 i, j: Integer;
289 pp: PPropList;
290 begin
291 if (obj = nil) then exit;
292 //e_LogWritefln('Object of type ''%s'':', [obj.ClassName]);
293 pi := obj.ClassInfo;
294 pt := GetTypeData(pi);
295 //e_LogWritefln('property count: %s', [pt.PropCount]);
296 GetMem(pp, pt^.PropCount*sizeof(Pointer));
297 try
298 j := GetPropList(pi, [tkInteger, tkBool, tkSString, tkLString, tkAString, tkSet, tkEnumeration], pp);
299 //e_LogWritefln('ordinal property count: %s', [j]);
300 for i := 0 to j-1 do
301 begin
302 {
303 if (typinfo.PropType(obj, pp^[i].name) in [tkSString, tkLString, tkAString]) then
304 begin
305 e_LogWritefln(' #%s: <%s>; type: %s; value: <%s>', [i+1, pp^[i].name, typeKind2Str(typinfo.PropType(obj, pp^[i].name)), GetStrProp(obj, pp^[i])]);
306 end
307 else if (typinfo.PropType(obj, pp^[i].name) = tkSet) then
308 begin
309 e_LogWritefln(' #%s: <%s>; type: %s; value: %s', [i+1, pp^[i].name, typeKind2Str(typinfo.PropType(obj, pp^[i].name)), GetSetProp(obj, pp^[i], true)]);
310 end
311 else if (typinfo.PropType(obj, pp^[i].name) = tkEnumeration) then
312 begin
313 e_LogWritefln(' #%s: <%s>; type: %s; value: <%s>', [i+1, pp^[i].name, typeKind2Str(typinfo.PropType(obj, pp^[i].name)), GetEnumProp(obj, pp^[i])]);
314 end
315 else
316 begin
317 e_LogWritefln(' #%s: <%s>; type: %s; value: %s', [i+1, pp^[i].name, typeKind2Str(typinfo.PropType(obj, pp^[i].name)), GetOrdProp(obj, pp^[i])]);
318 end;
319 }
320 end;
321 finally
322 FreeMem(pp);
323 end;
324 end;
325 *)
328 // ////////////////////////////////////////////////////////////////////////// //
330 var
334 begin
340 pc := GetPropList(pi, [tkInteger, tkBool, tkSString, tkLString, tkAString, {tkSet,} tkEnumeration], pl);
345 begin
355 var
357 begin
360 begin
367 //tkFloat: result := 'Float';
368 //tkClass: result := 'Class';
369 //tkInt64: result := 'Int64';
370 //tkClassRef: result := 'ClassRef';
379 var
381 begin
384 begin
389 tkBool: if TExprBase.coerce2bool(v) then SetOrdProp(obj, pl^[idx], 1) else SetOrdProp(obj, pl^[idx], 0);
391 //tkFloat: result := 'Float';
392 //tkClass: result := 'Class';
393 //tkInt64: result := 'Int64';
394 //tkClassRef: result := 'ClassRef';
402 // ////////////////////////////////////////////////////////////////////////// //
403 class procedure TExprScope.error (const amsg: AnsiString); begin raise TExomaException.Create(amsg); end;
404 class procedure TExprScope.errorfmt (const afmt: AnsiString; const args: array of const); begin raise TExomaException.CreateFmt(afmt, args); end;
406 function TExprScope.getObj (const aname: AnsiString): TObject; begin result := nil; errorfmt('unknown object ''%s''', [aname]); end;
407 function TExprScope.getField (obj: TObject; const afldname: AnsiString): Variant; begin result := Unassigned; errorfmt('unknown field ''%s''', [afldname]); end;
408 procedure TExprScope.setField (obj: TObject; const afldname: AnsiString; var aval: Variant); begin errorfmt('unknown field ''%s''', [afldname]); end;
411 // ////////////////////////////////////////////////////////////////////////// //
412 class procedure TExprBase.error (const amsg: AnsiString); begin raise TExomaException.Create(amsg); end;
413 class procedure TExprBase.errorfmt (const afmt: AnsiString; const args: array of const); begin raise TExomaException.CreateFmt(afmt, args); end;
415 class procedure TExprBase.parseError (pr: TTextParser; const amsg: AnsiString); begin raise TExomaParseException.Create(pr, amsg); end;
416 class procedure TExprBase.parseError (pr: TTextParser; const afmt: AnsiString; const args: array of const); begin raise TExomaParseException.CreateFmt(pr, afmt, args); end;
419 begin
427 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := (LongInt(v0) <> 0);
435 begin
443 begin
451 begin
456 begin
461 begin
472 procedure TExprBase.assign (scope: TExprScope; var v: Variant); begin error('not an lvalue'); end;
475 // ////////////////////////////////////////////////////////////////////////// //
477 destructor TExprStatList.Destroy (); var f: Integer; begin for f := 0 to High(mList) do mList[f].Free(); mList := nil; end;
480 var
482 begin
487 var
489 begin
494 var
497 begin
501 try
503 except
510 // ////////////////////////////////////////////////////////////////////////// //
515 begin
520 function TExprCond.toString (): AnsiString; begin result := '('+mCond.toString()+'?'+mTrue.toString()+':'+mFalse.toString()+')'; end;
523 begin
531 // ////////////////////////////////////////////////////////////////////////// //
533 function TObjExpr.value (scope: TExprScope): Variant; begin result := UInt64(PtrUInt(Pointer(scope.getObj(mName)))); end;
538 // ////////////////////////////////////////////////////////////////////////// //
543 function TLitExpr.toString (): AnsiString; begin result := VarToStr(mValue); if isStr(mValue) then result := quoteStr(result); end;
544 function TLitExpr.clone (): TExprBase; begin result := TLitExpr.Create(0); (result as TLitExpr).mValue := mValue; end;
547 // ////////////////////////////////////////////////////////////////////////// //
550 function TUnExpr.clone (): TExprBase; begin result := (self.ClassType.Create() as TUnExpr); (result as TUnExpr).mOp0 := mOp0.clone(); end;
553 begin
568 begin
576 // ////////////////////////////////////////////////////////////////////////// //
578 begin
584 begin
586 if (varType(result) <> varQWord) then errorfmt('can''t take field ''%s'' value of non-object', [mField]);
591 var
593 begin
595 if (varType(o) <> varQWord) then errorfmt('can''t assign value to field ''%s'' of non-object', [mField]);
604 // ////////////////////////////////////////////////////////////////////////// //
607 function TBinExpr.clone (): TExprBase; begin result := (self.ClassType.Create() as TBinExpr); (result as TBinExpr).mOp0 := mOp0.clone(); (result as TBinExpr).mOp1 := mOp1.clone(); end;
610 begin
612 begin
614 begin
625 end
627 begin
634 end
636 begin
645 end
646 else
647 begin
654 // ////////////////////////////////////////////////////////////////////////// //
656 var
658 begin
665 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result)+LongInt(r1);
670 function TBinExprAdd.toString (): AnsiString; begin result := '('+mOp0.toString()+'+'+mOp1.toString+')'; end;
673 var
675 begin
681 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result)-LongInt(r1);
686 function TBinExprSub.toString (): AnsiString; begin result := '('+mOp0.toString()+'-'+mOp1.toString+')'; end;
689 var
691 begin
697 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result)*LongInt(r1);
702 function TBinExprMul.toString (): AnsiString; begin result := '('+mOp0.toString()+'*'+mOp1.toString+')'; end;
705 var
707 begin
713 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result) div LongInt(r1);
718 function TBinExprDiv.toString (): AnsiString; begin result := '('+mOp0.toString()+'/'+mOp1.toString+')'; end;
721 var
723 begin
728 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result) mod LongInt(r1);
733 function TBinExprMod.toString (): AnsiString; begin result := '('+mOp0.toString()+'%'+mOp1.toString+')'; end;
736 begin
742 function TBinExprLogAnd.toString (): AnsiString; begin result := '('+mOp0.toString()+'&&'+mOp1.toString+')'; end;
745 begin
751 function TBinExprLogOr.toString (): AnsiString; begin result := '('+mOp0.toString()+'||'+mOp1.toString+')'; end;
754 var
756 begin
762 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) < LongInt(r1));
768 function TBinExprCmpLess.toString (): AnsiString; begin result := '('+mOp0.toString()+'<'+mOp1.toString+')'; end;
771 var
773 begin
779 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) > LongInt(r1));
785 function TBinExprCmpGreat.toString (): AnsiString; begin result := '('+mOp0.toString()+'>'+mOp1.toString+')'; end;
788 var
790 begin
796 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) <= LongInt(r1));
802 function TBinExprCmpLessEqu.toString (): AnsiString; begin result := '('+mOp0.toString()+'<='+mOp1.toString+')'; end;
805 var
807 begin
813 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) >= LongInt(r1));
819 function TBinExprCmpGreatEqu.toString (): AnsiString; begin result := '('+mOp0.toString()+'>='+mOp1.toString+')'; end;
822 var
824 begin
830 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) = LongInt(r1));
838 function TBinExprCmpEqu.toString (): AnsiString; begin result := '('+mOp0.toString()+'=='+mOp1.toString+')'; end;
841 var
843 begin
849 varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) <> LongInt(r1));
857 function TBinExprCmpNotEqu.toString (): AnsiString; begin result := '('+mOp0.toString()+'<>'+mOp1.toString+')'; end;
860 // ////////////////////////////////////////////////////////////////////////// //
862 begin
867 function TBinAssign.toString (): AnsiString; begin result := mOp0.toString()+'='+mOp1.toString(); end;
870 // ////////////////////////////////////////////////////////////////////////// //
872 var
874 begin
876 try
878 if (pr.tokType <> pr.TTEOF) then begin result.Free(); parseError(pr, 'extra code in expression'); end;
879 finally
885 var
889 begin
894 try
896 begin
908 finally
920 begin
922 try
924 if pr.eatDelim('!') then begin result := doTerm(); result := TUnExprNot.Create(result); exit; end;
926 if pr.eatDelim('-') then begin result := doTerm(); result := TUnExprNeg.Create(result); exit; end;
930 begin
932 if (pr.tokStr = 'false') then begin result := TLitExpr.Create(false); pr.skipToken(); exit; end;
933 if (CompareText(pr.tokStr, 'true') = 0) or (CompareText(pr.tokStr, 'false') = 0) then parseError(pr, '`true` and `false` are case-sensitive');
936 begin
940 exit;
942 except
950 begin
952 try
954 begin
960 except
967 begin
969 try
971 begin
976 except
983 begin
985 try
987 begin
991 else if pr.eatTT(pr.TTGreatEqu) then result := TBinExprCmpGreatEqu.Create(result, doPlusMinus())
994 except
1001 begin
1003 try
1005 begin
1010 except
1017 begin
1019 try
1021 begin
1024 except
1031 begin
1033 try
1035 begin
1038 except
1044 // funcall, [], dot
1045 // !, ~
1046 // *, /, %
1047 // +, -
1048 // <<, >>
1049 // <, <=, >, >=
1050 // ==, !=
1051 // &
1052 // ^
1053 // |
1054 // &&
1055 // ||
1058 var
1060 begin
1068 var
1071 begin
1076 // ternary
1078 begin
1081 try
1086 except
1092 var
1094 begin
1097 try
1099 try
1102 try
1104 except
1107 finally
1110 except
1115 else
1121 {
1122 varEmpty:
1123 varNull:
1124 varSingle:
1125 varDouble:
1126 varDecimal:
1127 varCurrency:
1128 varDate:
1129 varOleStr:
1130 varStrArg:
1131 varString:
1132 varDispatch:
1133 varBoolean:
1134 varVariant:
1135 varUnknown:
1136 varShortInt:
1137 varSmallint:
1138 varInteger:
1139 varInt64:
1140 varByte:
1141 varWord:
1142 varLongWord:
1143 varQWord:
1144 varError:
1145 }