Эти соглашения об обозначениях используются для представления синтаксиса:
[pattern] |
необязательный |
{pattern} |
ноль или более повторений |
(pattern) |
группировка |
|
выбор |
|
разность --- элементы, порождаемые с помощью , за исключением элементов, порождаемых с помощью |
fibonacci |
терминальный синтаксис в машинописном шрифте |
Повсюду используется -подобный синтаксис, чьи правила вывода имеют вид:
Nonterm |
$$\to$$ | alt1 | alt2 | ... | altn |
Перевод:
| $$\to$$ | альтернатива1 | альтернатива2 | ... | альтернативаn |
В синтаксисе, который следует далее, есть некоторые семейства нетерминалов, индексированные уровнями приоритета (записанными как верхний индекс). Аналогично, нетерминалы (оператор), varop (оператор-переменной) и conop (оператор-конструктора) могут иметь двойной индекс: букву l, r или n соответственно для левоассоциативности, правоассоциативности или отсутствия ассоциативности и уровень приоритета. Переменная уровня приоритета i изменяется в пределах от 0 до 9, переменная ассоциативности a изменяется в диапазоне {l, r, n}. Например,
aexp |
$$\to$$ | ( expi+1 qop(a,i) ) |
на самом деле обозначает 30 правил вывода с 10 подстановками для i и 3 для a.
И в лексическом, и в контекстно-свободном синтаксисе есть некоторые неоднозначности, которые разрешаются посредством создания грамматических фраз наибольшей из возможных длины, действуя слева направо (в восходящем let -выражения и лямбда-абстракции продолжаются вправо насколько возможно.
program |
$$\to$$ | { |
|
$$\to$$ | qvarid | qconid | qvarsym | qconsym |
| | | |
|
|
$$\to$$ | integer | float | char | string |
special |
$$\to$$ | ( | ) | , | ; | [ | ] | apos;| { | } |
|
$$\to$$ | whitestuff {whitestuff} |
whitestuff |
$$\to$$ | whitechar | comment | ncomment |
whitechar |
$$\to$$ | |
|
$$\to$$ | return |
return |
$$\to$$ | возврат каретки |
|
$$\to$$ | перевод строки |
vertab |
$$\to$$ | вертикальная табуляция |
formfeed |
$$\to$$ | перевод страницы |
space |
$$\to$$ | пробел |
tab |
$$\to$$ | горизонтальная табуляция |
uniWhite |
$$\to$$ | любой пробельный символ Unicode |
comment |
$$\to$$ | |
|
$$\to$$ | -- {-} |
opencom |
$$\to$$ | {- |
closecom |
$$\to$$ | -} |
ncomment |
$$\to$$ | opencom ANYseq {ncomment ANYseq}closecom |
ANYseq |
$$\to$$ | {ANY}<{ANY}( opencom | closecom ) {ANY}> |
ANY |
$$\to$$ | graphic | whitechar |
any |
$$\to$$ | graphic | space | tab |
graphic |
$$\to$$ | small | large | symbol | digit | special | : | " | ' |
small |
$$\to$$ | ascSmall | uniSmall | _ |
ascSmall |
$$\to$$ | a | b | ... | z |
uniSmall |
$$\to$$ | любая буква Unicode нижнего регистра |
large |
$$\to$$ | ascLarge | uniLarge |
ascLarge |
$$\to$$ | A | B | ... | Z |
uniLarge |
$$\to$$ | любая буква Unicode верхнего регистра или заглавная |
symbol |
$$\to$$ | ascSymbol | uniSymbol<special | _ | : | " | '> |
ascSymbol |
$$\to$$ | ! | # | $ | % | | * | + | . | / | < | = | > | ? | @ |
| | | \ | ^ | | | - | $$\sim$$ | |
uniSymbol |
$$\to$$ | любой символ или знак пунктуации Unicode |
digit |
$$\to$$ | ascDigit | uniDigit |
ascDigit |
$$\to$$ | 0 | 1 | ... | 9 |
uniDigit |
$$\to$$ | любая десятичная цифра Unicode |
octit |
$$\to$$ | 0 | 1 | ... | 7 |
hexit |
$$\to$$ | digit | A | ... | F | a | ... | f |
Перевод:
| программа | $$\to$$ | { |
| $$\to$$ | квалифицированный-идентификатор-переменной | |
| | | квалифицированный-идентификатор-конструктора | |
| | | квалифицированный-символ-переменной | |
| | | квалифицированный-символ-конструктора | |
| | | литерал | |
| | | специальная- |
|
| | | зарезервированный-оператор | |
| | | зарезервированный-идентификатор | |
| литерал | $$\to$$ | целый-литерал |
| | | литерал-с-плавающей-точкой | |
| | | символьный-литерал | |
| | | строковый-литерал | |
| специальная- |
$$\to$$ | ( | ) | , | ; | [ | ] | apos;| { | } |
| пробельная-строка | $$\to$$ | пробельный-элемент {пробельный-элемент} |
| пробельный-элемент | $$\to$$ | пробельный-символ |
| | | комментарий | |
| | | вложенный-комментарий | |
| пробельный-символ | $$\to$$ | новая-строка |
| | | вертикальная-табуляция | |
| | | пробел | |
| | | горизонтальная-табуляция | |
| | | пробельный-символ-Unicode | |
| новая-строка | $$\to$$ | возврат-каретки перевод-строки |
| | | возврат-каретки | |
| | | перевод-строки | |
| | | перевод-страницы | |
| комментарий | $$\to$$ | тире [ любой-символ<символ> {любой-символ}] новая-строка |
| тире | $$\to$$ | -- {-} |
| начало-комментария | $$\to$$ | {- |
| конец-комментария | $$\to$$ | -} |
| вложенный-комментарий | $$\to$$ | начало-комментария ЛЮБАЯ-последовательность {вложенный-комментарий ЛЮБАЯ-последовательность}конец-комментария |
| ЛЮБАЯ-последовательность | $$\to$$ | {ЛЮБОЙ-символ}<{ЛЮБОЙ-символ}( начало-комментария | конец-комментария ) {ЛЮБОЙ-символ}> |
| ЛЮБОЙ-символ | $$\to$$ | графический-символ | пробельный-символ |
| любой-символ | $$\to$$ | графический-символ |
| | | пробел | |
| | | горизонтальная-табуляция | |
| графический-символ | $$\to$$ | маленькая-буква |
| | | большая-буква | |
| | | символ | |
| | | цифра | |
| | | специальная- |
|
| | | : | " | ' | |
| маленькая-буква | $$\to$$ | маленькая-буква-ASCII |
| | | маленькая-буква-Unicode | |
| | | - | |
| маленькая-буква-ASCII | $$\to$$ | a | b | ... | z |
| большая-буква | $$\to$$ | большая-буква-ASCII | большая-буква-Unicode |
| большая-буква-ASCII | $$\to$$ | A | B | ... | Z |
| символ | $$\to$$ | символ-ASCII |
| | | символ-Unicode<специальная-лексема | _ | : | " | '> | |
| символ-ASCII | $$\to$$ | ! | # | $ | % | | * | + | . | / | < | = | > | ? | @ |
| | | \ | ^ | | | - | $$\sim$$ | |
| символ-Unicode | $$\to$$ | любой символ или знак пунктуации Unicode |
| цифра | $$\to$$ | цифра-ASCII | цифра-Unicode |
| цифра-ASCII | $$\to$$ | 0 | 1 | ... | 9 |
| цифра-Unicode | $$\to$$ | любая десятичная цифра Unicode |
| восьмиричная-цифра | $$\to$$ | 0 | 1 | ... | 7 |
| шестнадцатиричная-цифра | $$\to$$ | цифра | A | ... | F | a | ... | f |
varid |
$$\to$$ | (small {small | large | digit | ' })<reservedid> |
|
conid |
$$\to$$ | large {small | large | digit | ' } |
|
reservedid |
$$\to$$ | case | class | data | default | |
|
| | | if | import | in | |
||
| | | let | module | newtype | of | tden | type | where | _ |
||
varsym |
$$\to$$ | ( symbol {symbol | :})<reservedop | dashes> |
|
consym |
$$\to$$ | (: {symbol | :})<reservedop> |
|
reservedop |
$$\to$$ | .. | : | :: | = | \ | | | $$\gets$$ | $$\to$$ | @ | $$\sim$$ | $$\Rightarrow$$ | |
varid |
(переменные) | ||
conid |
(конструкторы) | ||
tyvar |
$$\to$$ | varid |
(переменные типов) |
tycon |
$$\to$$ | conid |
( |
tycls |
$$\to$$ | conid |
(классы типов) |
modid |
$$\to$$ | conid |
(модули) |
qvarid |
$$\to$$ | [ modid . ] varid |
|
qconid |
$$\to$$ | [ modid . ] conid |
|
qtycon |
$$\to$$ | [ modid . ] tycon |
|
qtycls |
$$\to$$ | [ modid . ] tycls |
|
qvarsym |
$$\to$$ | [ modid . ] varsym |
|
qconsym |
$$\to$$ | [ modid . ] consym |
|
decimal |
$$\to$$ | digit{digit} |
|
|
$$\to$$ | octit{octit} |
|
|
$$\to$$ | hexit{hexit} |
|
integer |
$$\to$$ | decimal |
|
| | | 0o |
||
| | | 0x |
||
float |
$$\to$$ | decimal . decimal [ |
|
| | | decimal |
||
|
$$\to$$ | (e | E) [+ | -] decimal |
|
char |
$$\to$$ | ' (graphic<' | \> | space | escape<\>) ' |
|
string |
$$\to$$ | " {graphic<" | \> | space | escape | |
|
escape |
$$\to$$ | \ ( charesc | ascii | decimal | o |
|
charesc |
$$\to$$ | a | b | f | n | r | t | v | \ | " | ' | |
|
ascii |
$$\to$$ | ^cntrl | NUL | |
|
| | | |
||
| | | DC1 | DC2 | DC3 | DC4 | |
||
| | | EM | SUB | ESC | FS | GS | RS | US | SP | DEL |
||
cntrl |
$$\to$$ | ascLarge | @ | [ | \ | ] | ^ | _ |
|
|
$$\to$$ | \ whitechar {whitechar}\ |
Перевод:
| идентификатор-переменной | $$\to$$ | (маленькая-буква {маленькая-буква | большая-буква | цифра | ' })<зарезервированный-идентификатор> | |
| идентификатор-конструктора | $$\to$$ | большая-буква {маленькая-буква | большая-буква | цифра | ' } | |
| зарезервированный-идентификатор | $$\to$$ | case | class | data | default | |
|
| | | if | import | in | |
||
| | | let | module | newtype | of | tden | type | where | _ |
||
| символ-переменной | $$\to$$ | ( символ {символ | :})<зарезервированный-оператор| тире> | |
| символ-конструктора | $$\to$$ | (: {символ | :})< зарезервированный-оператор> | |
| зарезервированный-оператор | $$\to$$ | .. | : | :: | = | \ | | | $$\gets$$ | $$\to$$ | @ | $$\sim$$ | $$\Rightarrow$$ | |
| $$\to$$ | |||
| идентификатор-переменной | (переменные) | ||
| идентификатор-конструктора | (конструкторы) | ||
| переменная-типа | $$\to$$ | идентификатор-переменной | (переменные типов) |
| конструктор-типа | $$\to$$ | идентификатор-конструктора | ( |
| класс-типа | $$\to$$ | идентификатор-конструктора | (классы типов) |
| идентификатор-модуля | $$\to$$ | идентификатор-конструктора | (модули) |
| квалифицированный-идентификатор-переменной | $$\to$$ | [ идентификатор-модуля . ] идентификатор-переменной | |
| квалифицированный-идентификатор-конструктора | $$\to$$ | [идентификатор-модуля . ] идентификатор-конструктора | |
| квалифицированный-конструктор-типа | $$\to$$ | [идентификатор-модуля . ] конструктор-типа | |
| квалифицированный-класс-типа | $$\to$$ | [идентификатор-модуля . ] класс-типа | |
| квалифицированный-символ-переменной | $$\to$$ | [идентификатор-модуля . ] символ-переменной | |
| квалифицированный-символ-конструктора | $$\to$$ | [идентификатор-модуля . ] символ-конструктора | |
| десятичный-литерал | $$\to$$ | цифра{цифра} | |
| восьмиричный-литерал | $$\to$$ | восьмиричная-цифра{восьмиричная-цифра} | |
| шестнадцатиричный-литерал | $$\to$$ | шестнадцатиричная-цифра{шестнадцатиричная-цифра} | |
| целый-литерал | $$\to$$ | десятичный-литерал | |
| | | 0o восьмиричный-литерал | 0O восьмиричный-литерал | ||
| | | 0x шестнадцатиричный-литерал | 0X шестнадцатиричный-литерал | ||
| литерал-с-плавающей-точкой | $$\to$$ | десятичный-литерал . десятичный-литерал [экспонента] | |
| | | десятичный-литерал экспонента | ||
| экспонента | $$\to$$ | (e | E) [+ | -] десятичный-литерал |
|
| символьный-литерал | $$\to$$ | ' (графический-символ<' | \> | пробел | эскейп-символ<\>) ' | |
| строковый-литерал | $$\to$$ | " {графический-символ<" | \> | пробел | эскейп-символ | разрыв}" | |
| эскейп-символ | $$\to$$ | \ ( символ-эскейп | символ-ascii | десятичный-литерал | o восьмиричный-литерал | x шестнадцатиричный-литерал ) | |
| символ-эскейп | $$\to$$ | a | b | f | n | r | t | v | \ | " | ' | |
|
| символ-ascii | $$\to$$ | ^управляющий-символ | NUL | |
|
| | | |
||
| | | DC1 | DC2 | DC3 | DC4 | |
||
| | | EM | SUB | ESC | FS | GS | RS | US | SP | DEL |
||
| управляющий-символ | $$\to$$ | большая-буква-ASCII | @ | [ | \ | ] | ^ | _ | |
| разрыв | $$\to$$ | \ пробельный-символ {пробельный-символ}\ |
В разделе 2.7 дается неформальное определение правила размещения. В этом разделе это правило определено более точно.
Смысл программы на
Влияние размещения задано в этом разделе посредством описания того, как добавить фигурные скобки и точки с запятой в текст программы. Спецификация принимает вид функции L, которая выполняет трансляцию. Входом для L являются:
let, where, do или of не следует {n} вставляется после ключевого слова, где n --- отступ следующей module, то она предваряется {n}, где n --- отступ <n>, где n --- отступ {n}. (NB: строковый литерал может простираться на несколько строк (см. раздел 2.6). Поэтому во фрагментеf = ("Здравствуйте \
\Билл", "Джейк")
<n> не вставляются ни перед \Билл, потому что она не является началом законченной
"Отступом"
С целью соблюдения правил размещения, символы Unicode в исходной программе рассматриваются как те же символы фиксированной ширины, что и символы ASCII. Тем не менее, чтобы избежать визуальной путаницы, программистам следует избегать написания программ, в которых смысл неявного размещения зависит от ширины непробельных символов.
Применение L токены [] передает не зависящую от размещения трансляцию L заключается в следующем: где мы используем ":" в качестве оператора конструирования потока и "[]" для пустого потока.
L (<n>:ts) (m:ms) |
= | ; : (L ts (m:ms)) |
если m = n |
| = | } : (L (<n>:ts) ms) |
если n < m |
|
L (<n>:ts) ms |
= | L ts ms |
|
L ({n}:ts) (m:ms) |
= | { : (L ts (n:m:ms)) |
если n > m (Замечание 1) |
L ({n}:ts) [] |
= | { : (L ts [n]) |
если n > 0 (Замечание 1) |
L ({n}:ts) ms |
= | { : } : (L (<n>:ts) ms) |
(Замечание 2) |
L (}:ts) (0:ms) |
= | } : (L ts ms) |
(Замечание 3) |
L (}:ts) ms |
= | ошибка-разбора | (Замечание 3) |
L ({:ts) ms |
= | { : (L ts (0:ms)) |
(Замечание 4) |
L (t:ts) (m:ms) |
= | } : (L (t:ts) ms) |
если m /= 0 и ошибка-разбора (t) |
| (Замечание 5) | |||
L (t:ts) ms |
= | t : (L ts ms) |
|
L [] [] |
= | [] | |
L [] (m:ms) |
= | } : L [] ms |
если m /=0 (Замечание 6) |
Замечание 1. Вложенный контекст должен иметь больший отступ, чем внешний контекст (n>m). Если нет --- L завершается с ошибкой, и компилятору следует указать на ошибку размещения. Пример:
f x = let
h y = let
p z = z
in p
in h
Здесь определение p имеет меньший отступ, чем отступ внешнего контекста, который устанавливается в этом случае путем определения h.
Замечание 2. Если первый {n} заменяется на <n>, чтобы сымитировать ситуацию как если бы пустые фигурные скобки были явными.
Замечание 3. Посредством сопоставления с 0 текущего контекста размещения, мы гарантируем, что явная закрывающая фигурная скобка может быть сопоставлена только явной открывающей фигурной скобке. Если явная закрывающая фигурная скобка будет сопоставлена неявной открывающей фигурной скобке --- возникнет ошибка разбора.
Замечание 4. Это утверждение означает, что все пары фигурных скобок трактуются как явные контексты размещения, включая именованные создание типов данных и их обновление (раздел 3.15). В этом заключается разница между этой формулировкой и
Замечание 5. Дополнительное условие ошибка-разбора (t) интерпретируется следующим образом: если токены, порожденные до сих пор L вместе со следующим токеном t представляет недопустимый префикс в грамматике L, за которым следует (t) равна истине.
Проверка m /= 0 контролирует, что неявно добавленная закрывающая фигурная скобка будет сопоставлена неявной открывающей фигурной скобке.
Замечание 6. В конце ввода добавляются все незаконченные закрывающие фигурные скобки. Будет ошибкой оказаться здесь в пределах контекста без размещения (т.е. m = 0).
Если ни одно из данных выше правил не подойдет, то алгоритм завершится неудачей. Он может завершиться неудачей, например, когда будет достигнут конец ввода, и контекст без размещения будет активен, так как закрывающая фигурная скобка пропущена. Некоторые сбойные ситуации не обнаруживаются алгоритмом, хотя они могут быть: например, let }.
Замечание 1 реализует свойство, при котором обработка размещения может быть остановлена преждевременно из-за ошибки разбора. Например,
let x = e; y = x in e'
правильно, потому что оно транслируется в
let { x = e; y = x } in e'
Закрывающая фигурная скобка вставляется вследствие описанного выше правила ошибки разбора. Правило ошибки разбора трудно реализовать в его полной применимости ко всему, потому что выполнение этого влечет применение ассоциативностей. Например, выражение
do a == b == c
имеет единственный однозначный (хотя, возможно, неправильный с точки зрения типов) разбор, а именно:
(do { a == b }) == c
потому что (==) является неассоциативным. Поэтому программистам советуют избегать написания кода, который требует, чтобы синтаксический анализатор вставлял закрывающую фигурную скобку в таких ситуациях.
Соглашение о "грамотных комментариях", впервые разработанное Ричардом Бердом (Richard Bird) и Филиппом Уодлером (Philip Wadler) для Orwell, и позаимствованное в свою очередь Дональдом Кнутом (Donald Knutd) для "грамотного программирования", является альтернативным стилем программирования исходного кода на
Текст программы восстанавливается путем выбора только тех строк, которые начинаются с ">", и замены первого ">" на пробел. В полученном тексте размещение и комментарии применяются в точности как описано в главе 9.
Чтобы охватить некоторые случаи, где можно по ошибке пропустить ">", возникнет ошибка, если строка программы появится рядом с непробельной строкой комментария; строка рассматривается как пробельная, если она состоит только из пробельных символов.
Условно на стиль комментария указывает расширение файла: ".hs" указывает на обычный файл на
Эта грамотная программа запрашивает у пользователя число
и выводит на экран факториал этого числа:
> main :: IO ()
> main = do putStr "Введите число: "
> l <- readLine
> putStr "n!= "
> print (fact (read l))
Это программа вычисления факториала.
> fact :: Integer -> Integer
> fact 0 = 1
> fact n = n * fact (n-1)
Альтернативный стиль грамотного программирования особенно подходит для использования вместе с системой обработки текста LaTeX. По этому соглашению только те части грамотной программы, которые полностью заключены между разделителями \begin{code}...\end{code}, рассматриваются как текст программы; все остальные строки --- комментарии. Более точно:
\begin{code}.\end{code} (конечно, игнорируя строковые литералы).Нет необходимости вставлять дополнительные пустые строки до или после этих разделителей, хотя со стилистической точки зрения это может быть желательно. Например,
\documentstyle{article}
\begin{document}
\section{Introduction}
Это тривиальная программа, которая выводит первые 20 факториалов.
\begin{code}
main :: IO ()
main = print [ (n, product [1..n]) | n <- [1..20]]
\end{code}
\end{document}
Этот стиль использует то же расширение файла. Нежелательно смешивать эти два стиля в одном файле.
module |
$$\to$$ | module modid [exports] where body |
|
| | | body |
||
body |
$$\to$$ | { impdecls ; topdecls } |
|
| | | { impdecls } |
||
| | | { topdecls } |
||
impdecls |
$$\to$$ | impdecl1 ; ... ; impdecln |
(n>=1) |
Перевод:
| модуль | $$\to$$ | module идентификатор-модуля [список-экспорта] where тело |
|
| | | тело | ||
| тело | $$\to$$ | { список-объявлений-импорта ; список-объявлений-верхнего-уровня } | |
| | | { список-объявлений-импорта } | ||
| | | { список-объявлений-верхнего-уровня } | ||
| список-объявлений-импорта | $$\to$$ | объявление-импорта1 ; ... ; объявление-импортаn | (n>=1) |
exports |
$$\to$$ | ( export1 , ... , exportn [ , ] ) |
(n>=0) |
export |
$$\to$$ | qvar |
|
| | | qtycon [(..) | ( cname1 , ... , cnamen )] |
(n>=0) |
|
| | | qtycls [(..) | ( qvar1 , ... , qvarn )] |
(n>=0) |
|
| | | module modid |
Перевод:
| список-экспорта | $$\to$$ | ( экспорт1 , ... , экспортn [ , ] ) | (n>=0) |
| экспорт | $$\to$$ | квалифицированная-переменная | |
| | | квалифицированный-конструктор-типа [(..) | ( c-имя1 , ... , c-имяn )] | (n>=0) |
|
| | | квалифицированный-класс-типа [(..) | ( квалифицированная-переменная1 , ... , квалифицированная-переменнаяn )] | (n>=0) |
|
| | | module идентификатор-модуля |
impdecl |
$$\to$$ | import [ |
|
| | | (пустое объявление) | ||
impspec |
$$\to$$ | ( import1 , ... , importn [ , ] ) |
(n>=0) |
| | | hiding ( import1 , ... , importn [ , ] ) |
(n>=0) |
|
import |
$$\to$$ | var |
|
| | | tycon [ (..) | ( cname1 , ... , cnamen )] |
(n>=0) |
|
| | | tycls [(..) | ( var1 , ... , varn )] |
(n>=0) |
|
cname |
$$\to$$ | var | con |
Перевод:
| объявление-импорта | $$\to$$ | import [ идентификатор-модуля [ as идентификатор-модуля] [спецификатор-импорта] |
|
| | | (пустое объявление) | ||
| спецификатор-импорта | $$\to$$ | ( импорт1 , ... , импортn [ , ] ) | (n>=0) |
| | | hiding ( импорт1 , ... , импортn [ , ] ) | (n>=0) |
|
| импорт | $$\to$$ | переменная | |
| | | конструктор-типа [ (..) | ( c-имя1 , ... , c-имяn )] | (n>=0) |
|
| | | класс-типа [(..) | ( переменная1 , ... , переменнаяn )] | (n>=0) |
|
| c-имя | $$\to$$ | переменная | конструктор |
topdecls |
$$\to$$ | topdecl1 ; ... ; topdecln |
(n>=0) |
topdecl |
$$\to$$ | type simpletype = type |
|
| | | data [context =>] simpletype = constrs [ |
||
| | | newtype [context =>] simpletype = newconstr [ |
||
| | | class [scontext =>] tycls tyvar [where cdecls] |
||
| | | instance [scontext =>] qtycls inst [where idecls] |
||
| | | default (type1 , ... , typen) |
(n>=0) |
|
| | | decl |
Перевод:
| список-объявлений-верхнего-уровня | $$\to$$ | объявление-верхнего-уровня1 ; ... ; объявление-верхнего-уровняn | (n>=1) |
| объявление-верхнего-уровня | $$\to$$ | type простой-тип = тип |
|
| | | data [контекст $$\Rightarrow$$ ] простой-тип = список-конструкций [ -инструкция] |
||
| | | newtype [контекст $$\Rightarrow$$ ] простой-тип = новая-конструкция [ -инструкция] |
||
| | | class [простой-контекст $$\Rightarrow$$ ] класс-типа переменная-типа [ where список-объявлений-классов] |
||
| | | instance [простой-контекст $$\Rightarrow$$ ] квалифицированный-класс-типа экземпляр [ where список-объявлений-экземпляров] |
||
| | | default (тип1 , ... , типn) |
(n>=0) |
|
| | | объявление |
decls |
$$\to$$ | { decl1 ; ... ; decln } |
(n>=0) |
decl |
$$\to$$ | gendecl |
|
| | | (funlhs | |
||
cdecls |
$$\to$$ | { cdecl1 ; ... ; cdecln } |
(n>=0) |
cdecl |
$$\to$$ | gendecl |
|
| | | (funlhs | var) rhs |
||
idecls |
$$\to$$ | { idecl1 ; ... ; idecln } |
(n>=0) |
idecl |
$$\to$$ | (funlhs | var) rhs |
|
| | | (empty) |
||
gendecl |
$$\to$$ | vars :: [context =>] type |
(сигнатура типа) |
| | | fixity [integer] |
( -объявление) |
|
| | | (пустое объявление) | ||
|
$$\to$$ | |
(n>=1) |
vars |
$$\to$$ | var1 , ..., varn |
(n>=1) |
fixity |
$$\to$$ | infixl | infixr | |
Перевод:
| список-объявлений | $$\to$$ | { объявление1 ; ... ; объявлениеn } | (n>=0) |
| объявление | $$\to$$ | общее-объявление | |
| | | (левая-часть-функции | образец0) правая-часть | ||
| список-объявлений-классов | $$\to$$ | { объявление-класса1 ; ... ; объявление-классаn } | (n>=0) |
| объявление-класса | $$\to$$ | общее-объявление | |
| | | (левая-часть-функции | переменная) правая-часть | ||
| список-объявлений-экземпляров | $$\to$$ | { объявление-экземпляра1 ; ... ; объявление-экземпляраn } | (n>=0) |
| объявление-экземпляра | $$\to$$ | (левая-часть-функции | переменная) правая-часть | |
| | | (пусто) | ||
| общее-объявление | $$\to$$ | список-переменных :: [контекст $$\Rightarrow$$ ] тип | (сигнатура типа) |
| | | ассоциативность [целый-литерал] список-операторов | ( -объявление) |
|
| | | (пустое объявление) | ||
| список-операторов | $$\to$$ | оператор1 , ... , операторn | (n>=1) |
| список-переменных | $$\to$$ | переменная1 , ... , переменнаяn | (n>=1) |
| ассоциативность | $$\to$$ | infixl | infixr | |
type |
$$\to$$ | btype [-> type] |
(тип функции) |
btype |
$$\to$$ | [btype] atype |
(наложение типов) |
atype |
$$\to$$ | gtycon |
|
| | | tyvar |
||
| | | ( type1 , ... , typek ) |
(тип кортежа, k>=2 ) |
|
| | | [ type ] |
(тип списка) | |
| | | ( type ) |
(конструктор в скобках) | |
gtycon |
$$\to$$ | gtycon |
|
| | | () | (тип объединения) | |
| | | [] | (конструктор списка) | |
| | | ( $$\to$$ ) | (конструктор функции) | |
| | | (,{,}) | (конструкторы кортежей) | |
context |
$$\to$$ | class |
|
| | | ( class1 , ... , classn ) |
(n>=0) |
|
class |
$$\to$$ | qtycls tyvar |
|
| | | qtycls ( tyvar atype1 ... atypen ) |
(n>=1) |
|
scontext |
$$\to$$ | simpleclass |
|
| | | ( simpleclass1 , ... , simpleclassn ) |
(n>=0) |
|
simpleclass |
$$\to$$ | qtycls tyvar |
Перевод:
| тип | $$\to$$ | b -тип [ $$\to$$ тип] |
(тип функции) |
b -тип |
$$\to$$ | [ b -тип] a -тип |
(наложение типов) |
a -тип |
$$\to$$ | общий-конструктор-типа | |
| | | переменная-типа | ||
| | | ( тип1 , ... , типk ) | (тип кортежа, k>=2 ) |
|
| | | [ тип ] | (тип списка) | |
| | | ( тип ) | (конструктор в скобках) | |
| общий-конструктор-типа | $$\to$$ | квалифицированный-конструктор-типа | |
| | | () | (тип объединения) | |
| | | [] | (конструктор списка) | |
| | | ( $$\to$$ ) | (конструктор функции) | |
| | | (,{,}) | (конструкторы кортежей) | |
| контекст | $$\to$$ | класс | |
| | | ( класс1 , ... , классn ) | (n>=0) |
|
| класс | $$\to$$ | квалифицированный-класс-типа переменная-типа | |
| | | квалифицированный-класс-типа ( переменная-типа a-тип1 ... a-типn ) | (n>=1) |
|
| простой-контекст | $$\to$$ | простой-класс | |
| | | ( простой-класс1 , ... , простой-классn ) | (n>=0) |
|
| простой-класс | $$\to$$ | квалифицированный-класс-типа переменная-типа |
simpletype |
$$\to$$ | tycon tyvar1 ... tyvark |
(k>=0) |
constrs |
$$\to$$ | constr1 | ... | constrn |
(n>=1) |
constr |
$$\to$$ | con [!] atype1 ... [!] atypek |
(число аргументов конструктора con = k, k>=0 ) |
| | | (btype | ! atype) conop (btype | ! atype) |
(инфиксный оператор conop) | |
| | | con { fielddecl1 , ... , fielddecln } |
(n>=0) |
|
newconstr |
$$\to$$ | con atype |
|
| | | con { var :: type } |
||
fielddecl |
$$\to$$ | vars :: (type | ! atype) |
|
|
$$\to$$ | |
(n>=0) |
dclass |
$$\to$$ | qtycls |
Перевод:
| простой-тип | $$\to$$ | конструктор-типа переменная-типа1 ... переменная-типаk | (k>=0) |
| список-конструкций | $$\to$$ | конструкция1 | ... | конструкцияn | (n>=1) |
| конструкция | $$\to$$ | конструктор [!] a-тип1 ... [!] a-типk | (число аргументов конструктора con = k, k>=0 ) |
| | | (b-тип | ! a -тип) оператор-конструктора ( b -тип | ! a -тип) |
(инфиксный оператор conop ) |
|
| | | конструктор { объявление-поля1 , ... , объявление-поляn } | (n>=0) |
|
| новая-конструкция | $$\to$$ | конструктор a -тип |
|
| | | конструктор { переменная :: тип } | ||
| объявление-поля | $$\to$$ | список-переменных :: (тип | ! a -тип) |
|
-инструкция |
$$\to$$ | (производный-класс | (производный-класс1, ... , производный-классn)) |
(n>=0) |
| производный-класс | $$\to$$ | квалифицированный-класс-типа |
inst |
$$\to$$ | gtycon |
|
| | | ( gtycon tyvar1 ... tyvark ) |
( k>=0, все tyvar различны) |
|
| | | ( tyvar1 , ... , tyvark ) |
( k>=2, все tyvar различны) |
|
| | | [ tyvar ] |
||
| | | ( tyvar1 -> tyvar2 ) |
( tyvar1 и tyvar2 различны) |
Перевод:
| экземпляр | $$\to$$ | общий-конструктор-типа | |
| | | ( общий-конструктор-типа переменная-типа1 ... переменная-типаk ) | ( k>=0, все переменные-типа различны) |
|
| | | ( переменная-типа1 , ... , переменная-типаk ) | ( k>=2, все переменные-типа различны) |
|
| | | [ переменная-типа ] | ||
| | | ( переменная-типа1 $$\to$$ переменная-типа2 ) | (переменная-типа1 и переменная-типа2 различны) |
funlhs |
$$\to$$ | var apat {apat } |
| | | |
|
| | | lpati varop(l,i) |
|
| | | |
|
| | | ( funlhs ) apat {apat } |
|
rhs |
$$\to$$ | = exp [where decls] |
| | | gdrhs [where decls] |
|
gdrhs |
$$\to$$ | gd = exp [gdrhs] |
gd |
$$\to$$ | | exp0 |
Перевод:
| левая-часть-функции | $$\to$$ | переменная такой-как-образец {такой-как-образец } |
| | | образецi+1 оператор-переменной(a,i) образецi+1 | |
| | | левый-образецi оператор-переменной(l,i) образецi+1 | |
| | | образецi+1 оператор-переменной(r,i) правый-образецi | |
| | | ( левая-часть-функции ) такой-как-образец {такой-как-образец } | |
| правая-часть | $$\to$$ | = выражение [where список-объявлений] |
| | | правая-часть-со-стражами [where список-объявлений] | |
| правая-часть-со-стражами | $$\to$$ | страж = выражение [правая-часть-со-стражами] |
| страж | $$\to$$ | | выражение0 |
exp |
$$\to$$ | exp0 :: [context =>] type |
(сигнатура типа выражения) |
| | | exp0 |
||
expi |
$$\to$$ | expi+1 [qop(n,i) expi+1] |
|
| | | lexpi |
||
| | | rexpi |
||
lexpi |
$$\to$$ | (lexpi | expi+1) qop(l,i) expi+1 |
|
lexp6 |
$$\to$$ | - exp7 |
|
rexpi |
$$\to$$ | expi+1 qop (r,i) (rexpi | expi+1) |
|
exp10 |
$$\to$$ | \ apat1 ... apatn -> exp |
(лямбда-абстракция, n>=1 ) |
| | | let decls in exp |
( let -выражение) |
|
| | | if exp tden exp else exp |
(условное выражение) | |
| | | case exp of { alts } |
( case -выражение) |
|
| | | do { stmts } |
( do -выражение) |
|
| | | fexp |
||
fexp |
$$\to$$ | [fexp] aexp |
(применение функции) |
Перевод:
| выражение | $$\to$$ | выражение0 :: [контекст $$\Rightarrow$$ ] тип | (сигнатура типа выражения) |
| | | выражение0 | ||
| выражениеi | $$\to$$ | выражениеi+1 [квалифицированный-оператор(n,i) выражениеi+1] | |
| | | левое-сечение-выраженияi | ||
| | | правое-сечение-выраженияi | ||
| левое-сечение-выраженияi | $$\to$$ | (левое-сечение-выраженияi | выражениеi+1) квалифицированный-оператор(l,i) выражениеi+1 | |
| левое-сечение-выражения6 | $$\to$$ | - выражение7 | |
| правое-сечение-выраженияi | $$\to$$ | выражениеi+1 квалифицированный-оператор(r,i) (правое-сечение-выраженияi | выражениеi+1) | |
| выражение10 | $$\to$$ | \ такой-как-образец1 ... такой-как-образецn $$\to$$ выражение | (лямбда-абстракция, n>=1 ) |
| | | let списки-объявлений in выражение |
( let -выражение) |
|
| | | if выражение tden выражение else выражение |
(условное выражение) | |
| | | case выражение of { список-альтернатив } |
( case -выражение) |
|
| | | do { список-инструкций } |
( do -выражение) |
|
| | | функциональное-выражение | ||
| функциональное-выражение | $$\to$$ | [функциональное-выражение] выражение-аргумента | (применение функции) |
aexp |
$$\to$$ | qvar |
(переменная) |
| | | gcon |
(общий конструктор) | |
| | | |
||
| | | ( exp ) |
(выражение в скобках) | |
| | | ( exp1 , ... , expk ) |
(кортеж, k>=2 ) |
|
| | | [ exp1 , ... , expk ] |
(список, k>=1 ) |
|
| | | [ exp1 [, exp2] .. [exp3] ] |
(арифметическая последовательность) | |
| | | [ exp | qual1 , ... , qualn ] |
(описание списка, n>=1 ) |
|
| | | ( expi+1 qop(a,i) ) |
(левое сечение) | |
| | | ( lexpi qop(l,i) ) |
(левое сечение) | |
| | | ( qop(a,i)<-> expi+1 ) |
(правое сечение) | |
| | | ( qop(r,i)<-> rexpi ) |
(правое сечение) | |
| | | qcon { fbind1 , ... , fbindn } |
(именованная конструкция, n>=0 ) |
|
| | | aexp<qcon> { fbind1 , ... , fbindn } |
(именованное обновление, n >= 1 ) |
Перевод:
| выражение-аргумента | $$\to$$ | квалифицированная-переменная | (переменная) |
| | | общий-конструктор | (общий конструктор) | |
| | | литерал | ||
| | | ( выражение ) | (выражение в скобках) | |
| | | ( выражение1 , ... , выражениеk ) | (кортеж, k>=2 ) |
|
| | | [ выражение1 , ... , выражениеk ] | (список, k>=1 ) |
|
| | | [ выражение1 [, выражение2] .. [выражение3] ] | (арифметическая последовательность) | |
| | | [ выражение | квалификатор1 , ... , квалификаторn ] | (описание списка, n>=1 ) |
|
| | | ( выражениеi+1 квалифицированный-оператор(a,i) ) | (левое сечение) | |
| | | ( левое-сечение-выраженияi квалифицированный-оператор(l,i) ) | (левое сечение) | |
| | | ( квалифицированный-оператор(a,i)< $$\to$$ выражениеi+1 ) | (правое сечение) | |
| | | ( квалифицированный-оператор(r,i)< $$\to$$ правое-сечение-выраженияi ) | (правое сечение) | |
| | | квалифицированный-конструктор { связывание-имени-поля1 , ... , связывание-имени-поляn } | (именованная конструкция, n>=0 ) |
|
| | | выражение-аргумента<квалифицированный-конструктор> { связывание-имени-поля1 , ... , связывание-имени-поляn } | (именованное обновление, n>=1 ) |
qual |
$$\to$$ | |
(генератор) |
| | | let decls |
(локальное объявление) | |
| | | exp |
(страж) | |
alts |
$$\to$$ | alt1 ; ... ; altn |
(n>=1) |
alt |
$$\to$$ | |
|
| | | |
||
| | | (пустая альтернатива) | ||
gdpat |
$$\to$$ | gd -> exp [ gdpat ] |
|
stmts |
$$\to$$ | stmt1 ... stmtn exp [;] |
(n>=0) |
stmt |
$$\to$$ | exp ; |
|
| | | |
||
| | | let decls ; |
||
| | | ; | (пустая инструкция) | |
fbind
|
$$\to$$ | qvar = exp |
Перевод:
| квалификатор | $$\to$$ | образец $$\gets$$ выражение | (генератор) |
| | | let списки-объявлений |
(локальное объявление) | |
| | | выражение | (страж) | |
| список-альтернатив | $$\to$$ | альтернатива1 ; ... ; альтернативаn | (n>=1) |
| альтернатива | $$\to$$ | образец $$\to$$ выражение [where список-объявлений] | |
| | | образец образец-со-стражами [ where список-объявлений] |
||
| | | (пустая альтернатива) | ||
| образец-со-стражами | $$\to$$ | страж $$\to$$ выражение [ образец-со-стражами ] | |
| список-инструкций | $$\to$$ | инструкция1 ... инструкцияn выражение [;] | (n>=0) |
| инструкция | $$\to$$ | выражение ; | |
| | | образец $$\gets$$ выражение ; | ||
| | | let список-объявлений ; |
||
| | | ; | (пустая инструкция) | |
| связывание-имени-поля | $$\to$$ | квалифицированная-переменная = выражение |
|
$$\to$$ | var + integer |
(образец упорядочивания) |
| | | |
||
|
$$\to$$ | |
|
| | | lpati |
||
| | | rpati |
||
lpati |
$$\to$$ | (lpati | |
|
lpat6 |
$$\to$$ | - (integer | float) |
(отрицательный литерал) |
rpati |
$$\to$$ | |
|
|
$$\to$$ | apat |
|
| | | gcon apat1 ... apatk |
(число аргументов конструктора gcon = k, k>=1 ) |
Перевод:
| образец | $$\to$$ | переменная + целый-литерал | (образец упорядочивания) |
| | | образец0 | ||
| образецi | $$\to$$ | образецi+1 [квалифицированный-оператор-конструктора(n,i) образецi+1] | |
| | | левый-образецi | ||
| | | правый-образецi | ||
| левый-образецi | $$\to$$ | (левый-образецi | образецi+1) квалифицированный-оператор-конструктора(l,i) образецi+1 | |
| левый-образец6 | $$\to$$ | - (целый-литерал | литерал-с-плавающей-точкой) | (отрицательный литерал) |
| правый-образецi | $$\to$$ | образецi+1 квалифицированный-оператор-конструктора(r,i) (правый-образецi | образецi+1) | |
| образец10 | $$\to$$ | такой-как-образец | |
| | | общий-конструктор такой-как-образец1 ... такой-как-образецk | (число аргументов конструктора gcon = k, k>=1 ) |
apat |
$$\to$$ | var [@ apat] |
("такой как"-образец) |
| | | gcon |
(число аргументов конструктора gcon = 0 ) |
|
| | | qcon { fpat1 , ... , fpatk } |
(именованный образец, k>=0 ) |
|
| | | |
||
| | | _ | (любые символы) | |
| | | ( |
(образец в скобках) | |
| | | ( |
(образец кортежа, k>=2 ) |
|
| | | [ |
(образец списка, k>=1 ) |
|
| | | ~ apat |
(неопровержимый образец) | |
fpat |
$$\to$$ | qvar = |
Перевод:
| такой-как-образец | $$\to$$ | переменная [@ такой-как-образец] | ("такой как"-образец) |
| | | общий-конструктор | (число аргументов конструктора gcon = 0 ) |
|
| | | квалифицированный-конструктор { образец-с-именем1 , ... , образец-с-именемk } | (именованный образец, k>=0 ) |
|
| | | литерал | ||
| | | _ | (любые символы) | |
| | | ( образец ) | (образец в скобках) | |
| | | ( образец1 , ... , образецk ) | (образец кортежа, k>=2 ) |
|
| | | [ образец1 , ... , образецk ] | (образец списка, k>=1 ) |
|
| | | $$\sim$$ такой-как-образец | (неопровержимый образец) | |
| образец-с-именем | $$\to$$ | квалифицированная-переменная = образец |
gcon |
$$\to$$ | () | |
| | | [] | ||
| | | (,{,}) | ||
| | | qcon |
||
var |
$$\to$$ | varid | ( varsym ) |
(переменная) |
qvar |
$$\to$$ | qvarid | ( qvarsym ) |
(квалифицированная переменная) |
con |
$$\to$$ | conid | ( consym ) |
(конструктор) |
qcon |
$$\to$$ | qconid | ( gconsym ) |
(квалифицированный конструктор) |
varop |
$$\to$$ | varsym | apos;varid apos; |
(оператор переменной) |
qvarop |
$$\to$$ | qvarsym | apos;qvarid apos; |
(квалифицированный оператор переменной) |
conop |
$$\to$$ | consym | apos;conid apos; |
(оператор конструктора) |
qconop |
$$\to$$ | gconsym | apos;qconid apos; |
(квалифицированный оператор конструктора) |
|
$$\to$$ | varop | conop |
(оператор) |
qop |
$$\to$$ | qvarop | qconop |
(квалифицированный оператор) |
gconsym |
$$\to$$ | : | qconsym |
Перевод:
| общий-конструктор | $$\to$$ | () | |
| | | [] | ||
| | | (,{,}) | ||
| | | квалифицированный-конструктор | ||
| переменная | $$\to$$ | идентификатор-переменной | ( символ-переменной ) | (переменная) |
| квалифицированная-переменная | $$\to$$ | квалифицированный-идентификатор-переменной | ( квалифицированный-символ-переменной ) | (квалифицированная переменная) |
| конструктор | $$\to$$ | идентификатор-конструктора | (символ-конструктора ) | (конструктор) |
| квалифицированный-конструктор | $$\to$$ | квалифицированный-идентификатор-конструктора | ( символ-общего-конструктора ) | (квалифицированный конструктор) |
| оператор-переменной | $$\to$$ | символ-переменной | apos;идентификатор-переменной apos; | (оператор переменной) |
| квалифицированный-оператор-переменной | $$\to$$ | квалифицированный-символ-переменной | apos;квалифицированный-идентификатор-переменной apos; | (квалифицированный оператор переменной) |
| оператор-конструктора | $$\to$$ | символ-конструктора | apos;идентификатор-конструктора apos; | (оператор конструктора) |
| квалифицированный-оператор-конструктора | $$\to$$ | символ-общего-конструктора | apos;квалифицированный-идентификатор-конструктора apos; | (квалифицированный оператор конструктора) |
| оператор | $$\to$$ | оператор-переменной | оператор-конструктора | (оператор) |
| квалифицированный-оператор | $$\to$$ | квалифицированный-оператор-переменной | квалифицированный-оператор-конструктора | (квалифицированный оператор) |
| символ-общего-конструктора | $$\to$$ | : | квалифицированный-символ-конструктора |
Эти соглашения об обозначениях используются для представления синтаксиса:
[pattern] |
необязательный |
{pattern} |
ноль или более повторений |
(pattern) |
группировка |
|
выбор |
|
разность --- элементы, порождаемые с помощью , за исключением элементов, порождаемых с помощью |
fibonacci |
терминальный синтаксис в машинописном шрифте |
Повсюду используется -подобный синтаксис, чьи правила вывода имеют вид:
Nonterm |
$$\to$$ | alt1 | alt2 | ... | altn |
Перевод:
| $$\to$$ | альтернатива1 | альтернатива2 | ... | альтернативаn |
В синтаксисе, который следует далее, есть некоторые семейства нетерминалов, индексированные уровнями приоритета (записанными как верхний индекс). Аналогично, нетерминалы (оператор), varop (оператор-переменной) и conop (оператор-конструктора) могут иметь двойной индекс: букву l, r или n соответственно для левоассоциативности, правоассоциативности или отсутствия ассоциативности и уровень приоритета. Переменная уровня приоритета i изменяется в пределах от 0 до 9, переменная ассоциативности a изменяется в диапазоне {l, r, n}. Например,
aexp |
$$\to$$ | ( expi+1 qop(a,i) ) |
на самом деле обозначает 30 правил вывода с 10 подстановками для i и 3 для a.
И в лексическом, и в контекстно-свободном синтаксисе есть некоторые неоднозначности, которые разрешаются посредством создания грамматических фраз наибольшей из возможных длины, действуя слева направо (в восходящем let -выражения и лямбда-абстракции продолжаются вправо насколько возможно.
program |
$$\to$$ | { |
|
$$\to$$ | qvarid | qconid | qvarsym | qconsym |
| | | |
|
|
$$\to$$ | integer | float | char | string |
special |
$$\to$$ | ( | ) | , | ; | [ | ] | apos;| { | } |
|
$$\to$$ | whitestuff {whitestuff} |
whitestuff |
$$\to$$ | whitechar | comment | ncomment |
whitechar |
$$\to$$ | |
|
$$\to$$ | return |
return |
$$\to$$ | возврат каретки |
|
$$\to$$ | перевод строки |
vertab |
$$\to$$ | вертикальная табуляция |
formfeed |
$$\to$$ | перевод страницы |
space |
$$\to$$ | пробел |
tab |
$$\to$$ | горизонтальная табуляция |
uniWhite |
$$\to$$ | любой пробельный символ Unicode |
comment |
$$\to$$ | |
|
$$\to$$ | -- {-} |
opencom |
$$\to$$ | {- |
closecom |
$$\to$$ | -} |
ncomment |
$$\to$$ | opencom ANYseq {ncomment ANYseq}closecom |
ANYseq |
$$\to$$ | {ANY}<{ANY}( opencom | closecom ) {ANY}> |
ANY |
$$\to$$ | graphic | whitechar |
any |
$$\to$$ | graphic | space | tab |
graphic |
$$\to$$ | small | large | symbol | digit | special | : | " | ' |
small |
$$\to$$ | ascSmall | uniSmall | _ |
ascSmall |
$$\to$$ | a | b | ... | z |
uniSmall |
$$\to$$ | любая буква Unicode нижнего регистра |
large |
$$\to$$ | ascLarge | uniLarge |
ascLarge |
$$\to$$ | A | B | ... | Z |
uniLarge |
$$\to$$ | любая буква Unicode верхнего регистра или заглавная |
symbol |
$$\to$$ | ascSymbol | uniSymbol<special | _ | : | " | '> |
ascSymbol |
$$\to$$ | ! | # | $ | % | | * | + | . | / | < | = | > | ? | @ |
| | | \ | ^ | | | - | $$\sim$$ | |
uniSymbol |
$$\to$$ | любой символ или знак пунктуации Unicode |
digit |
$$\to$$ | ascDigit | uniDigit |
ascDigit |
$$\to$$ | 0 | 1 | ... | 9 |
uniDigit |
$$\to$$ | любая десятичная цифра Unicode |
octit |
$$\to$$ | 0 | 1 | ... | 7 |
hexit |
$$\to$$ | digit | A | ... | F | a | ... | f |
Перевод:
| программа | $$\to$$ | { |
| $$\to$$ | квалифицированный-идентификатор-переменной | |
| | | квалифицированный-идентификатор-конструктора | |
| | | квалифицированный-символ-переменной | |
| | | квалифицированный-символ-конструктора | |
| | | литерал | |
| | | специальная- |
|
| | | зарезервированный-оператор | |
| | | зарезервированный-идентификатор | |
| литерал | $$\to$$ | целый-литерал |
| | | литерал-с-плавающей-точкой | |
| | | символьный-литерал | |
| | | строковый-литерал | |
| специальная- |
$$\to$$ | ( | ) | , | ; | [ | ] | apos;| { | } |
| пробельная-строка | $$\to$$ | пробельный-элемент {пробельный-элемент} |
| пробельный-элемент | $$\to$$ | пробельный-символ |
| | | комментарий | |
| | | вложенный-комментарий | |
| пробельный-символ | $$\to$$ | новая-строка |
| | | вертикальная-табуляция | |
| | | пробел | |
| | | горизонтальная-табуляция | |
| | | пробельный-символ-Unicode | |
| новая-строка | $$\to$$ | возврат-каретки перевод-строки |
| | | возврат-каретки | |
| | | перевод-строки | |
| | | перевод-страницы | |
| комментарий | $$\to$$ | тире [ любой-символ<символ> {любой-символ}] новая-строка |
| тире | $$\to$$ | -- {-} |
| начало-комментария | $$\to$$ | {- |
| конец-комментария | $$\to$$ | -} |
| вложенный-комментарий | $$\to$$ | начало-комментария ЛЮБАЯ-последовательность {вложенный-комментарий ЛЮБАЯ-последовательность}конец-комментария |
| ЛЮБАЯ-последовательность | $$\to$$ | {ЛЮБОЙ-символ}<{ЛЮБОЙ-символ}( начало-комментария | конец-комментария ) {ЛЮБОЙ-символ}> |
| ЛЮБОЙ-символ | $$\to$$ | графический-символ | пробельный-символ |
| любой-символ | $$\to$$ | графический-символ |
| | | пробел | |
| | | горизонтальная-табуляция | |
| графический-символ | $$\to$$ | маленькая-буква |
| | | большая-буква | |
| | | символ | |
| | | цифра | |
| | | специальная- |
|
| | | : | " | ' | |
| маленькая-буква | $$\to$$ | маленькая-буква-ASCII |
| | | маленькая-буква-Unicode | |
| | | - | |
| маленькая-буква-ASCII | $$\to$$ | a | b | ... | z |
| большая-буква | $$\to$$ | большая-буква-ASCII | большая-буква-Unicode |
| большая-буква-ASCII | $$\to$$ | A | B | ... | Z |
| символ | $$\to$$ | символ-ASCII |
| | | символ-Unicode<специальная-лексема | _ | : | " | '> | |
| символ-ASCII | $$\to$$ | ! | # | $ | % | | * | + | . | / | < | = | > | ? | @ |
| | | \ | ^ | | | - | $$\sim$$ | |
| символ-Unicode | $$\to$$ | любой символ или знак пунктуации Unicode |
| цифра | $$\to$$ | цифра-ASCII | цифра-Unicode |
| цифра-ASCII | $$\to$$ | 0 | 1 | ... | 9 |
| цифра-Unicode | $$\to$$ | любая десятичная цифра Unicode |
| восьмиричная-цифра | $$\to$$ | 0 | 1 | ... | 7 |
| шестнадцатиричная-цифра | $$\to$$ | цифра | A | ... | F | a | ... | f |
varid |
$$\to$$ | (small {small | large | digit | ' })<reservedid> |
|
conid |
$$\to$$ | large {small | large | digit | ' } |
|
reservedid |
$$\to$$ | case | class | data | default | |
|
| | | if | import | in | |
||
| | | let | module | newtype | of | tden | type | where | _ |
||
varsym |
$$\to$$ | ( symbol {symbol | :})<reservedop | dashes> |
|
consym |
$$\to$$ | (: {symbol | :})<reservedop> |
|
reservedop |
$$\to$$ | .. | : | :: | = | \ | | | $$\gets$$ | $$\to$$ | @ | $$\sim$$ | $$\Rightarrow$$ | |
varid |
(переменные) | ||
conid |
(конструкторы) | ||
tyvar |
$$\to$$ | varid |
(переменные типов) |
tycon |
$$\to$$ | conid |
( |
tycls |
$$\to$$ | conid |
(классы типов) |
modid |
$$\to$$ | conid |
(модули) |
qvarid |
$$\to$$ | [ modid . ] varid |
|
qconid |
$$\to$$ | [ modid . ] conid |
|
qtycon |
$$\to$$ | [ modid . ] tycon |
|
qtycls |
$$\to$$ | [ modid . ] tycls |
|
qvarsym |
$$\to$$ | [ modid . ] varsym |
|
qconsym |
$$\to$$ | [ modid . ] consym |
|
decimal |
$$\to$$ | digit{digit} |
|
|
$$\to$$ | octit{octit} |
|
|
$$\to$$ | hexit{hexit} |
|
integer |
$$\to$$ | decimal |
|
| | | 0o |
||
| | | 0x |
||
float |
$$\to$$ | decimal . decimal [ |
|
| | | decimal |
||
|
$$\to$$ | (e | E) [+ | -] decimal |
|
char |
$$\to$$ | ' (graphic<' | \> | space | escape<\>) ' |
|
string |
$$\to$$ | " {graphic<" | \> | space | escape | |
|
escape |
$$\to$$ | \ ( charesc | ascii | decimal | o |
|
charesc |
$$\to$$ | a | b | f | n | r | t | v | \ | " | ' | |
|
ascii |
$$\to$$ | ^cntrl | NUL | |
|
| | | |
||
| | | DC1 | DC2 | DC3 | DC4 | |
||
| | | EM | SUB | ESC | FS | GS | RS | US | SP | DEL |
||
cntrl |
$$\to$$ | ascLarge | @ | [ | \ | ] | ^ | _ |
|
|
$$\to$$ | \ whitechar {whitechar}\ |
Перевод:
| идентификатор-переменной | $$\to$$ | (маленькая-буква {маленькая-буква | большая-буква | цифра | ' })<зарезервированный-идентификатор> | |
| идентификатор-конструктора | $$\to$$ | большая-буква {маленькая-буква | большая-буква | цифра | ' } | |
| зарезервированный-идентификатор | $$\to$$ | case | class | data | default | |
|
| | | if | import | in | |
||
| | | let | module | newtype | of | tden | type | where | _ |
||
| символ-переменной | $$\to$$ | ( символ {символ | :})<зарезервированный-оператор| тире> | |
| символ-конструктора | $$\to$$ | (: {символ | :})< зарезервированный-оператор> | |
| зарезервированный-оператор | $$\to$$ | .. | : | :: | = | \ | | | $$\gets$$ | $$\to$$ | @ | $$\sim$$ | $$\Rightarrow$$ | |
| $$\to$$ | |||
| идентификатор-переменной | (переменные) | ||
| идентификатор-конструктора | (конструкторы) | ||
| переменная-типа | $$\to$$ | идентификатор-переменной | (переменные типов) |
| конструктор-типа | $$\to$$ | идентификатор-конструктора | ( |
| класс-типа | $$\to$$ | идентификатор-конструктора | (классы типов) |
| идентификатор-модуля | $$\to$$ | идентификатор-конструктора | (модули) |
| квалифицированный-идентификатор-переменной | $$\to$$ | [ идентификатор-модуля . ] идентификатор-переменной | |
| квалифицированный-идентификатор-конструктора | $$\to$$ | [идентификатор-модуля . ] идентификатор-конструктора | |
| квалифицированный-конструктор-типа | $$\to$$ | [идентификатор-модуля . ] конструктор-типа | |
| квалифицированный-класс-типа | $$\to$$ | [идентификатор-модуля . ] класс-типа | |
| квалифицированный-символ-переменной | $$\to$$ | [идентификатор-модуля . ] символ-переменной | |
| квалифицированный-символ-конструктора | $$\to$$ | [идентификатор-модуля . ] символ-конструктора | |
| десятичный-литерал | $$\to$$ | цифра{цифра} | |
| восьмиричный-литерал | $$\to$$ | восьмиричная-цифра{восьмиричная-цифра} | |
| шестнадцатиричный-литерал | $$\to$$ | шестнадцатиричная-цифра{шестнадцатиричная-цифра} | |
| целый-литерал | $$\to$$ | десятичный-литерал | |
| | | 0o восьмиричный-литерал | 0O восьмиричный-литерал | ||
| | | 0x шестнадцатиричный-литерал | 0X шестнадцатиричный-литерал | ||
| литерал-с-плавающей-точкой | $$\to$$ | десятичный-литерал . десятичный-литерал [экспонента] | |
| | | десятичный-литерал экспонента | ||
| экспонента | $$\to$$ | (e | E) [+ | -] десятичный-литерал |
|
| символьный-литерал | $$\to$$ | ' (графический-символ<' | \> | пробел | эскейп-символ<\>) ' | |
| строковый-литерал | $$\to$$ | " {графический-символ<" | \> | пробел | эскейп-символ | разрыв}" | |
| эскейп-символ | $$\to$$ | \ ( символ-эскейп | символ-ascii | десятичный-литерал | o восьмиричный-литерал | x шестнадцатиричный-литерал ) | |
| символ-эскейп | $$\to$$ | a | b | f | n | r | t | v | \ | " | ' | |
|
| символ-ascii | $$\to$$ | ^управляющий-символ | NUL | |
|
| | | |
||
| | | DC1 | DC2 | DC3 | DC4 | |
||
| | | EM | SUB | ESC | FS | GS | RS | US | SP | DEL |
||
| управляющий-символ | $$\to$$ | большая-буква-ASCII | @ | [ | \ | ] | ^ | _ | |
| разрыв | $$\to$$ | \ пробельный-символ {пробельный-символ}\ |
В разделе 2.7 дается неформальное определение правила размещения. В этом разделе это правило определено более точно.
Смысл программы на
Влияние размещения задано в этом разделе посредством описания того, как добавить фигурные скобки и точки с запятой в текст программы. Спецификация принимает вид функции L, которая выполняет трансляцию. Входом для L являются:
let, where, do или of не следует {n} вставляется после ключевого слова, где n --- отступ следующей module, то она предваряется {n}, где n --- отступ <n>, где n --- отступ {n}. (NB: строковый литерал может простираться на несколько строк (см. раздел 2.6). Поэтому во фрагментеf = ("Здравствуйте \
\Билл", "Джейк")
<n> не вставляются ни перед \Билл, потому что она не является началом законченной
"Отступом"
С целью соблюдения правил размещения, символы Unicode в исходной программе рассматриваются как те же символы фиксированной ширины, что и символы ASCII. Тем не менее, чтобы избежать визуальной путаницы, программистам следует избегать написания программ, в которых смысл неявного размещения зависит от ширины непробельных символов.
Применение L токены [] передает не зависящую от размещения трансляцию L заключается в следующем: где мы используем ":" в качестве оператора конструирования потока и "[]" для пустого потока.
L (<n>:ts) (m:ms) |
= | ; : (L ts (m:ms)) |
если m = n |
| = | } : (L (<n>:ts) ms) |
если n < m |
|
L (<n>:ts) ms |
= | L ts ms |
|
L ({n}:ts) (m:ms) |
= | { : (L ts (n:m:ms)) |
если n > m (Замечание 1) |
L ({n}:ts) [] |
= | { : (L ts [n]) |
если n > 0 (Замечание 1) |
L ({n}:ts) ms |
= | { : } : (L (<n>:ts) ms) |
(Замечание 2) |
L (}:ts) (0:ms) |
= | } : (L ts ms) |
(Замечание 3) |
L (}:ts) ms |
= | ошибка-разбора | (Замечание 3) |
L ({:ts) ms |
= | { : (L ts (0:ms)) |
(Замечание 4) |
L (t:ts) (m:ms) |
= | } : (L (t:ts) ms) |
если m /= 0 и ошибка-разбора (t) |
| (Замечание 5) | |||
L (t:ts) ms |
= | t : (L ts ms) |
|
L [] [] |
= | [] | |
L [] (m:ms) |
= | } : L [] ms |
если m /=0 (Замечание 6) |
Замечание 1. Вложенный контекст должен иметь больший отступ, чем внешний контекст (n>m). Если нет --- L завершается с ошибкой, и компилятору следует указать на ошибку размещения. Пример:
f x = let
h y = let
p z = z
in p
in h
Здесь определение p имеет меньший отступ, чем отступ внешнего контекста, который устанавливается в этом случае путем определения h.
Замечание 2. Если первый {n} заменяется на <n>, чтобы сымитировать ситуацию как если бы пустые фигурные скобки были явными.
Замечание 3. Посредством сопоставления с 0 текущего контекста размещения, мы гарантируем, что явная закрывающая фигурная скобка может быть сопоставлена только явной открывающей фигурной скобке. Если явная закрывающая фигурная скобка будет сопоставлена неявной открывающей фигурной скобке --- возникнет ошибка разбора.
Замечание 4. Это утверждение означает, что все пары фигурных скобок трактуются как явные контексты размещения, включая именованные создание типов данных и их обновление (раздел 3.15). В этом заключается разница между этой формулировкой и
Замечание 5. Дополнительное условие ошибка-разбора (t) интерпретируется следующим образом: если токены, порожденные до сих пор L вместе со следующим токеном t представляет недопустимый префикс в грамматике L, за которым следует (t) равна истине.
Проверка m /= 0 контролирует, что неявно добавленная закрывающая фигурная скобка будет сопоставлена неявной открывающей фигурной скобке.
Замечание 6. В конце ввода добавляются все незаконченные закрывающие фигурные скобки. Будет ошибкой оказаться здесь в пределах контекста без размещения (т.е. m = 0).
Если ни одно из данных выше правил не подойдет, то алгоритм завершится неудачей. Он может завершиться неудачей, например, когда будет достигнут конец ввода, и контекст без размещения будет активен, так как закрывающая фигурная скобка пропущена. Некоторые сбойные ситуации не обнаруживаются алгоритмом, хотя они могут быть: например, let }.
Замечание 1 реализует свойство, при котором обработка размещения может быть остановлена преждевременно из-за ошибки разбора. Например,
let x = e; y = x in e'
правильно, потому что оно транслируется в
let { x = e; y = x } in e'
Закрывающая фигурная скобка вставляется вследствие описанного выше правила ошибки разбора. Правило ошибки разбора трудно реализовать в его полной применимости ко всему, потому что выполнение этого влечет применение ассоциативностей. Например, выражение
do a == b == c
имеет единственный однозначный (хотя, возможно, неправильный с точки зрения типов) разбор, а именно:
(do { a == b }) == c
потому что (==) является неассоциативным. Поэтому программистам советуют избегать написания кода, который требует, чтобы синтаксический анализатор вставлял закрывающую фигурную скобку в таких ситуациях.
Соглашение о "грамотных комментариях", впервые разработанное Ричардом Бердом (Richard Bird) и Филиппом Уодлером (Philip Wadler) для Orwell, и позаимствованное в свою очередь Дональдом Кнутом (Donald Knutd) для "грамотного программирования", является альтернативным стилем программирования исходного кода на
Текст программы восстанавливается путем выбора только тех строк, которые начинаются с ">", и замены первого ">" на пробел. В полученном тексте размещение и комментарии применяются в точности как описано в главе 9.
Чтобы охватить некоторые случаи, где можно по ошибке пропустить ">", возникнет ошибка, если строка программы появится рядом с непробельной строкой комментария; строка рассматривается как пробельная, если она состоит только из пробельных символов.
Условно на стиль комментария указывает расширение файла: ".hs" указывает на обычный файл на
Эта грамотная программа запрашивает у пользователя число
и выводит на экран факториал этого числа:
> main :: IO ()
> main = do putStr "Введите число: "
> l <- readLine
> putStr "n!= "
> print (fact (read l))
Это программа вычисления факториала.
> fact :: Integer -> Integer
> fact 0 = 1
> fact n = n * fact (n-1)
Альтернативный стиль грамотного программирования особенно подходит для использования вместе с системой обработки текста LaTeX. По этому соглашению только те части грамотной программы, которые полностью заключены между разделителями \begin{code}...\end{code}, рассматриваются как текст программы; все остальные строки --- комментарии. Более точно:
\begin{code}.\end{code} (конечно, игнорируя строковые литералы).Нет необходимости вставлять дополнительные пустые строки до или после этих разделителей, хотя со стилистической точки зрения это может быть желательно. Например,
\documentstyle{article}
\begin{document}
\section{Introduction}
Это тривиальная программа, которая выводит первые 20 факториалов.
\begin{code}
main :: IO ()
main = print [ (n, product [1..n]) | n <- [1..20]]
\end{code}
\end{document}
Этот стиль использует то же расширение файла. Нежелательно смешивать эти два стиля в одном файле.
module |
$$\to$$ | module modid [exports] where body |
|
| | | body |
||
body |
$$\to$$ | { impdecls ; topdecls } |
|
| | | { impdecls } |
||
| | | { topdecls } |
||
impdecls |
$$\to$$ | impdecl1 ; ... ; impdecln |
(n>=1) |
Перевод:
| модуль | $$\to$$ | module идентификатор-модуля [список-экспорта] where тело |
|
| | | тело | ||
| тело | $$\to$$ | { список-объявлений-импорта ; список-объявлений-верхнего-уровня } | |
| | | { список-объявлений-импорта } | ||
| | | { список-объявлений-верхнего-уровня } | ||
| список-объявлений-импорта | $$\to$$ | объявление-импорта1 ; ... ; объявление-импортаn | (n>=1) |
exports |
$$\to$$ | ( export1 , ... , exportn [ , ] ) |
(n>=0) |
export |
$$\to$$ | qvar |
|
| | | qtycon [(..) | ( cname1 , ... , cnamen )] |
(n>=0) |
|
| | | qtycls [(..) | ( qvar1 , ... , qvarn )] |
(n>=0) |
|
| | | module modid |
Перевод:
| список-экспорта | $$\to$$ | ( экспорт1 , ... , экспортn [ , ] ) | (n>=0) |
| экспорт | $$\to$$ | квалифицированная-переменная | |
| | | квалифицированный-конструктор-типа [(..) | ( c-имя1 , ... , c-имяn )] | (n>=0) |
|
| | | квалифицированный-класс-типа [(..) | ( квалифицированная-переменная1 , ... , квалифицированная-переменнаяn )] | (n>=0) |
|
| | | module идентификатор-модуля |
impdecl |
$$\to$$ | import [ |
|
| | | (пустое объявление) | ||
impspec |
$$\to$$ | ( import1 , ... , importn [ , ] ) |
(n>=0) |
| | | hiding ( import1 , ... , importn [ , ] ) |
(n>=0) |
|
import |
$$\to$$ | var |
|
| | | tycon [ (..) | ( cname1 , ... , cnamen )] |
(n>=0) |
|
| | | tycls [(..) | ( var1 , ... , varn )] |
(n>=0) |
|
cname |
$$\to$$ | var | con |
Перевод:
| объявление-импорта | $$\to$$ | import [ идентификатор-модуля [ as идентификатор-модуля] [спецификатор-импорта] |
|
| | | (пустое объявление) | ||
| спецификатор-импорта | $$\to$$ | ( импорт1 , ... , импортn [ , ] ) | (n>=0) |
| | | hiding ( импорт1 , ... , импортn [ , ] ) | (n>=0) |
|
| импорт | $$\to$$ | переменная | |
| | | конструктор-типа [ (..) | ( c-имя1 , ... , c-имяn )] | (n>=0) |
|
| | | класс-типа [(..) | ( переменная1 , ... , переменнаяn )] | (n>=0) |
|
| c-имя | $$\to$$ | переменная | конструктор |
topdecls |
$$\to$$ | topdecl1 ; ... ; topdecln |
(n>=0) |
topdecl |
$$\to$$ | type simpletype = type |
|
| | | data [context =>] simpletype = constrs [ |
||
| | | newtype [context =>] simpletype = newconstr [ |
||
| | | class [scontext =>] tycls tyvar [where cdecls] |
||
| | | instance [scontext =>] qtycls inst [where idecls] |
||
| | | default (type1 , ... , typen) |
(n>=0) |
|
| | | decl |
Перевод:
| список-объявлений-верхнего-уровня | $$\to$$ | объявление-верхнего-уровня1 ; ... ; объявление-верхнего-уровняn | (n>=1) |
| объявление-верхнего-уровня | $$\to$$ | type простой-тип = тип |
|
| | | data [контекст $$\Rightarrow$$ ] простой-тип = список-конструкций [ -инструкция] |
||
| | | newtype [контекст $$\Rightarrow$$ ] простой-тип = новая-конструкция [ -инструкция] |
||
| | | class [простой-контекст $$\Rightarrow$$ ] класс-типа переменная-типа [ where список-объявлений-классов] |
||
| | | instance [простой-контекст $$\Rightarrow$$ ] квалифицированный-класс-типа экземпляр [ where список-объявлений-экземпляров] |
||
| | | default (тип1 , ... , типn) |
(n>=0) |
|
| | | объявление |
decls |
$$\to$$ | { decl1 ; ... ; decln } |
(n>=0) |
decl |
$$\to$$ | gendecl |
|
| | | (funlhs | |
||
cdecls |
$$\to$$ | { cdecl1 ; ... ; cdecln } |
(n>=0) |
cdecl |
$$\to$$ | gendecl |
|
| | | (funlhs | var) rhs |
||
idecls |
$$\to$$ | { idecl1 ; ... ; idecln } |
(n>=0) |
idecl |
$$\to$$ | (funlhs | var) rhs |
|
| | | (empty) |
||
gendecl |
$$\to$$ | vars :: [context =>] type |
(сигнатура типа) |
| | | fixity [integer] |
( -объявление) |
|
| | | (пустое объявление) | ||
|
$$\to$$ | |
(n>=1) |
vars |
$$\to$$ | var1 , ..., varn |
(n>=1) |
fixity |
$$\to$$ | infixl | infixr | |
Перевод:
| список-объявлений | $$\to$$ | { объявление1 ; ... ; объявлениеn } | (n>=0) |
| объявление | $$\to$$ | общее-объявление | |
| | | (левая-часть-функции | образец0) правая-часть | ||
| список-объявлений-классов | $$\to$$ | { объявление-класса1 ; ... ; объявление-классаn } | (n>=0) |
| объявление-класса | $$\to$$ | общее-объявление | |
| | | (левая-часть-функции | переменная) правая-часть | ||
| список-объявлений-экземпляров | $$\to$$ | { объявление-экземпляра1 ; ... ; объявление-экземпляраn } | (n>=0) |
| объявление-экземпляра | $$\to$$ | (левая-часть-функции | переменная) правая-часть | |
| | | (пусто) | ||
| общее-объявление | $$\to$$ | список-переменных :: [контекст $$\Rightarrow$$ ] тип | (сигнатура типа) |
| | | ассоциативность [целый-литерал] список-операторов | ( -объявление) |
|
| | | (пустое объявление) | ||
| список-операторов | $$\to$$ | оператор1 , ... , операторn | (n>=1) |
| список-переменных | $$\to$$ | переменная1 , ... , переменнаяn | (n>=1) |
| ассоциативность | $$\to$$ | infixl | infixr | |
type |
$$\to$$ | btype [-> type] |
(тип функции) |
btype |
$$\to$$ | [btype] atype |
(наложение типов) |
atype |
$$\to$$ | gtycon |
|
| | | tyvar |
||
| | | ( type1 , ... , typek ) |
(тип кортежа, k>=2 ) |
|
| | | [ type ] |
(тип списка) | |
| | | ( type ) |
(конструктор в скобках) | |
gtycon |
$$\to$$ | gtycon |
|
| | | () | (тип объединения) | |
| | | [] | (конструктор списка) | |
| | | ( $$\to$$ ) | (конструктор функции) | |
| | | (,{,}) | (конструкторы кортежей) | |
context |
$$\to$$ | class |
|
| | | ( class1 , ... , classn ) |
(n>=0) |
|
class |
$$\to$$ | qtycls tyvar |
|
| | | qtycls ( tyvar atype1 ... atypen ) |
(n>=1) |
|
scontext |
$$\to$$ | simpleclass |
|
| | | ( simpleclass1 , ... , simpleclassn ) |
(n>=0) |
|
simpleclass |
$$\to$$ | qtycls tyvar |
Перевод:
| тип | $$\to$$ | b -тип [ $$\to$$ тип] |
(тип функции) |
b -тип |
$$\to$$ | [ b -тип] a -тип |
(наложение типов) |
a -тип |
$$\to$$ | общий-конструктор-типа | |
| | | переменная-типа | ||
| | | ( тип1 , ... , типk ) | (тип кортежа, k>=2 ) |
|
| | | [ тип ] | (тип списка) | |
| | | ( тип ) | (конструктор в скобках) | |
| общий-конструктор-типа | $$\to$$ | квалифицированный-конструктор-типа | |
| | | () | (тип объединения) | |
| | | [] | (конструктор списка) | |
| | | ( $$\to$$ ) | (конструктор функции) | |
| | | (,{,}) | (конструкторы кортежей) | |
| контекст | $$\to$$ | класс | |
| | | ( класс1 , ... , классn ) | (n>=0) |
|
| класс | $$\to$$ | квалифицированный-класс-типа переменная-типа | |
| | | квалифицированный-класс-типа ( переменная-типа a-тип1 ... a-типn ) | (n>=1) |
|
| простой-контекст | $$\to$$ | простой-класс | |
| | | ( простой-класс1 , ... , простой-классn ) | (n>=0) |
|
| простой-класс | $$\to$$ | квалифицированный-класс-типа переменная-типа |
simpletype |
$$\to$$ | tycon tyvar1 ... tyvark |
(k>=0) |
constrs |
$$\to$$ | constr1 | ... | constrn |
(n>=1) |
constr |
$$\to$$ | con [!] atype1 ... [!] atypek |
(число аргументов конструктора con = k, k>=0 ) |
| | | (btype | ! atype) conop (btype | ! atype) |
(инфиксный оператор conop) | |
| | | con { fielddecl1 , ... , fielddecln } |
(n>=0) |
|
newconstr |
$$\to$$ | con atype |
|
| | | con { var :: type } |
||
fielddecl |
$$\to$$ | vars :: (type | ! atype) |
|
|
$$\to$$ | |
(n>=0) |
dclass |
$$\to$$ | qtycls |
Перевод:
| простой-тип | $$\to$$ | конструктор-типа переменная-типа1 ... переменная-типаk | (k>=0) |
| список-конструкций | $$\to$$ | конструкция1 | ... | конструкцияn | (n>=1) |
| конструкция | $$\to$$ | конструктор [!] a-тип1 ... [!] a-типk | (число аргументов конструктора con = k, k>=0 ) |
| | | (b-тип | ! a -тип) оператор-конструктора ( b -тип | ! a -тип) |
(инфиксный оператор conop ) |
|
| | | конструктор { объявление-поля1 , ... , объявление-поляn } | (n>=0) |
|
| новая-конструкция | $$\to$$ | конструктор a -тип |
|
| | | конструктор { переменная :: тип } | ||
| объявление-поля | $$\to$$ | список-переменных :: (тип | ! a -тип) |
|
-инструкция |
$$\to$$ | (производный-класс | (производный-класс1, ... , производный-классn)) |
(n>=0) |
| производный-класс | $$\to$$ | квалифицированный-класс-типа |
inst |
$$\to$$ | gtycon |
|
| | | ( gtycon tyvar1 ... tyvark ) |
( k>=0, все tyvar различны) |
|
| | | ( tyvar1 , ... , tyvark ) |
( k>=2, все tyvar различны) |
|
| | | [ tyvar ] |
||
| | | ( tyvar1 -> tyvar2 ) |
( tyvar1 и tyvar2 различны) |
Перевод:
| экземпляр | $$\to$$ | общий-конструктор-типа | |
| | | ( общий-конструктор-типа переменная-типа1 ... переменная-типаk ) | ( k>=0, все переменные-типа различны) |
|
| | | ( переменная-типа1 , ... , переменная-типаk ) | ( k>=2, все переменные-типа различны) |
|
| | | [ переменная-типа ] | ||
| | | ( переменная-типа1 $$\to$$ переменная-типа2 ) | (переменная-типа1 и переменная-типа2 различны) |
funlhs |
$$\to$$ | var apat {apat } |
| | | |
|
| | | lpati varop(l,i) |
|
| | | |
|
| | | ( funlhs ) apat {apat } |
|
rhs |
$$\to$$ | = exp [where decls] |
| | | gdrhs [where decls] |
|
gdrhs |
$$\to$$ | gd = exp [gdrhs] |
gd |
$$\to$$ | | exp0 |
Перевод:
| левая-часть-функции | $$\to$$ | переменная такой-как-образец {такой-как-образец } |
| | | образецi+1 оператор-переменной(a,i) образецi+1 | |
| | | левый-образецi оператор-переменной(l,i) образецi+1 | |
| | | образецi+1 оператор-переменной(r,i) правый-образецi | |
| | | ( левая-часть-функции ) такой-как-образец {такой-как-образец } | |
| правая-часть | $$\to$$ | = выражение [where список-объявлений] |
| | | правая-часть-со-стражами [where список-объявлений] | |
| правая-часть-со-стражами | $$\to$$ | страж = выражение [правая-часть-со-стражами] |
| страж | $$\to$$ | | выражение0 |
exp |
$$\to$$ | exp0 :: [context =>] type |
(сигнатура типа выражения) |
| | | exp0 |
||
expi |
$$\to$$ | expi+1 [qop(n,i) expi+1] |
|
| | | lexpi |
||
| | | rexpi |
||
lexpi |
$$\to$$ | (lexpi | expi+1) qop(l,i) expi+1 |
|
lexp6 |
$$\to$$ | - exp7 |
|
rexpi |
$$\to$$ | expi+1 qop (r,i) (rexpi | expi+1) |
|
exp10 |
$$\to$$ | \ apat1 ... apatn -> exp |
(лямбда-абстракция, n>=1 ) |
| | | let decls in exp |
( let -выражение) |
|
| | | if exp tden exp else exp |
(условное выражение) | |
| | | case exp of { alts } |
( case -выражение) |
|
| | | do { stmts } |
( do -выражение) |
|
| | | fexp |
||
fexp |
$$\to$$ | [fexp] aexp |
(применение функции) |
Перевод:
| выражение | $$\to$$ | выражение0 :: [контекст $$\Rightarrow$$ ] тип | (сигнатура типа выражения) |
| | | выражение0 | ||
| выражениеi | $$\to$$ | выражениеi+1 [квалифицированный-оператор(n,i) выражениеi+1] | |
| | | левое-сечение-выраженияi | ||
| | | правое-сечение-выраженияi | ||
| левое-сечение-выраженияi | $$\to$$ | (левое-сечение-выраженияi | выражениеi+1) квалифицированный-оператор(l,i) выражениеi+1 | |
| левое-сечение-выражения6 | $$\to$$ | - выражение7 | |
| правое-сечение-выраженияi | $$\to$$ | выражениеi+1 квалифицированный-оператор(r,i) (правое-сечение-выраженияi | выражениеi+1) | |
| выражение10 | $$\to$$ | \ такой-как-образец1 ... такой-как-образецn $$\to$$ выражение | (лямбда-абстракция, n>=1 ) |
| | | let списки-объявлений in выражение |
( let -выражение) |
|
| | | if выражение tden выражение else выражение |
(условное выражение) | |
| | | case выражение of { список-альтернатив } |
( case -выражение) |
|
| | | do { список-инструкций } |
( do -выражение) |
|
| | | функциональное-выражение | ||
| функциональное-выражение | $$\to$$ | [функциональное-выражение] выражение-аргумента | (применение функции) |
aexp |
$$\to$$ | qvar |
(переменная) |
| | | gcon |
(общий конструктор) | |
| | | |
||
| | | ( exp ) |
(выражение в скобках) | |
| | | ( exp1 , ... , expk ) |
(кортеж, k>=2 ) |
|
| | | [ exp1 , ... , expk ] |
(список, k>=1 ) |
|
| | | [ exp1 [, exp2] .. [exp3] ] |
(арифметическая последовательность) | |
| | | [ exp | qual1 , ... , qualn ] |
(описание списка, n>=1 ) |
|
| | | ( expi+1 qop(a,i) ) |
(левое сечение) | |
| | | ( lexpi qop(l,i) ) |
(левое сечение) | |
| | | ( qop(a,i)<-> expi+1 ) |
(правое сечение) | |
| | | ( qop(r,i)<-> rexpi ) |
(правое сечение) | |
| | | qcon { fbind1 , ... , fbindn } |
(именованная конструкция, n>=0 ) |
|
| | | aexp<qcon> { fbind1 , ... , fbindn } |
(именованное обновление, n >= 1 ) |
Перевод:
| выражение-аргумента | $$\to$$ | квалифицированная-переменная | (переменная) |
| | | общий-конструктор | (общий конструктор) | |
| | | литерал | ||
| | | ( выражение ) | (выражение в скобках) | |
| | | ( выражение1 , ... , выражениеk ) | (кортеж, k>=2 ) |
|
| | | [ выражение1 , ... , выражениеk ] | (список, k>=1 ) |
|
| | | [ выражение1 [, выражение2] .. [выражение3] ] | (арифметическая последовательность) | |
| | | [ выражение | квалификатор1 , ... , квалификаторn ] | (описание списка, n>=1 ) |
|
| | | ( выражениеi+1 квалифицированный-оператор(a,i) ) | (левое сечение) | |
| | | ( левое-сечение-выраженияi квалифицированный-оператор(l,i) ) | (левое сечение) | |
| | | ( квалифицированный-оператор(a,i)< $$\to$$ выражениеi+1 ) | (правое сечение) | |
| | | ( квалифицированный-оператор(r,i)< $$\to$$ правое-сечение-выраженияi ) | (правое сечение) | |
| | | квалифицированный-конструктор { связывание-имени-поля1 , ... , связывание-имени-поляn } | (именованная конструкция, n>=0 ) |
|
| | | выражение-аргумента<квалифицированный-конструктор> { связывание-имени-поля1 , ... , связывание-имени-поляn } | (именованное обновление, n>=1 ) |
qual |
$$\to$$ | |
(генератор) |
| | | let decls |
(локальное объявление) | |
| | | exp |
(страж) | |
alts |
$$\to$$ | alt1 ; ... ; altn |
(n>=1) |
alt |
$$\to$$ | |
|
| | | |
||
| | | (пустая альтернатива) | ||
gdpat |
$$\to$$ | gd -> exp [ gdpat ] |
|
stmts |
$$\to$$ | stmt1 ... stmtn exp [;] |
(n>=0) |
stmt |
$$\to$$ | exp ; |
|
| | | |
||
| | | let decls ; |
||
| | | ; | (пустая инструкция) | |
fbind
|
$$\to$$ | qvar = exp |
Перевод:
| квалификатор | $$\to$$ | образец $$\gets$$ выражение | (генератор) |
| | | let списки-объявлений |
(локальное объявление) | |
| | | выражение | (страж) | |
| список-альтернатив | $$\to$$ | альтернатива1 ; ... ; альтернативаn | (n>=1) |
| альтернатива | $$\to$$ | образец $$\to$$ выражение [where список-объявлений] | |
| | | образец образец-со-стражами [ where список-объявлений] |
||
| | | (пустая альтернатива) | ||
| образец-со-стражами | $$\to$$ | страж $$\to$$ выражение [ образец-со-стражами ] | |
| список-инструкций | $$\to$$ | инструкция1 ... инструкцияn выражение [;] | (n>=0) |
| инструкция | $$\to$$ | выражение ; | |
| | | образец $$\gets$$ выражение ; | ||
| | | let список-объявлений ; |
||
| | | ; | (пустая инструкция) | |
| связывание-имени-поля | $$\to$$ | квалифицированная-переменная = выражение |
|
$$\to$$ | var + integer |
(образец упорядочивания) |
| | | |
||
|
$$\to$$ | |
|
| | | lpati |
||
| | | rpati |
||
lpati |
$$\to$$ | (lpati | |
|
lpat6 |
$$\to$$ | - (integer | float) |
(отрицательный литерал) |
rpati |
$$\to$$ | |
|
|
$$\to$$ | apat |
|
| | | gcon apat1 ... apatk |
(число аргументов конструктора gcon = k, k>=1 ) |
Перевод:
| образец | $$\to$$ | переменная + целый-литерал | (образец упорядочивания) |
| | | образец0 | ||
| образецi | $$\to$$ | образецi+1 [квалифицированный-оператор-конструктора(n,i) образецi+1] | |
| | | левый-образецi | ||
| | | правый-образецi | ||
| левый-образецi | $$\to$$ | (левый-образецi | образецi+1) квалифицированный-оператор-конструктора(l,i) образецi+1 | |
| левый-образец6 | $$\to$$ | - (целый-литерал | литерал-с-плавающей-точкой) | (отрицательный литерал) |
| правый-образецi | $$\to$$ | образецi+1 квалифицированный-оператор-конструктора(r,i) (правый-образецi | образецi+1) | |
| образец10 | $$\to$$ | такой-как-образец | |
| | | общий-конструктор такой-как-образец1 ... такой-как-образецk | (число аргументов конструктора gcon = k, k>=1 ) |
apat |
$$\to$$ | var [@ apat] |
("такой как"-образец) |
| | | gcon |
(число аргументов конструктора gcon = 0 ) |
|
| | | qcon { fpat1 , ... , fpatk } |
(именованный образец, k>=0 ) |
|
| | | |
||
| | | _ | (любые символы) | |
| | | ( |
(образец в скобках) | |
| | | ( |
(образец кортежа, k>=2 ) |
|
| | | [ |
(образец списка, k>=1 ) |
|
| | | ~ apat |
(неопровержимый образец) | |
fpat |
$$\to$$ | qvar = |
Перевод:
| такой-как-образец | $$\to$$ | переменная [@ такой-как-образец] | ("такой как"-образец) |
| | | общий-конструктор | (число аргументов конструктора gcon = 0 ) |
|
| | | квалифицированный-конструктор { образец-с-именем1 , ... , образец-с-именемk } | (именованный образец, k>=0 ) |
|
| | | литерал | ||
| | | _ | (любые символы) | |
| | | ( образец ) | (образец в скобках) | |
| | | ( образец1 , ... , образецk ) | (образец кортежа, k>=2 ) |
|
| | | [ образец1 , ... , образецk ] | (образец списка, k>=1 ) |
|
| | | $$\sim$$ такой-как-образец | (неопровержимый образец) | |
| образец-с-именем | $$\to$$ | квалифицированная-переменная = образец |
gcon |
$$\to$$ | () | |
| | | [] | ||
| | | (,{,}) | ||
| | | qcon |
||
var |
$$\to$$ | varid | ( varsym ) |
(переменная) |
qvar |
$$\to$$ | qvarid | ( qvarsym ) |
(квалифицированная переменная) |
con |
$$\to$$ | conid | ( consym ) |
(конструктор) |
qcon |
$$\to$$ | qconid | ( gconsym ) |
(квалифицированный конструктор) |
varop |
$$\to$$ | varsym | apos;varid apos; |
(оператор переменной) |
qvarop |
$$\to$$ | qvarsym | apos;qvarid apos; |
(квалифицированный оператор переменной) |
conop |
$$\to$$ | consym | apos;conid apos; |
(оператор конструктора) |
qconop |
$$\to$$ | gconsym | apos;qconid apos; |
(квалифицированный оператор конструктора) |
|
$$\to$$ | varop | conop |
(оператор) |
qop |
$$\to$$ | qvarop | qconop |
(квалифицированный оператор) |
gconsym |
$$\to$$ | : | qconsym |
Перевод:
| общий-конструктор | $$\to$$ | () | |
| | | [] | ||
| | | (,{,}) | ||
| | | квалифицированный-конструктор | ||
| переменная | $$\to$$ | идентификатор-переменной | ( символ-переменной ) | (переменная) |
| квалифицированная-переменная | $$\to$$ | квалифицированный-идентификатор-переменной | ( квалифицированный-символ-переменной ) | (квалифицированная переменная) |
| конструктор | $$\to$$ | идентификатор-конструктора | (символ-конструктора ) | (конструктор) |
| квалифицированный-конструктор | $$\to$$ | квалифицированный-идентификатор-конструктора | ( символ-общего-конструктора ) | (квалифицированный конструктор) |
| оператор-переменной | $$\to$$ | символ-переменной | apos;идентификатор-переменной apos; | (оператор переменной) |
| квалифицированный-оператор-переменной | $$\to$$ | квалифицированный-символ-переменной | apos;квалифицированный-идентификатор-переменной apos; | (квалифицированный оператор переменной) |
| оператор-конструктора | $$\to$$ | символ-конструктора | apos;идентификатор-конструктора apos; | (оператор конструктора) |
| квалифицированный-оператор-конструктора | $$\to$$ | символ-общего-конструктора | apos;квалифицированный-идентификатор-конструктора apos; | (квалифицированный оператор конструктора) |
| оператор | $$\to$$ | оператор-переменной | оператор-конструктора | (оператор) |
| квалифицированный-оператор | $$\to$$ | квалифицированный-оператор-переменной | квалифицированный-оператор-конструктора | (квалифицированный оператор) |
| символ-общего-конструктора | $$\to$$ | : | квалифицированный-символ-конструктора |
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.