base file
This commit is contained in:
463
北极星光OPENWRT/编程器软件/scripts/README_RU.TXT
Normal file
463
北极星光OPENWRT/编程器软件/scripts/README_RU.TXT
Normal file
@@ -0,0 +1,463 @@
|
||||
1. Описание
|
||||
-----------
|
||||
|
||||
Модуль pascalc.dcu представляет собой интерпретатор Pascal - подобного
|
||||
языка для Delphi. Основные отличия его от стандартного Паскаля следующие:
|
||||
|
||||
- Для значений переменных используеися тип Variant, что позволяет хранить
|
||||
разнообразные типы данных.
|
||||
|
||||
- Переменные обьявлять не надо, они при небходимости создаются динамически
|
||||
при присваивании им значений. Тип определяется по последнему присвоенному
|
||||
значению, типовый контроль при присваивании не выполняется. То есть если
|
||||
существующей числовой переменной присвоить строку, ее тип изменится.
|
||||
Символам строки можно присваивать числовые значения в диапазоне 0..255 или
|
||||
символы (строки длиной 1).
|
||||
|
||||
- В выражениях поддерживаются следующие операции:
|
||||
арифметические: +, -, *, /, ^ (возведение в степень), SHL, SHR
|
||||
операции с битами: BITOR,BITAND,BITXOR,BITNOT
|
||||
логические: >, <, >=, <=, =, <>, AND, OR, NOT, константы TRUE и FALSE.
|
||||
Tакже можно использовать скобки. Порядок выполненния операций стандартный.
|
||||
|
||||
- В интерпретаторе поддерживаются операторы:
|
||||
BEGIN ... END
|
||||
IF ... THEN ... ELSE
|
||||
CASE
|
||||
FOR ... TO/DOWNTO ... DO
|
||||
WHILE ... DO
|
||||
REPEAT ... UNTIL
|
||||
CONTINUE
|
||||
BREAK
|
||||
GOTO
|
||||
EXIT
|
||||
USES
|
||||
INCLUDE
|
||||
|
||||
- Все зарезервированные слова объявлены в interface как массив строк.
|
||||
При желании вы можете изменить их на любые другие, например сделать
|
||||
русскими. Допускаются одинаковые операторы присваивания и равенства.
|
||||
Интерпретатор может сам различать их в зависимости от контекста. Все
|
||||
остальные зарезервированные слова должны отличаться друг от друга.
|
||||
|
||||
- Поддерживаются многомерные массивы, которые хранятся как набор переменных.
|
||||
Имена таких переменных состоят из имени массива и индексов в квадратных
|
||||
скобках. Имя массива должно быть уникальным, не допускается одновременное
|
||||
существование обычной переменной и переменной массива с тем же именем.
|
||||
(например переменная с именем MyArr и элемент массива MyArr[1]).
|
||||
Так как элементы массивов хранятся как обычные переменные, на них
|
||||
распространяются все правила применимые к обычным переменнм. Массивы не надо
|
||||
обьявлять, элементы одного массива могут хранить как строки так и числа.
|
||||
Для диапазона индексов массивов нет никаких ограничений. Непрерывность
|
||||
элементов массива также не обязательна. Чтобы создать непрерывную
|
||||
последовательность элементов массива им надо просто присвоить (например в цикле)
|
||||
какие - либо значения. Кроме того, к символам строк можно обращаться как к
|
||||
массиву символов. Так например MyArr[1][2] значит обрашение ко 2-му символу
|
||||
1-й строки массива MyArr. Запись MyArr[1] может значить либо первый символ
|
||||
обычной строковой переменной MyArr, либо первый элемент массива. Но так как
|
||||
элемент массива и переменная с таким же именем одновременно существовать не могут,
|
||||
неоднозначность не возникает.
|
||||
|
||||
- Все встроенные функции интерпретатора user-defined. Mодуль pasfunc.pas содержит
|
||||
библиотеку в которую включены аналоги многих функций Delphi. Пример ее
|
||||
использования есть в demo-программе. Вы можете использовать эту библиотеку,
|
||||
дополнив при необходимости любым количеством своих функций снужными вам
|
||||
параметрами. Параметры функций заранее не описываются, поэтому их количество
|
||||
и типы ничем не ограничены (подобно процедуре write паскаля). Интерпретатор
|
||||
вычисляет все параметры конкретного вызова и передает их функции как список
|
||||
значений. При необходимости вы можете реализовать типовый контроль внутри
|
||||
своей реализации функции. Если в качестве параметра функции передается
|
||||
переменная интерпретатора, этот пареметр считается VAR-параметром, и его
|
||||
изменение в коде функции вызовет изменение значения соответствующей переменной
|
||||
интерпретатора. Тип возвращаемого функцией значения тоже может быть разным при
|
||||
разных параметрах вызова. В модуле pasfunc.pas есть пример реализации таких
|
||||
функций (ф-ции Max, Min). Функции можно вызывать как процедуры, не используя
|
||||
возвращаемое значение.
|
||||
|
||||
- Поддерживаются процедуры и функции на языке интерпретатора. В списке параметров
|
||||
процедур и функций необходимо только перечислить имена формальных параметров.
|
||||
Типы параметров и способ передачи указывать не надо, также в объявлении функций
|
||||
не надо указывать тип возвращаемого значения. Для возврата значения функции
|
||||
используется переменная "result". Если в качестве параметра функции или процедуры
|
||||
передается глобальная переменная интерпретатора, этот параметр для данного вызова
|
||||
считается VAR-параметром и его изменение внутри функции изменит значение
|
||||
глобальной переменной. В то же время все глобальные переменные интерпретатора
|
||||
внутри функции или процедуры ведут себя, как локальные переменные, которым
|
||||
присвоены начальные значения совпадающие со значениями одноименных глобальных
|
||||
переменных. Их значения доступны в процедурах и функциях, их можно изменить,
|
||||
но после выхода из процедуры или функции значение глобальной переменной не
|
||||
изменится. Все новые переменные, созданные внутри процедур и функций являются
|
||||
локальными, и после выхода из процедуры/функции исчезнут. Таким образом, в
|
||||
процедурах и функциях можно использовать любые имена для локальных переменных,
|
||||
не опасаясь что они совпадут с именами глобальных переменных.
|
||||
|
||||
Для реализации библиотек процедур можно использовать операторы USES и INCLUDE.
|
||||
Их синтаксис : USES 'имя файла';
|
||||
INCLUDE 'имя файла';
|
||||
|
||||
Операторы USES и INCLUDE обрабатываются препроцессором, до начала выполнения
|
||||
скрипта. Оператор INCLUDE вставляет в скрипт текст из файла. Оператор USES
|
||||
только загружает реализации процедур и функций, чтобы их можно было
|
||||
использовать при выполнении скрипта.
|
||||
|
||||
|
||||
2. Лицензия.
|
||||
------------
|
||||
|
||||
Интерпретатор PASCALC распространяется по принципу "как есть".
|
||||
При этом не предусматривается никаких гарантий, явных или подразумеваемых.
|
||||
Вы используете его на свой собственный риск. Автор не отвечает за потери
|
||||
данных, повреждения, потери прибыли или любые другие виды потерь, связанные
|
||||
с использованием (правильным или неправильным) этого программного продукта.
|
||||
|
||||
http://alexboiko.da.ru
|
||||
http://alexboiko.chat.ru
|
||||
|
||||
|
||||
3. Интерфейс модуля интерпретатора:
|
||||
-----------------------------------
|
||||
|
||||
unit pascalc;
|
||||
|
||||
{$F+,B-,R-}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Classes, Math;
|
||||
|
||||
type TToken =
|
||||
(tEMPTY, tVR, tCON, tTRUE, tFALSE,
|
||||
tEQU, tOR, tAND, tNOT, tXOR,
|
||||
tCOMMA, tLBL, tNEQ, tGT, tLS,
|
||||
tGTE, tLSE, tADD, tSUB, tMUL,
|
||||
tDIV, tPWR, tLBR, tRBR, tLARR,
|
||||
tRARR, tSEMI, tREM, tREMB, tREME,
|
||||
tASSIGN, tBEGIN, tEND, tIF, tTHEN,
|
||||
tELSE, tFOR, tTO, tDOWNTO, tDO,
|
||||
tWHILE, tREPEAT, tUNTIL, tBREAK, tCONTINUE,
|
||||
tEXIT, tGOTO, tSHL, tSHR, tPROC,
|
||||
tFUNCT, tUSES, tINCLUDE, tCASE, tOF,
|
||||
tCOMMA2);
|
||||
|
||||
type TTokenSet = set of TToken;
|
||||
|
||||
const
|
||||
ResWords : array[TToken] of string[10] =
|
||||
('', '', '', 'TRUE', 'FALSE',
|
||||
'=', 'OR', 'AND', 'NOT', 'XOR',
|
||||
',', ':', '<>', '>', '<',
|
||||
'>=', '<=', '+', '-', '*',
|
||||
'/', '^', '(', ')', '[',
|
||||
']', ';', '//', '{', '}',
|
||||
':=', 'BEGIN', 'END', 'IF', 'THEN',
|
||||
'ELSE', 'FOR', 'TO', 'DOWNTO', 'DO',
|
||||
'WHILE', 'REPEAT', 'UNTIL', 'BREAK', 'CONTINUE',
|
||||
'EXIT', 'GOTO', 'SHL', 'SHR', 'PROCEDURE',
|
||||
'FUNCTION', 'USES', 'INCLUDE', 'CASE', 'OF',
|
||||
'..');
|
||||
|
||||
const
|
||||
Alpha : set of char = ['_','0'..'9','a'..'z','A'..'Z','а'..'я','ё','А'..'Я','Ё'];
|
||||
StrDelimiter : char = '''';
|
||||
DecimalPoint : char = '.';
|
||||
TokenDelimiter : char = #127;
|
||||
|
||||
|
||||
type TVar = record
|
||||
Name : string;
|
||||
Value : variant;
|
||||
end;
|
||||
|
||||
type TPVar = ^TVar;
|
||||
|
||||
type TVarList = class (TList)
|
||||
destructor Destroy; override;
|
||||
procedure ClearAll;
|
||||
function AddVar(V:TVar) : boolean;
|
||||
function AddValue(N:string; V:variant) : boolean;
|
||||
function VarExist(N:string):boolean;
|
||||
function VarIndex(N:string):integer;
|
||||
function VarByName(N:string;var V:TVar) : boolean;
|
||||
function SetVar(V:TVar) : boolean;
|
||||
function SetValue(N:string; V:variant) : boolean;
|
||||
procedure CopyTo(VL:TVarList);
|
||||
end;
|
||||
|
||||
type TPVarList = ^TVarList;
|
||||
|
||||
type PProcessProc = procedure;
|
||||
|
||||
type PFunction = function(Sender:TObject; var A:TVarList; var R:TVar) : boolean;
|
||||
|
||||
type TFunc = record
|
||||
Name : string;
|
||||
Func : Pointer;
|
||||
end;
|
||||
|
||||
type TPFunc = ^TFunc;
|
||||
|
||||
type TFuncList = class (TList)
|
||||
destructor Destroy; override;
|
||||
procedure ClearAll;
|
||||
function AddFunction(N:string; F:Pointer) : boolean;
|
||||
end;
|
||||
|
||||
type TProcedure = record
|
||||
Name : string;
|
||||
Body : string;
|
||||
Params : string;
|
||||
Result : boolean;
|
||||
end;
|
||||
|
||||
type TPProcedure = ^TProcedure;
|
||||
|
||||
type TProcList = class(TList)
|
||||
destructor Destroy; override;
|
||||
procedure ClearAll;
|
||||
function AddProc(Proc:TProcedure):boolean;
|
||||
function ProcIndex(Name:string):integer;
|
||||
function ProcByName(Name:string; var Proc:TProcedure):boolean;
|
||||
end;
|
||||
|
||||
|
||||
type TPasCalc = class
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure ClearVars;
|
||||
function VarCount : integer;
|
||||
function VarIndex(N:string) : integer;
|
||||
function VarByName(N:string; var V:TVar) : boolean;
|
||||
function VarByIndex(I:integer; var V:TVar) : boolean;
|
||||
function SetVar(V:TVar) : boolean;
|
||||
function SetValue(N:string; V:variant):boolean;
|
||||
procedure ClearFuncs;
|
||||
function SetFunction(N:string; F:Pointer) : boolean;
|
||||
procedure SetProcessProc(P:Pointer);
|
||||
function Parse(S:string) : string;
|
||||
function Calculate(S:string; var R:TVar) : boolean;
|
||||
function Execute(S:string):boolean;
|
||||
private
|
||||
Expr : string;
|
||||
ExprIndex : integer;
|
||||
Token : string;
|
||||
TokenCode : TToken;
|
||||
|
||||
BlockLevel : integer;
|
||||
BlockCmd : TToken;
|
||||
GotoLabel : string;
|
||||
|
||||
VarList : TVarList;
|
||||
FuncList : TFuncList;
|
||||
ProcList : TProcList;
|
||||
|
||||
ProcessProc : PProcessProc;
|
||||
|
||||
LastString : string;
|
||||
LastParsed : string;
|
||||
|
||||
procedure Clear;
|
||||
procedure Process;
|
||||
procedure Error(Msg,Line:string; Code:integer);
|
||||
procedure Level1(var R:TVar);
|
||||
procedure Level2(var R:TVar);
|
||||
procedure Level3(var R:TVar);
|
||||
procedure Level4(var R:TVar);
|
||||
procedure Level5(var R:TVar);
|
||||
procedure Level6(var R:TVar);
|
||||
procedure Level7(var R:TVar);
|
||||
procedure Level8(var R:TVar);
|
||||
procedure Arith(o : TToken; var R,H:TVar);
|
||||
procedure Unary(o : TToken; var R:TVar);
|
||||
function GetIndex(S:string; var Index:integer; var T:TToken) : string;
|
||||
function GetFuncParams(S:string; var Index:integer) : string;
|
||||
function FindFunc(N:string) : integer;
|
||||
function FindArray(N:string) : boolean;
|
||||
procedure SetVarDirect(var R:TVar);
|
||||
function CallFunc(N:string; A:string; var V:TVar) : boolean;
|
||||
function CallProc(N:string; A:string; var V:TVar) : boolean;
|
||||
function GetTextToken(S: string; var Index : integer; var Code : TToken) : string;
|
||||
function TokenStr(T:TToken;S:string) : string;
|
||||
function GetToken(S:string; var Index : integer; var Code : TToken) : string;
|
||||
function GetTokenCode(S: string; var Index:integer; var Code:TToken) : integer;
|
||||
function GetTokenLine(S:string; var Index:integer; var Code:TToken;
|
||||
StopToken:TTokenSet) : string;
|
||||
function NextToken(S:string; Index:integer) : TToken;
|
||||
function GetOperator(Txt:string; var Index : integer; EndToken:TTokenSet) : string;
|
||||
function ParseOperator(Txt:string; var Cmd,Line,Lbl : string) : TToken;
|
||||
function DelRemarks(S:string) : string;
|
||||
function UnParse(S:string; Show:boolean) : string;
|
||||
function PreProcess(Txt:string):string;
|
||||
function Calc(S:string; var R:TVar) : boolean;
|
||||
procedure Exec(Txt:string);
|
||||
procedure DoSet(CmdLine,Cmd,Line:string);
|
||||
procedure DoIf(CmdLine,Line:string);
|
||||
procedure DoBegin(CmdLine,Line:string);
|
||||
procedure DoFor(CmdLine,Line:string);
|
||||
procedure DoBreak(CmdLine,Line:string);
|
||||
procedure DoContinue(CmdLine,Line:string);
|
||||
procedure DoExit(CmdLine,Line:string);
|
||||
procedure DoWhile(CmdLine,Line:string);
|
||||
procedure DoRepeat(CmdLine,Line:string);
|
||||
procedure DoGoto(CmdLine,Line:string);
|
||||
procedure DoCase(CmdLine,Line:string);
|
||||
public
|
||||
Stop : boolean;
|
||||
ErrCode : integer;
|
||||
ErrMsg : string;
|
||||
ErrLine : string;
|
||||
end;
|
||||
|
||||
|
||||
4. Функции (unit PASFUNC.PAS)
|
||||
------------------------------
|
||||
|
||||
// Функции для работы со строками
|
||||
|
||||
Val
|
||||
IntToStr
|
||||
StrToInt
|
||||
FloatToStr
|
||||
StrToFloat
|
||||
Copy
|
||||
Pos
|
||||
Length
|
||||
Insert
|
||||
Delete
|
||||
Trim
|
||||
TrimLeft
|
||||
TrimRight
|
||||
UpperCase
|
||||
LowerCase
|
||||
Format
|
||||
|
||||
// Функции для работы с датой и временем
|
||||
|
||||
Now
|
||||
Date
|
||||
Time
|
||||
DateToStr
|
||||
StrToDate
|
||||
TimeToStr
|
||||
StrToTime
|
||||
FormatDateTime
|
||||
DayOfWeek
|
||||
IncMonth
|
||||
DecodeDate
|
||||
DecodeTime
|
||||
EncodeDate
|
||||
EncodeTime
|
||||
|
||||
// Математические функции
|
||||
|
||||
Abs
|
||||
Int
|
||||
Frac
|
||||
Round
|
||||
Ceil
|
||||
Floor
|
||||
Trunc
|
||||
Sin
|
||||
Cos
|
||||
Tan
|
||||
ArcSin
|
||||
ArcCos
|
||||
ArcTan
|
||||
Exp
|
||||
Ln
|
||||
IntPower
|
||||
Sqr
|
||||
Sqrt
|
||||
Min
|
||||
Max
|
||||
Inc
|
||||
Dec
|
||||
|
||||
// Функции PASCALC для работы с переменными.
|
||||
// Позволяют обращаться к переменной по вычисляемому имени.
|
||||
|
||||
SetVar
|
||||
GetVar
|
||||
|
||||
|
||||
5. Использование интерпретатора
|
||||
-------------------------------
|
||||
|
||||
Пример использования есть в demo-программе. В скриптах интерпретатора вы
|
||||
можете использовать готовую библиотеку функций из модуля pasfunc.pas, или
|
||||
напиcать собственную реализацию нужных вам функций, которых нет в библиотеке.
|
||||
Функция должна записать результат в поле Value переменной R:TVar и вернуть true.
|
||||
В случае ошибки (например при вызове с недопустимыми параметрами) функция
|
||||
должна вернуть false.
|
||||
|
||||
Потом создайте экземпляр класса TPasCalc. С помошью метода SetProcessProc
|
||||
можно задать указатель на процедуру которая будет регулярно вызываться в
|
||||
циклах интерпретатора. С ее помощью можно например реализовать таймаут.
|
||||
Если вы задали такую процедуру, то в ней стоит предусмотреть вызов обработчика
|
||||
сообщений (Application.ProcessMessages например). Если ее не задали, то вместо
|
||||
нее будет использоваться метод Process, в котором предусмотрена обработка сообщений.
|
||||
|
||||
Затем вызовами TPasCalc.SetFunction надо зарегистрировать функции которые вы
|
||||
хотите использовать и задать им имена. В модуле pasfunc.pas регистрация делается
|
||||
вызовом процедуры SetFunctions. Также можно задать предопределенные переменные
|
||||
вызовами SetVarNum или SetVarStr.
|
||||
|
||||
Метод Calculate вычисляет значение математического выражения и возвращает
|
||||
результат в переменной R:TVar, а метод Execute выполняет текст скрипта и
|
||||
заполняет список переменных. С помощью методов VarCount, VarByIndex или
|
||||
VarByName вы можете получить их значения. При возникновении ошибок их код
|
||||
возврашается в ErrCode. В ErrMsg и ErrLine возвращается сообщение об ошибке
|
||||
и строка ее вызвавшая.
|
||||
|
||||
При следуюших вызовах Calculate и Execute список переменных не очищается и
|
||||
их значения можно использовать в выражениях. При желании вы можете сами
|
||||
очистить список переменных вызвав ClearVars. Очистить список функций можно с
|
||||
помощью ClearFuncs. Если возникла необходимость принудительно прервать
|
||||
интерпретацию, надо присвоить значение true перменной TPasCalc.Stop.
|
||||
|
||||
Чтобы ускорить выполнение скриптов их можно предварительно подготовить
|
||||
с помощью метода Parse, который возвращает разобранную строку.
|
||||
Ее можно сохранить и затем выполнять теми же методами Calculate и Execute.
|
||||
|
||||
|
||||
6. Коды ошибок (ErrCode)
|
||||
------------------------
|
||||
|
||||
0 - O.K.
|
||||
1 - ошибка в выражении
|
||||
2 - непарные скобки
|
||||
3 - переменная не найдена
|
||||
4 - недопустимое имя переменной или функции
|
||||
5 - неверный тип операнда
|
||||
6 - невернaя строковая константе
|
||||
7 - неверный вызов функции
|
||||
8 - функция не найдена
|
||||
9 - неизвестный оператор
|
||||
10 - нехватает END
|
||||
11 - лишний END
|
||||
12 - нехватает TO или DOWNTO
|
||||
13 - нет переменной цикла
|
||||
14 - нехватает DO
|
||||
15 - BREAK вне цикла
|
||||
16 - нехватает UNTIL
|
||||
17 - лишний UNTIL
|
||||
18 - метка не найдена
|
||||
19 - индекс за границей диапазона
|
||||
20 - значение за границей диапазона
|
||||
21 - нехватает ']'
|
||||
22 - нехватает '['
|
||||
23 - деление на 0
|
||||
24 - Дублируется имя переменной/массива
|
||||
25 - Ошибка открытия файла
|
||||
26 - Функция должна возвращать значение
|
||||
27 - нет OF в операторе CASE
|
||||
28 - несколько ELSE в операторе CASE
|
||||
29 - неверный диапазон значений в операторе CASE
|
||||
|
||||
|
||||
7. Автор:
|
||||
---------
|
||||
|
||||
Алексей Бойко
|
||||
alexboiko@mtu-net.ru
|
||||
http://alexboiko.da.ru
|
||||
Reference in New Issue
Block a user