📄 dbgexpressions.pas
字号:
//////////////////////////////////////////////////////////////////////
// //
// dbgExpressions.pas: Expression management //
// Bog-standard expression parser. //
// //
// The contents of this file are subject to the Bottled Light //
// Public License Version 1.0 (the "License"); you may not use this //
// file except in compliance with the License. You may obtain a //
// copy of the License at http://www.bottledlight.com/BLPL/ //
// //
// Software distributed under the License is distributed on an //
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or //
// implied. See the License for the specific language governing //
// rights and limitations under the License. //
// //
// The Original Code is the Mappy VM User Interface, released //
// April 1st, 2003. The Initial Developer of the Original Code is //
// Bottled Light, Inc. Portions created by Bottled Light, Inc. are //
// Copyright (C) 2001-2003 Bottled Light, Inc. All Rights Reserved. //
// //
// Author(s): //
// Michael Noland (joat), michael@bottledlight.com //
// //
// Changelog: //
// 1.0: First public release (April 1st, 2003) //
// //
// Notes: //
// Can you feel the dust? This is positivly ancient code, it //
// came in large part from one of my first interpreters written //
// in TP7.0, pre MappyScript even. //
// //
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
unit dbgExpressions; /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
interface ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
uses
SysUtils, nexus, console, dwarfUtils;
//////////////////////////////////////////////////////////////////////
type
TExpression = string;
//////////////////////////////////////////////////////////////////////
function EvaluateExpression(expr: TExpression): integer;
//////////////////////////////////////////////////////////////////////
implementation ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
function RExpression: integer; forward;
procedure SkipWhite; forward;
//////////////////////////////////////////////////////////////////////
var
Look: char;
scriptBuffer: string;
ScriptLen, ScriptPos: integer;
//////////////////////////////////////////////////////////////////////
// Report what was expected and what was found
procedure Expected(this, that: string);
begin
raise Exception.Create(this + ' was expected, but ' + that + ' was found');
end;
//////////////////////////////////////////////////////////////////////
// Read a new character from the input stream
procedure GetChar;
begin
if (ScriptPos < ScriptLen) then begin
Inc(ScriptPos);
Look := scriptBuffer[ScriptPos];
end else
raise Exception.Create('Expression expected but end of file found');
end;
//////////////////////////////////////////////////////////////////////
// Match a specific input character versus what was found
procedure Match(what: char);
begin
if Look = what then GetChar else Expected(''''+what+'''', ''''+look+'''');
SkipWhite;
end;
//////////////////////////////////////////////////////////////////////
function IsAlpha(c: char): boolean;
begin
IsAlpha := UpCase(c) in ['A'..'Z', '_', '?'];
end;
//////////////////////////////////////////////////////////////////////
function IsDigit(c: char): boolean;
begin
IsDigit := c in ['0'..'9'];
end;
//////////////////////////////////////////////////////////////////////
function IsAddOp(c: char): boolean;
begin
IsAddOp := c in ['+', '-', '|', '^'];
end;
//////////////////////////////////////////////////////////////////////
function IsMulOp(c: char): boolean;
begin
IsMulOp := c in ['*', '/', '&', '%'];
end;
//////////////////////////////////////////////////////////////////////
function IsRelop(c: char): boolean;
begin
IsRelop := c in ['=', '<', '>'];
end;
//////////////////////////////////////////////////////////////////////
function IsWhite(c: char): boolean;
begin
IsWhite := c in [#0..#32];
end;
//////////////////////////////////////////////////////////////////////
procedure SkipWhite;
begin
while IsWhite(Look) do GetChar;
end;
//////////////////////////////////////////////////////////////////////
function GetName: string;
begin
// Reset the string and check for a alpha start
Result := '';
if not IsAlpha(Look) then Expected('A name', Look);
// Read in the string
while (IsAlpha(Look) or IsDigit(Look)) do begin
Result := Result + Look;
GetChar;
end;
// Skip white space in the input sequence
SkipWhite;
end;
//////////////////////////////////////////////////////////////////////
// Read in a number
function GetNum: integer;
var
st: string;
begin
{ Make sure there is a digit at the front }
if not (Look in ['$', '0'..'9']) then Expected('Number', Look);
st := '';
while Look in ['$', 'x', '0'..'9'] do begin
st := st + Look;
GetChar;
end;
if Copy(st, 1, 2) = '0x' then begin
Delete(st, 1, 2);
st := '$' + st;
end;
Result := StrToInt(st);
SkipWhite;
end;
//////////////////////////////////////////////////////////////////////
procedure SetScript(script: string);
begin
scriptBuffer := script;
scriptLen := Length(script);
scriptPos := 0;
GetChar;
end;
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
function GetIdentifier(token: string): integer;
begin
if (token <> '') and (token[1] in ['r', 'R']) then begin
Delete(token, 1, 1);
Result := vmGetRegister(StrToIntDef(token, 0));
end else
Result := ExamineVariable(token);
end;
//////////////////////////////////////////////////////////////////////
// Parse and interpret a factor
function Factor: integer;
begin
if Look = '[' then begin
Match('[');
Result := RExpression;
Match(']');
if Look = ':' then begin
Match(':');
if Look = '8' then begin
Match('8');
Result := vmReadByte(Result);
end else if Look = '1' then begin
Match('1');
Match('6');
Result := vmReadHalfword(Result);
end else if Look = '3' then begin
Match('3');
Match('2');
Result := vmReadWord(Result);
end;
end else
Result := vmReadWord(Result);
end else if Look = '(' then begin
Match('(');
Result := RExpression;
Match(')');
end else if IsAlpha(Look) then begin
;
{ if Look = '(' then
Result := ParseSubroutineCall
else}
Result := GetIdentifier(GetName);
end else
Result := GetNum;
end;
//////////////////////////////////////////////////////////////////////
// Parse and interpret a term
function Term: integer;
begin
Result := Factor;
while IsMulOp(Look) do begin
case Look of
'*': begin
Match('*');
Result := Result * Factor;
end;
'/': begin
Match('/');
Result := Result div Factor;
end;
'&': begin
Match('&');
if Look = '&' then begin
Match('&');
if Result <> 0 then Result := 1;
if Factor = 0 then Result := 0;
end else
Result := Result and Factor;
end;
'%': begin
Match('%');
Result := Result mod Factor;
end;
end;
end;
end;
//////////////////////////////////////////////////////////////////////
// Parse and interpret an expression
function RExpression: integer;
begin
if IsAddop(Look) then Result := 0 else Result := Term;
while IsAddop(Look) do begin
case Look of
'+': begin
Match('+');
Result := Result + Term;
end;
'-': begin
Match('-');
Result := Result - Term;
end;
'|': begin
Match('|');
if Look = '|' then Match('|');
Result := Result or Term;
end;
'^': begin
Match('^');
Result := Result xor Term;
end;
end;
end;
end;
//////////////////////////////////////////////////////////////////////
function Equal(left: integer): integer;
begin
Match('=');
// Compare the left and right hand sides
if left = RExpression then Equal := 1 else Equal := 0;
end;
//////////////////////////////////////////////////////////////////////
function LessOrEqual(left: integer): integer;
begin
Match('=');
// Compare the left and right hand sides }
if left <= RExpression then LessOrEqual := 1 else LessOrEqual := 0;
end;
//////////////////////////////////////////////////////////////////////
function NotEqual(left: integer): integer;
begin
Match('>');
// Compare the left and right hand sides
if left <> RExpression then NotEqual := 1 else NotEqual := 0;
end;
//////////////////////////////////////////////////////////////////////
function Less(left: integer): integer;
var
Right: integer;
begin
Match('<');
// Perform a <=, <>, or a < test
case Look of
'=': Result := LessOrEqual(left);
'>': Result := NotEqual(left);
else
Right := RExpression;
if left < right then Result := 1 else Result := 0;
end;
end;
//////////////////////////////////////////////////////////////////////
// Recognize and interpret a relational greater than
function Greater(left: integer): integer;
var
Right: integer;
begin
Match('>');
// Perform either a >= or a > test
if Look = '=' then begin
Match('=');
Right := RExpression;
if left >= right then Greater := 1 else Greater := 0;
end else begin
Right := RExpression;
if left > right then Greater := 1 else Greater := 0;
end;
end;
//////////////////////////////////////////////////////////////////////
{ Parse and interpret a relation }
function Relation: integer;
var
Value: integer;
begin
Value := RExpression;
if IsRelOp(Look) then begin
case Look of
'=': Value := Equal(Value);
'<': Value := Less(Value);
'>': Value := Greater(Value);
end;
end;
Relation := Value;
end;
//////////////////////////////////////////////////////////////////////
{ Parse and interpret a boolean factor with a leading not }
function Expression: integer;
begin
if Look = '!' then begin
Match('!');
Expression := not Relation;
end else
Expression := Relation;
end;
//////////////////////////////////////////////////////////////////////
function EvaluateExpression(expr: TExpression): integer;
begin
Result := 1;
if expr <> '' then begin
try
SetScript(expr + '.');
Result := Expression;
except
on e: Exception do logWriteLn(e.Message);
end;
end;
end;
//////////////////////////////////////////////////////////////////////
end.
//////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -