Мельница данных- Язык PascalScript (раздел целиком) (24.03.2023) | (одним файлом) |
Язык PascalScript |
На языке PascalScript на платформе "Мельница данных" описываются тела методов и выражения. Выражения используются в условиях отбора объектов определенного класса при их отображении в представлениях, а также как встраиваемые выражения, которые могут служить членами класса для чтения свойств. Здесь и далее зарезервированные слова выделены жирным шрифтом. |
1. Структура программного блока тела метода |
1 [Описание переменных] 2 begin 3 //Операторы end; Комментарии расположены между символами { и } либо от символов // до конца строки. |
2. Описание переменных | ||
1var 2 Имя переменной[, Имя переменной…]: Тип; 3 Имя переменной[, Имя переменной…]: Тип; 4 ...Имя переменной должно быть идентификатором (последовательность символов a-z, A-Z, 0-9, _). "Тип" может быть одним из следующих:
|
3. Операторы PascalScript |
Операторы разделяются точкой с запятой (;). Операторы могут быть одним из следующих: |
3.1. Составной оператор | ||
1begin 2 //Другие операторы endОператоры, размещенные внутри составного оператора, разделяются точкой с запятой. Никаких ограничений на состав операторов и количество уровней вложенности не накладывается.
|
3.2. Оператор присваивания | ||||||||
Выражение1 := Выражение2 Присваивает значение выражения Выражение2 выражению Выражение1. Типы Выражения1 и Выражения2 должны быть совместимы (совпадать по классу домена либо оба быть числовыми). Для этого на Выражение1 (стоящее слева от знака равенства, lvalue) накладывается ряд ограничений. Это выражение должно быть:
|
3.3. Оператор вызова | ||
ИмяПроцедуры [(Параметр1, Параметр2 ...)] "ИмяПроцедуры" должно быть:
|
3.4. Оператор ветвления | ||||
1if Выражение then 2 //Оператор1 3[else 4 //Оператор2] Выражение должно быть логического типа. В случае если значение Выражения истинно, выполняется Оператор1. Часть else является необязательной и относится к последнему оператору if, не имеющему таковой. В случае ее наличия Оператор2 выполняется, если значение Выражения ложно.
|
3.5. Оператор выбора | ||
1case Выражение of 2 Значение1: //Оператор1 3 Значение2: //Оператор2 4 ... 5[else 6 //Оператор ] end Заменяет каскад операторов if. Значение Выражения должно быть числового типа. Часть else выполняется в случае, если Выражение не равно ни одному из перечисленных вариантов. Эта часть не является обязательной.
|
3.6. Цикл с предусловием | ||
1while Выражение do 2 //Оператор Оператор выполняется до тех пор, пока значение Выражения истинно. Выражение должно быть логического типа. Если при входе в цикл Выражение не истинно, то тело цикла не будет выполнено ни одного раза.
|
3.7. Цикл с постусловием | ||
1repeat 2 //Операторы 3until Выражение Операторы выполняются до тех пор, пока значение Выражения ложно. Выражение должно быть логического типа. Обратите внимание, что внутри себя оператор может содержать несколько операторов, разделенных точкой с запятой. Тело цикла обязательно будет выполнено хотя бы один раз.
|
3.8. Цикл с параметром | ||
1for Параметр := Выражение1 (to|downto) Выражение2 do 2 //Оператор Параметр цикла обязан быть простой локальной переменной. Функционально цикл с параметром эквивалентен циклам:
|
3.9. Цикл по экземплярам | ||
1for each Параметр of ИмяКласса [with Выражение] 2 [by [-] Выражение [, [-] Выражение]] do 3 //Оператор Цикл осуществляется по выборке среди экземпляров класса ИмяКласса, для которых истинно Выражение. Если Выражение не задано, то по всем экземплярам. Ссылка на текущий в рамках цикла экземпляр присваивается в локальную переменную Параметр. Выражение должно определяться относительно переменной Параметр. Выраженния, следующие за ключевым словом by, определяют порядок обхода экземпляров. Знак "-" перед выражением (любого типа) определяет обратный порядок обхода.
|
3.10. Оператор прекращения цикла |
break Происходит немедленный выход из цикла. Выполняется финализация операторов защиты завершения, которыми защищено тело цикла. Допустим только в теле цикла с предусловием, цикла с постусловием, цикла с параметром или цикла по экземплярам. |
3.11. Оператор выхода из подпрограммы |
exit Происходит немедленный выход из программного блока. Выполняется финализация операторов защиты завершения. |
3.12. Оператор защиты завершения | ||
1try 2 //Операторы1 3finally 4 //Операторы2 end Выполняются операторы Операторы1, разделенные точкой с запятой. В случае возникновения исключительной ситуации управление сразу передается на Операторы2, и после их выполнения исключение остается активным. Если исключения не произошло, выполняются Операторы2. Если среди Операторов1 встречается оператор exit, то Операторы2 все равно выполняются.
|
3.13. Оператор обработки исключительных ситуаций | ||||
1try 2 //Операторы1 3except 4 //Операторы2 end Выполняются операторы Операторы1. В случае возникновения исключительной ситуации управление передается на Операторы2. Если исключительных ситуаций не возникло, Операторы2 не выполняются никогда. При передаче управления на Операторы2 исключительная ситуация деактивирована. Для ее повторного возбуждения можно воспользоваться оператором возбуждения исключения без указания текстовой строки сообщения.
|
3.14. Оператор возбуждения исключения |
raise [Выражение]Возбуждает исключение, которое, если не было обработано блоком except оператора обработки, дойдет до пользователя. Пользователь увидит сообщение, определяемое Выражением. Выражение должно иметь строковый тип и является обязательным для всех случаев, кроме части except оператора обработки исключений. |
3.15. Оператор унаследованного вызова | ||
inherited Работает только в унаследованном переопределенном методе. Вызывается метод предка с параметрами, заданными в параметрах к моменту вызова. Если программный блок представляет собой тело функции, то в псевдопеременной Result будет результат выполнения метода предка.
|
4. Выражения и операции |
4.1. Состав выражения |
Любое выражение имеет тип. Выражения состоят из следующих элементов:
|
4.2. Квалификатор | ||||||||||||||
Квалификатор обозначает объект, переменную, параметр, свойство, поле, вызов функции. Квалификатор состоит из идентификаторов, разделенных точкой.
При интерпретации квалификатора используется следующий порядок разбора идентификатора:
При интерпретации квалификатора внутри выражения агрегата правила разбора идентификатора изменяются:
|
4.3. Агрегат | ||||||||
Агрегат определяет агрегированное значение над экземплярами определенного класса, удовлетворяющими условиям агрегации. Агрегаты бывают следующих типов:
Внутри выражения агрегата правила разбора идентификатора изменяются на следующие:
|
4.4. Операции | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Операции связывают элементы выражений. Таблица операций в порядке приоритета:
|
4.4.1. Особенности применения операций |
|
5. Формальная грамматика |
001Goal: MethodBody | Expression; 002 003MethodBody: [ConstantDeclaration] [VariableDeclaration] CompoundStatement ";"; 004 005ConstantDeclaration: "const" Ident ":" DomainSpecification ";" 006 [{Ident ":" DomainSpecification ";"}]; 007 008VariableDeclaration: "var" DomainDefinition [{DomainDefinition}]; 009 010DomainDefinition: Ident ":" DomainSpecification ";"; 011 012DomainSpecification: IntegerDomainDefinition 013 | StringDomainDefinition 014 | FloatDomainDefinition 015 | DateDomainDefinition 016 | TimeDomainDefinition 017 | DateTimeDomainDefinition 018 | BooleanDomainDefinition 019 | BlobDomainDefinition 020 | EnumerationDomainDefinition 021 | Ident; 022 023IntegerDomainDefinition: "integer"; 024StringDomainDefinition: "string" "[" Number "]"; 025FloatDomainDefinition: "float" ["(" Number ["." Number] ")"]; 026DateDomainDefinition: "date"; 027TimeDomainDefinition: "time"; 028DateTimeDomainDefinition: "datetime"; 029BooleanDomainDefinition: "boolean"; 030BlobDomainDefinition: "blob" | "clob"; 031EnumerationDomainDefinition: "(" Ident {"," Ident} ")"; 032 033CompoundStatement: "begin" Statement [{";" Statement}] "end"; 034 035Statement: 036 | CompoundStatement 037 | AssignmentStatement 038 | InheritedStatement 039 | CallStatement 040 | IfStatement 041 | CaseStatement 042 | ForStatement 043 | WhileStatement 044 | RepeatStatement 045 | TryFinallyStatement 046 | TryExceptStatement 047 | RaiseStatement 048 | ForEachStatement 049 | ExitStatement; 050 051AssignmentStatement: Qualifier ":=" Expression; 052 053CallStatement: Qualifier; 054 055InheritedStatement: "inherited"; 056 057IfStatement: "if" Expression "then" Statement ["else" Statement]; 058 059CaseStatement: "case" Expression "of" {CaseBranch} ["else" Statement ";"] "end"; 060 061CaseBranch: CaseLabel [{',' CaseLabel}] ":" Statement ";"; 062 063CaseLabel: Number | Ident; 064 065ForStatement: "for" Ident ":=" Expression ("to"|"downto") 066 Expression "do" Statement; 067 068WhileStatement: "while" Expression "do" Statement; 069 070RepeatStatement: "repeat" Statement [{";" Statement}] "until" Expression; 071 072TryFinallyStatement: "try" Statement [{";" Statement}] "finally" 073 Statement [{";" Statement}] "end"; 074 075TryExceptStatement: "try" Statement [{";" Statement}] "except" 076 Statement [{";" Statement}] "end"; 077 078RaiseStatement: "raise" [Expression]; 079 080ForEachStatement: "for" "each" Ident "of" Ident ["with" Expression] 081 ["by" Expression] "do" Statement; 082 083ExitStatement: "exit"; 084 085Expression: ComparedExpression [{RelationOperation Expression}]; 086 087ComparedExpression: Addon [{AdditionOperaton ComparedExpression}]; 088 089Addon: Factor [{MultiplicativeOperation Addon}]; 090 091Factor: "(" Expression ")" 092 | "not" Expression 093 | Number ["." Number] 094 | StringConstant 095 | Qualifier 096 | "nil" 097 | "True" 098 | "False" 099 | "(" Expression "is" Ident ")" 100 | "any" Aggregate 101 | "count" Aggregate 102 | "sum" Aggregate 103 | "max" Aggregate 104 | "min" Aggregate; 105 106Aggregate: "(" Ident ["." Ident] ["with" Expression] ")"; 107 108Qualifier: QualifierPart [{"." QualifierPart}]; 109 110QualifierPart: Ident ["(" Expression [{", " Expression}] ")"] 111 | "self" 112 | "(" Qualifier "as" Ident ")"; 113 114RelationOperation: "<" 115 | ">" 116 | "<=" 117 | ">=" 118 | "=" 119 | "<>"; 120 121AdditionOperaton: "+" 122 | "-" 123 | "or"; 124 125MultiplicativeOperation: "*" 126 | "/" 127 | "div" 128 | "and"; |
6. Соглашения |
6.1. Соглашения о наименованиях | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
В качестве вводимых (объявляемых) идентификаторов необходимо использовать так называемую нотацию InfixCaps. Если при создании имени используется несколько слов, то необходимо использовать заглавную букву для каждого слова в имени. Для разделения слов нельзя использовать символ подчеркивания. Все сущности именуются на английском языке, при этом использование сокращений является оправданным только в случае, если длина образуемого имени не согласуется с внешними по отношению к соображениям бизнес-логики ограничениям.
|
6.2. Стилевое оформление исходного кода |
Код на языке PascalScript, являющийся частью поставляемого решения, должен быть оформлен в соответствии с изложенными правилами. |
6.2.1. Использование строк, пробелов и отступов |
Пустые строки могут повысить читабельность путем группирования секций кода, которые логически связаны между собой. Пробелы, запрещенные к использованию:
Двоеточие для всех объявлений переменных не должно содержать перед собой пробелов и иметь один пробел после перед именем типа. Всегда необходимо использовать два пробела для всех уровней отступа. Другими словами, первый уровень отступает на два пробела, второй на четыре и так далее. Никогда не используйте символы табуляции. Существует несколько исключений из этого правила. Зарезервированные слова var, begin и end, относящиеся к программному блоку вцелом, всегда должны примыкать к левой границе. Код внутри блока begin..end должен иметь отступ два символа. Все строки должны быть ограничены 80 столбцами. Строки, длиннее чем 80 столбцов должны быть разделены и перенесены. Все перенесенные строки должны быть выровнены по первой строке и иметь отступ в два символа. Зарезервированное слово begin всегда должно находиться на своей отдельной строке. Нельзя переносить строки в тех местах, где не допускаются пробелы, например между именем метода и открывающей скобкой. Никогда нельзя помещать зарезервированное слово begin на строку, содержащую другой код. |
6.2.2. Оформление объявлений и операторов | ||||||||||||||||||||||||||
Все переменные с их типами должны быть объявлены на различных строках. Простые операторы содержат одну точку с запятой. Если Вам необходимо разделить оператор, то перенесите продолжение оператора на следующую строку с отступом в два пробела.
Составные операторы всегда заканчиваются точкой с запятой.
Каждое присвоение и каждое выражение должно располагаться на разных строках. Оператор "if" Оператор if всегда должен располагаться по крайней мере на двух строках
Оператор "for"
Оператор "while"
Оператор "repeat..until"
Оператор "case" Несмотря на то, что существует множество синтаксически правильных конструкций, одобренной и рекомендованной считается следующая:
Оператор "try" Несмотря на то, что существует множество синтаксически правильных конструкций, одобренной и рекомендованной считается следующая:
|