Эти соглашения об обозначениях используются для представления синтаксиса:
[pattern] | необязательный |
{pattern} | ноль или более повторений |
(pattern) | группировка |
pat1 | pat2 | выбор |
pat<pat'> | разность --- элементы, порождаемые с помощью pat, |
за исключением элементов, порождаемых с помощью pat' | |
fibonacci | терминальный синтаксис в машинописном шрифте |
Повсюду используется BNF-подобный синтаксис, чьи правила вывода имеют вид:
nonterm | -> | alt1 | alt2 | ... | altn |
Перевод: | ||
нетерминал | -> | альтернатива1 | альтернатива2 | ... | альтернативаn |
В синтаксисе, который следует далее, есть некоторые семейства нетерминалов, индексированные уровнями приоритета (записанными как верхний индекс). Аналогично, нетерминалы op (оператор), varop (оператор-переменной) и conop (оператор-конструктора) могут иметь двойной индекс: букву l, r или n соответственно для левоассоциативности, правоассоциативности или отсутствия ассоциативности и уровень приоритета. Переменная уровня приоритета i изменяется в пределах от 0 до 9, переменная ассоциативности a изменяется в диапазоне {l, r, n}. Например,
aexp | -> | ( expi+1 qop(a,i) ) |
И в лексическом, и в контекстно-свободном синтаксисе есть некоторые неоднозначности, которые разрешаются посредством создания грамматических фраз наибольшей из возможных длины, действуя слева направо (в восходящем синтаксическом анализе при конфликте сдвиг - свертка выполняется сдвиг). В лексическом синтаксисе это правило "максимального потребления". В контекстно-свободном синтаксисе это означает, что условные выражения, let-выражения и лямбда-абстракции продолжаются вправо насколько возможно.
program | -> | {lexeme | whitespace } |
lexeme | -> | qvarid | qconid | qvarsym | qconsym |
| | literal | special | reservedop | reservedid | |
literal | -> | integer | float | char | string |
special | -> | ( | ) | , | ; | [ | ] | `| { | } |
whitespace | -> | whitestuff {whitestuff} |
whitestuff | -> | whitechar | comment | ncomment |
whitechar | -> | newline | vertab | space | tab | uniWhite |
newline | -> | return linefeed | return | linefeed | formfeed |
return | -> | возврат каретки |
linefeed | -> | перевод строки |
vertab | -> | вертикальная табуляция |
formfeed | -> | перевод страницы |
space | -> | пробел |
tab | -> | горизонтальная табуляция |
uniWhite | -> | любой пробельный символ Unicode |
comment | -> | dashes [ any<symbol> {any}] newline |
dashes | -> | -- {-} |
opencom | -> | {- |
closecom | -> | -} |
ncomment | -> | opencom ANYseq {ncomment ANYseq}closecom |
ANYseq | -> | {ANY}<{ANY}( opencom | closecom ) {ANY}> |
ANY | -> | graphic | whitechar |
any | -> | graphic | space | tab |
graphic | -> | small | large | symbol | digit | special | : | " | ' |
small | -> | ascSmall | uniSmall | _ |
ascSmall | -> | a | b | ... | z |
uniSmall | -> | любая буква Unicode нижнего регистра |
large | -> | ascLarge | uniLarge |
ascLarge | -> | A | B | ... | Z |
uniLarge | -> | любая буква Unicode верхнего регистра или заглавная |
symbol | -> | ascSymbol | uniSymbol<special | _ | : | " | '> |
ascSymbol | -> | ! | # | $ | % | & | * | + | . | / | < | = | > | ? | @ |
| | \ | ^ | | | - | ~ | |
uniSymbol | -> | любой символ или знак пунктуации Unicode |
digit | -> | ascDigit | uniDigit |
ascDigit | -> | 0 | 1 | ... | 9 |
uniDigit | -> | любая десятичная цифра Unicode |
octit | -> | 0 | 1 | ... | 7 |
hexit | -> | digit | A | ... | F | a | ... | f |
Перевод: | ||
программа | -> | {лексема | пробельная-строка } |
лексема | -> | квалифицированный-идентификатор-переменной |
| | квалифицированный-идентификатор-конструктора | |
| | квалифицированный-символ-переменной | |
| | квалифицированный-символ-конструктора | |
| | литерал | |
| | специальная-лексема | |
| | зарезервированный-оператор | |
| | зарезервированный-идентификатор | |
литерал | -> | целый-литерал |
| | литерал-с-плавающей-точкой | |
| | символьный-литерал | |
| | строковый-литерал | |
специальная-лексема | -> | ( | ) | , | ; | [ | ] | `| { | } |
пробельная-строка | -> | пробельный-элемент {пробельный-элемент} |
пробельный-элемент | -> | пробельный-символ |
| | комментарий | |
| | вложенный-комментарий | |
пробельный-символ | -> | новая-строка |
| | вертикальная-табуляция | |
| | пробел | |
| | горизонтальная-табуляция | |
| | пробельный-символ-Unicode | |
новая-строка | -> | возврат-каретки перевод-строки |
| | возврат-каретки | |
| | перевод-строки | |
| | перевод-страницы | |
комментарий | -> | тире [ любой-символ<символ> {любой-символ}] новая-строка |
тире | -> | -- {-} |
начало-комментария | -> | {- |
конец-комментария | -> | -} |
вложенный-комментарий | -> | начало-комментария ЛЮБАЯ-последовательность {вложенный-комментарий ЛЮБАЯ-последовательность}конец-комментария |
ЛЮБАЯ-последовательность | -> | {ЛЮБОЙ-символ}<{ЛЮБОЙ-символ}( начало-комментария | конец-комментария ) {ЛЮБОЙ-символ}> |
ЛЮБОЙ-символ | -> | графический-символ | пробельный-символ |
любой-символ | -> | графический-символ |
| | пробел | |
| | горизонтальная-табуляция | |
графический-символ | -> | маленькая-буква |
| | большая-буква | |
| | символ | |
| | цифра | |
| | специальная-лексема | |
| | : | " | ' | |
маленькая-буква | -> | маленькая-буква-ASCII |
| | маленькая-буква-Unicode | |
| | _ | |
маленькая-буква-ASCII | -> | a | b | ... | z |
большая-буква | -> | большая-буква-ASCII | большая-буква-Unicode |
большая-буква-ASCII | -> | A | B | ... | Z |
символ | -> | символ-ASCII |
| | символ-Unicode<специальная-лексема | _ | : | " | '> | |
символ-ASCII | -> | ! | # | $ | % | & | * | + | . | / | < | = | > | ? | @ |
| | \ | ^ | | | - | ~ | |
символ-Unicode | -> | любой символ или знак пунктуации Unicode |
цифра | -> | цифра-ASCII | цифра-Unicode |
цифра-ASCII | -> | 0 | 1 | ... | 9 |
цифра-Unicode | -> | любая десятичная цифра Unicode |
восьмиричная-цифра | -> | 0 | 1 | ... | 7 |
шестнадцатиричная-цифра | -> | цифра | A | ... | F | a | ... | f |
varid | -> | (small {small | large | digit | ' })<reservedid> | |
conid | -> | large {small | large | digit | ' } | |
reservedid | -> | case | class | data | default | deriving | do | else | |
| | if | import | in | infix | infixl | infixr | instance | ||
| | let | module | newtype | of | then | type | where | _ | ||
varsym | -> | ( symbol {symbol | :})<reservedop | dashes> | |
consym | -> | (: {symbol | :})<reservedop> | |
reservedop | -> | .. | : | :: | = | \ | | | <- | -> | @ | ~ | => | |
varid | (переменные) | ||
conid | (конструкторы) | ||
tyvar | -> | varid | (переменные типов) |
tycon | -> | conid | (конструкторы типов) |
tycls | -> | conid | (классы типов) |
modid | -> | conid | (модули) |
qvarid | -> | [ modid . ] varid | |
qconid | -> | [ modid . ] conid | |
qtycon | -> | [ modid . ] tycon | |
qtycls | -> | [ modid . ] tycls | |
qvarsym | -> | [ modid . ] varsym | |
qconsym | -> | [ modid . ] consym | |
decimal | -> | digit{digit} | |
octal | -> | octit{octit} | |
hexadecimal | -> | hexit{hexit} | |
integer | -> | decimal | |
| | 0o octal | 0O octal | ||
| | 0x hexadecimal | 0X hexadecimal | ||
float | -> | decimal . decimal [exponent] | |
| | decimal exponent | ||
exponent | -> | (e | E) [+ | -] decimal | |
char | -> | ' (graphic<' | \> | space | escape<\&>) ' | |
string | -> | " {graphic<" | \> | space | escape | gap}" | |
escape | -> | \ ( charesc | ascii | decimal | o octal | x hexadecimal ) | |
charesc | -> | a | b | f | n | r | t | v | \ | " | ' | & | |
ascii | -> | ^cntrl | NUL | SOH | STX | ETX | EOT | ENQ | ACK | |
| | BEL | BS | HT | LF | VT | FF | CR | SO | SI | DLE | ||
| | DC1 | DC2 | DC3 | DC4 | NAK | SYN | ETB | CAN | ||
| | EM | SUB | ESC | FS | GS | RS | US | SP | DEL | ||
cntrl | -> | ascLarge | @ | [ | \ | ] | ^ | _ | |
gap | -> | \ whitechar {whitechar}\ |
Перевод: | |||
идентификатор-переменной | -> | (маленькая-буква {маленькая-буква | большая-буква | цифра | ' })<зарезервированный-идентификатор> | |
идентификатор-конструктора | -> | большая-буква {маленькая-буква | большая-буква | цифра | ' } | |
зарезервированный-идентификатор | -> | case | class | data | default | deriving | do | else | |
| | if | import | in | infix | infixl | infixr | instance | ||
| | let | module | newtype | of | then | type | where | _ | ||
символ-переменной | -> | ( символ {символ | :})<зарезервированный-оператор| тире> | |
символ-конструктора | -> | (: {символ | :})< зарезервированный-оператор> | |
зарезервированный-оператор | -> | .. | : | :: | = | \ | | | <- | -> | @ | ~ | => | |
идентификатор-переменной | (переменные) | ||
идентификатор-конструктора | (конструкторы) | ||
переменная-типа | -> | идентификатор-переменной | (переменные типов) |
конструктор-типа | -> | идентификатор-конструктора | (конструкторы типов) |
класс-типа | -> | идентификатор-конструктора | (классы типов) |
идентификатор-модуля | -> | идентификатор-конструктора | (модули) |
квалифицированный-идентификатор-переменной | -> | [ идентификатор-модуля . ] идентификатор-переменной | |
квалифицированный-идентификатор-конструктора | -> | [идентификатор-модуля . ] идентификатор-конструктора | |
квалифицированный-конструктор-типа | -> | [идентификатор-модуля . ] конструктор-типа | |
квалифицированный-класс-типа | -> | [идентификатор-модуля . ] класс-типа | |
квалифицированный-символ-переменной | -> | [идентификатор-модуля . ] символ-переменной | |
квалифицированный-символ-конструктора | -> | [идентификатор-модуля . ] символ-конструктора | |
десятичный-литерал | -> | цифра{цифра} | |
восьмиричный-литерал | -> | восьмиричная-цифра{восьмиричная-цифра} | |
шестнадцатиричный-литерал | -> | шестнадцатиричная-цифра{шестнадцатиричная-цифра} | |
целый-литерал | -> | десятичный-литерал | |
| | 0o восьмиричный-литерал | 0O восьмиричный-литерал | ||
| | 0x шестнадцатиричный-литерал | 0X шестнадцатиричный-литерал | ||
литерал-с-плавающей-точкой | -> | десятичный-литерал . десятичный-литерал [экспонента] | |
| | десятичный-литерал экспонента | ||
экспонента | -> | (e | E) [+ | -] десятичный-литерал | |
символьный-литерал | -> | ' (графический-символ<' | \> | пробел | эскейп-символ<\&>) ' | |
строковый-литерал | -> | " {графический-символ<" | \> | пробел | эскейп-символ | разрыв}" | |
эскейп-символ | -> | \ ( символ-эскейп | символ-ascii | десятичный-литерал | o восьмиричный-литерал | x шестнадцатиричный-литерал ) | |
символ-эскейп | -> | a | b | f | n | r | t | v | \ | " | ' | & | |
символ-ascii | -> | ^управляющий-символ | NUL | SOH | STX | ETX | EOT | ENQ | ACK | |
| | BEL | BS | HT | LF | VT | FF | CR | SO | SI | DLE | ||
| | DC1 | DC2 | DC3 | DC4 | NAK | SYN | ETB | CAN | ||
| | EM | SUB | ESC | FS | GS | RS | US | SP | DEL | ||
управляющий-символ | -> | большая-буква-ASCII | @ | [ | \ | ] | ^ | _ | |
разрыв | -> | \ пробельный-символ {пробельный-символ}\ |
В разделе 2.7 дается неформальное определение правила размещения. В этом разделе это правило определено более точно.
Смысл программы на Haskell может зависеть от размещения ее текста. Влияние размещения на ее смысл может быть полностью описано путем добавления фигурных скобок и точек с запятой в местах, определяемых размещением. Смысл такого дополнения программы состоит в том, чтобы сделать ее не зависимой от размещения текста.
Влияние размещения задано в этом разделе посредством описания того, как добавить фигурные скобки и точки с запятой в текст программы. Спецификация принимает вид функции L, которая выполняет трансляцию. Входом для L являются:
"Отступом" лексемы является номер колонки для первого символа этой лексемы; отступом строки является отступ его крайней слева лексемы. Для того чтобы определить номер колонки, предположим, что используется шрифт фиксированной ширины со следующими условностями:
Применение
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) |
Проверка 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 Knuth) для "грамотного программирования", является альтернативным стилем программирования исходного кода на Haskell . Грамотный стиль поощряет комментарии, создавая их по умолчанию. Строка, в которой ">" является первым символом, интерпретируется как часть программы; все остальные строки являются комментарием.
Текст программы восстанавливается путем выбора только тех строк, которые начинаются с ">", и замены первого ">" на пробел. В полученном тексте размещение и комментарии применяются в точности как описано в главе 9.
Чтобы охватить некоторые случаи, где можно по ошибке пропустить ">", возникнет ошибка, если строка программы появится рядом с непробельной строкой комментария; строка рассматривается как пробельная, если она состоит только из пробельных символов.
Условно на стиль комментария указывает расширение файла:
".hs" указывает на обычный файл на Haskell, а
".lhs" указывает на файл с грамотным Haskell. С использованием этого стиля
простая программа вычисления факториала могла бы выглядеть так:
Эта грамотная программа запрашивает у пользователя число
и выводит на экран факториал этого числа:
> 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}, рассматриваются как текст программы; все остальные строки --- комментарии. Более точно:
module | -> | module modid [exports] where body | |
| | body | ||
body | -> | { impdecls ; topdecls } | |
| | { impdecls } | ||
| | { topdecls } | ||
impdecls | -> | impdecl1 ; ... ; impdecln | (n>=1) |
Перевод: | |||
модуль | -> | module идентификатор-модуля [список-экспорта] where тело | |
| | тело | ||
тело | -> | { список-объявлений-импорта ; список-объявлений-верхнего-уровня } | |
| | { список-объявлений-импорта } | ||
| | { список-объявлений-верхнего-уровня } | ||
список-объявлений-импорта | -> | объявление-импорта1 ; ... ; объявление-импортаn | (n>=1) |
exports | -> | ( export1 , ... , exportn [ , ] ) | (n>=0) |
export | -> | qvar | |
| | qtycon [(..) | ( cname1 , ... , cnamen )] | (n>=0) | |
| | qtycls [(..) | ( qvar1 , ... , qvarn )] | (n>=0) | |
| | module modid |
Перевод: | |||
список-экспорта | -> | ( экспорт1 , ... , экспортn [ , ] ) | (n>=0) |
экспорт | -> | квалифицированная-переменная | |
| | квалифицированный-конструктор-типа [(..) | ( c-имя1 , ... , c-имяn )] | (n>=0) | |
| | квалифицированный-класс-типа [(..) | ( квалифицированная-переменная1 , ... , квалифицированная-переменнаяn )] | (n>=0) | |
| | module идентификатор-модуля |
impdecl | -> | import [qualified] modid [as modid] [impspec] | |
| | (пустое объявление) | ||
impspec | -> | ( import1 , ... , importn [ , ] ) | (n>=0) |
| | hiding ( import1 , ... , importn [ , ] ) | (n>=0) | |
import | -> | var | |
| | tycon [ (..) | ( cname1 , ... , cnamen )] | (n>=0) | |
| | tycls [(..) | ( var1 , ... , varn )] | (n>=0) | |
cname | -> | var | con |
Перевод: | |||
объявление-импорта | -> | import [qualified] идентификатор-модуля [as идентификатор-модуля] [спецификатор-импорта] | |
| | (пустое объявление) | ||
спецификатор-импорта | -> | ( импорт1 , ... , импортn [ , ] ) | (n>=0) |
| | hiding ( импорт1 , ... , импортn [ , ] ) | (n>=0) | |
импорт | -> | переменная | |
| | конструктор-типа [ (..) | ( c-имя1 , ... , c-имяn )] | (n>=0) | |
| | класс-типа [(..) | ( переменная1 , ... , переменнаяn )] | (n>=0) | |
c-имя | -> | переменная | конструктор |
topdecls | -> | topdecl1 ; ... ; topdecln | (n>=0) |
topdecl | -> | type simpletype = type | |
| | data [context =>] simpletype = constrs [deriving] | ||
| | newtype [context =>] simpletype = newconstr [deriving] | ||
| | class [scontext =>] tycls tyvar [where cdecls] | ||
| | instance [scontext =>] qtycls inst [where idecls] | ||
| | default (type1 , ... , typen) | (n>=0) | |
| | decl |
Перевод: | |||
список-объявлений-верхнего-уровня | -> | объявление-верхнего-уровня1 ; ... ; объявление-верхнего-уровняn | (n>=1) |
объявление-верхнего-уровня | -> | type простой-тип = тип | |
| | data [контекст =>] простой-тип = список-конструкций [deriving-инструкция] | ||
| | newtype [контекст =>] простой-тип = новая-конструкция [deriving-инструкция] | ||
| | class [простой-контекст =>] класс-типа переменная-типа [where список-объявлений-классов] | ||
| | instance [простой-контекст =>] квалифицированный-класс-типа экземпляр [where список-объявлений-экземпляров] | ||
| | default (тип1 , ... , типn) | (n>=0) | |
| | объявление |
decls | -> | { decl1 ; ... ; decln } | (n>=0) |
decl | -> | gendecl | |
| | (funlhs | pat0) rhs | ||
cdecls | -> | { cdecl1 ; ... ; cdecln } | (n>=0) |
cdecl | -> | gendecl | |
| | (funlhs | var) rhs | ||
idecls | -> | { idecl1 ; ... ; idecln } | (n>=0) |
idecl | -> | (funlhs | var) rhs | |
| | (empty) | ||
gendecl | -> | vars :: [context =>] type | (сигнатура типа) |
| | fixity [integer] ops | (infix-объявление) | |
| | (пустое объявление) | ||
ops | -> | op1 , ... , opn | (n>=1) |
vars | -> | var1 , ..., varn | (n>=1) |
fixity | -> | infixl | infixr | infix |
Перевод: | |||
список-объявлений | -> | { объявление1 ; ... ; объявлениеn } | (n>=0) |
объявление | -> | общее-объявление | |
| | (левая-часть-функции | образец0) правая-часть | ||
список-объявлений-классов | -> | { объявление-класса1 ; ... ; объявление-классаn } | (n>=0) |
объявление-класса | -> | общее-объявление | |
| | (левая-часть-функции | переменная) правая-часть | ||
список-объявлений-экземпляров | -> | { объявление-экземпляра1 ; ... ; объявление-экземпляраn } | (n>=0) |
объявление-экземпляра | -> | (левая-часть-функции | переменная) правая-часть | |
| | (пусто) | ||
общее-объявление | -> | список-переменных :: [контекст =>] тип | (сигнатура типа) |
| | ассоциативность [целый-литерал] список-операторов | (infix-объявление) | |
| | (пустое объявление) | ||
список-операторов | -> | оператор1 , ... , операторn | (n>=1) |
список-переменных | -> | переменная1 , ... , переменнаяn | (n>=1) |
ассоциативность | -> | infixl | infixr | infix |
type | -> | btype [-> type] | (тип функции) |
btype | -> | [btype] atype | (наложение типов) |
atype | -> | gtycon | |
| | tyvar | ||
| | ( type1 , ... , typek ) | (тип кортежа, k>=2) | |
| | [ type ] | (тип списка) | |
| | ( type ) | (конструктор в скобках) | |
gtycon | -> | qtycon | |
| | () | (тип объединения) | |
| | [] | (конструктор списка) | |
| | (->) | (конструктор функции) | |
| | (,{,}) | (конструкторы кортежей) | |
context | -> | class | |
| | ( class1 , ... , classn ) | (n>=0) | |
class | -> | qtycls tyvar | |
| | qtycls ( tyvar atype1 ... atypen ) | (n>=1) | |
scontext | -> | simpleclass | |
| | ( simpleclass1 , ... , simpleclassn ) | (n>=0) | |
simpleclass | -> | qtycls tyvar |
Перевод: | |||
тип | -> | b-тип [-> тип] | (тип функции) |
b-тип | -> | [b-тип] a-тип | (наложение типов) |
a-тип | -> | общий-конструктор-типа | |
| | переменная-типа | ||
| | ( тип1 , ... , типk ) | (тип кортежа, k>=2) | |
| | [ тип ] | (тип списка) | |
| | ( тип ) | (конструктор в скобках) | |
общий-конструктор-типа | -> | квалифицированный-конструктор-типа | |
| | () | (тип объединения) | |
| | [] | (конструктор списка) | |
| | (->) | (конструктор функции) | |
| | (,{,}) | (конструкторы кортежей) | |
контекст | -> | класс | |
| | ( класс1 , ... , классn ) | (n>=0) | |
класс | -> | квалифицированный-класс-типа переменная-типа | |
| | квалифицированный-класс-типа ( переменная-типа a-тип1 ... a-типn ) | (n>=1) | |
простой-контекст | -> | простой-класс | |
| | ( простой-класс1 , ... , простой-классn ) | (n>=0) | |
простой-класс | -> | квалифицированный-класс-типа переменная-типа |
simpletype | -> | tycon tyvar1 ... tyvark | (k>=0) |
constrs | -> | constr1 | ... | constrn | (n>=1) |
constr | -> | con [!] atype1 ... [!] atypek | (число аргументов конструктора con = k, k>=0) |
| | (btype | ! atype) conop (btype | ! atype) | (инфиксный оператор conop) | |
| | con { fielddecl1 , ... , fielddecln } | (n>=0) | |
newconstr | -> | con atype | |
| | con { var :: type } | ||
fielddecl | -> | vars :: (type | ! atype) | |
deriving | -> | deriving (dclass | (dclass1, ... , dclassn)) | (n>=0) |
dclass | -> | qtycls |
Перевод: | |||
простой-тип | -> | конструктор-типа переменная-типа1 ... переменная-типаk | (k>=0) |
список-конструкций | -> | конструкция1 | ... | конструкцияn | (n>=1) |
конструкция | -> | конструктор [!] a-тип1 ... [!] a-типk | (число аргументов конструктора con = k, k>=0) |
| | (b-тип | ! a-тип) оператор-конструктора (b-тип | ! a-тип) | (инфиксный оператор conop) | |
| | конструктор { объявление-поля1 , ... , объявление-поляn } | (n>=0) | |
новая-конструкция | -> | конструктор a-тип | |
| | конструктор { переменная :: тип } | ||
объявление-поля | -> | список-переменных :: (тип | ! a-тип) | |
deriving-инструкция | -> | deriving (производный-класс | (производный-класс1, ... , производный-классn)) | (n>=0) |
производный-класс | -> | квалифицированный-класс-типа |
inst | -> | gtycon | |
| | ( gtycon tyvar1 ... tyvark ) | (k>=0, все tyvar различны) | |
| | ( tyvar1 , ... , tyvark ) | (k>=2, все tyvar различны) | |
| | [ tyvar ] | ||
| | ( tyvar1 -> tyvar2 ) | (tyvar1 и tyvar2 различны) |
Перевод: | |||
экземпляр | -> | общий-конструктор-типа | |
| | ( общий-конструктор-типа переменная-типа1 ... переменная-типаk ) | (k>=0, все переменные-типа различны) | |
| | ( переменная-типа1 , ... , переменная-типаk ) | (k>=2, все переменные-типа различны) | |
| | [ переменная-типа ] | ||
| | ( переменная-типа1 -> переменная-типа2 ) | (переменная-типа1 и переменная-типа2 различны) |
funlhs | -> | var apat {apat } |
| | pati+1 varop(a,i) pati+1 | |
| | lpati varop(l,i) pati+1 | |
| | pati+1 varop(r,i) rpati | |
| | ( funlhs ) apat {apat } | |
rhs | -> | = exp [where decls] |
| | gdrhs [where decls] | |
gdrhs | -> | gd = exp [gdrhs] |
gd | -> | | exp0 |
Перевод: | ||
левая-часть-функции | -> | переменная такой-как-образец {такой-как-образец } |
| | образецi+1 оператор-переменной(a,i) образецi+1 | |
| | левый-образецi оператор-переменной(l,i) образецi+1 | |
| | образецi+1 оператор-переменной(r,i) правый-образецi | |
| | ( левая-часть-функции ) такой-как-образец {такой-как-образец } | |
правая-часть | -> | = выражение [where список-объявлений] |
| | правая-часть-со-стражами [where список-объявлений] | |
правая-часть-со-стражами | -> | страж = выражение [правая-часть-со-стражами] |
страж | -> | | выражение0 |
exp | -> | exp0 :: [context =>] type | (сигнатура типа выражения) |
| | exp0 | ||
expi | -> | expi+1 [qop(n,i) expi+1] | |
| | lexpi | ||
| | rexpi | ||
lexpi | -> | (lexpi | expi+1) qop(l,i) expi+1 | |
lexp6 | -> | - exp7 | |
rexpi | -> | expi+1 qop(r,i) (rexpi | expi+1) | |
exp10 | -> | \ apat1 ... apatn -> exp | (лямбда-абстракция, n>=1) |
| | let decls in exp | (let-выражение) | |
| | if exp then exp else exp | (условное выражение) | |
| | case exp of { alts } | (case-выражение) | |
| | do { stmts } | (do-выражение) | |
| | fexp | ||
fexp | -> | [fexp] aexp | (применение функции) |
Перевод: | |||
выражение | -> | выражение0 :: [контекст =>] тип | (сигнатура типа выражения) |
| | выражение0 | ||
выражениеi | -> | выражениеi+1 [квалифицированный-оператор(n,i) выражениеi+1] | |
| | левое-сечение-выраженияi | ||
| | правое-сечение-выраженияi | ||
левое-сечение-выраженияi | -> | (левое-сечение-выраженияi | выражениеi+1) квалифицированный-оператор(l,i) выражениеi+1 | |
левое-сечение-выражения6 | -> | - выражение7 | |
правое-сечение-выраженияi | -> | выражениеi+1 квалифицированный-оператор(r,i) (правое-сечение-выраженияi | выражениеi+1) | |
выражение10 | -> | \ такой-как-образец1 ... такой-как-образецn -> выражение | (лямбда-абстракция, n>=1) |
| | let списки-объявлений in выражение | (let-выражение) | |
| | if выражение then выражение else выражение | (условное выражение) | |
| | case выражение of { список-альтернатив } | (case-выражение) | |
| | do { список-инструкций } | (do-выражение) | |
| | функциональное-выражение | ||
функциональное-выражение | -> | [функциональное-выражение] выражение-аргумента | (применение функции) |
aexp | -> | qvar | (переменная) |
| | gcon | (общий конструктор) | |
| | literal | ||
| | ( 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) |
Перевод: | |||
выражение-аргумента | -> | квалифицированная-переменная | (переменная) |
| | общий-конструктор | (общий конструктор) | |
| | литерал | ||
| | ( выражение ) | (выражение в скобках) | |
| | ( выражение1 , ... , выражениеk ) | (кортеж, k>=2) | |
| | [ выражение1 , ... , выражениеk ] | (список, k>=1) | |
| | [ выражение1 [, выражение2] .. [выражение3] ] | (арифметическая последовательность) | |
| | [ выражение | квалификатор1 , ... , квалификаторn ] | (описание списка, n>=1) | |
| | ( выражениеi+1 квалифицированный-оператор(a,i) ) | (левое сечение) | |
| | ( левое-сечение-выраженияi квалифицированный-оператор(l,i) ) | (левое сечение) | |
| | ( квалифицированный-оператор(a,i)<-> выражениеi+1 ) | (правое сечение) | |
| | ( квалифицированный-оператор(r,i)<-> правое-сечение-выраженияi ) | (правое сечение) | |
| | квалифицированный-конструктор { связывание-имени-поля1 , ... , связывание-имени-поляn } | (именованная конструкция, n>=0) | |
| | выражение-аргумента<квалифицированный-конструктор> { связывание-имени-поля1 , ... , связывание-имени-поляn } | (именованное обновление, n>=1) |
qual | -> | pat <- exp | (генератор) |
| | let decls | (локальное объявление) | |
| | exp | (страж) | |
alts | -> | alt1 ; ... ; altn | (n>=1) |
alt | -> | pat -> exp [where decls] | |
| | pat gdpat [where decls] | ||
| | (пустая альтернатива) | ||
gdpat | -> | gd -> exp [ gdpat ] | |
stmts | -> | stmt1 ... stmtn exp [;] | (n>=0) |
stmt | -> | exp ; | |
| | pat <- exp ; | ||
| | let decls ; | ||
| | ; | (пустая инструкция) | |
fbind | -> | qvar = exp | |
Перевод: | |||
квалификатор | -> | образец <- выражение | (генератор) |
| | let списки-объявлений | (локальное объявление) | |
| | выражение | (страж) | |
список-альтернатив | -> | альтернатива1 ; ... ; альтернативаn | (n>=1) |
альтернатива | -> | образец -> выражение [where список-объявлений] | |
| | образец образец-со-стражами [where список-объявлений] | ||
| | (пустая альтернатива) | ||
образец-со-стражами | -> | страж -> выражение [ образец-со-стражами ] | |
список-инструкций | -> | инструкция1 ... инструкцияn выражение [;] | (n>=0) |
инструкция | -> | выражение ; | |
| | образец <- выражение ; | ||
| | let список-объявлений ; | ||
| | ; | (пустая инструкция) | |
связывание-имени-поля | -> | квалифицированная-переменная = выражение |
pat | -> | var + integer | (образец упорядочивания) |
| | pat0 | ||
pati | -> | pati+1 [qconop(n,i) pati+1] | |
| | lpati | ||
| | rpati | ||
lpati | -> | (lpati | pati+1) qconop(l,i) pati+1 | |
lpat6 | -> | - (integer | float) | (отрицательный литерал) |
rpati | -> | pati+1 qconop(r,i) (rpati | pati+1) | |
pat10 | -> | apat | |
| | gcon apat1 ... apatk | (число аргументов конструктора gcon = k, k>=1) |
Перевод: | |||
образец | -> | переменная + целый-литерал | (образец упорядочивания) |
| | образец0 | ||
образецi | -> | образецi+1 [квалифицированный-оператор-конструктора(n,i) образецi+1] | |
| | левый-образецi | ||
| | правый-образецi | ||
левый-образецi | -> | (левый-образецi | образецi+1) квалифицированный-оператор-конструктора(l,i) образецi+1 | |
левый-образец6 | -> | - (целый-литерал | литерал-с-плавающей-точкой) | (отрицательный литерал) |
правый-образецi | -> | образецi+1 квалифицированный-оператор-конструктора(r,i) (правый-образецi | образецi+1) | |
образец10 | -> | такой-как-образец | |
| | общий-конструктор такой-как-образец1 ... такой-как-образецk | (число аргументов конструктора gcon = k, k>=1) |
apat | -> | var [@ apat] | ("такой как"-образец) |
| | gcon | (число аргументов конструктора gcon = 0) | |
| | qcon { fpat1 , ... , fpatk } | (именованный образец, k>=0) | |
| | literal | ||
| | _ | (любые символы) | |
| | ( pat ) | (образец в скобках) | |
| | ( pat1 , ... , patk ) | (образец кортежа, k>=2) | |
| | [ pat1 , ... , patk ] | (образец списка, k>=1) | |
| | ~ apat | (неопровержимый образец) | |
fpat | -> | qvar = pat |
Перевод: | |||
такой-как-образец | -> | переменная [@ такой-как-образец] | ("такой как"-образец) |
| | общий-конструктор | (число аргументов конструктора gcon = 0) | |
| | квалифицированный-конструктор { образец-с-именем1 , ... , образец-с-именемk } | (именованный образец, k>=0) | |
| | литерал | ||
| | _ | (любые символы) | |
| | ( образец ) | (образец в скобках) | |
| | ( образец1 , ... , образецk ) | (образец кортежа, k>=2) | |
| | [ образец1 , ... , образецk ] | (образец списка, k>=1) | |
| | ~ такой-как-образец | (неопровержимый образец) | |
образец-с-именем | -> | квалифицированная-переменная = образец |
gcon | -> | () | |
| | [] | ||
| | (,{,}) | ||
| | qcon | ||
var | -> | varid | ( varsym ) | (переменная) |
qvar | -> | qvarid | ( qvarsym ) | (квалифицированная переменная) |
con | -> | conid | ( consym ) | (конструктор) |
qcon | -> | qconid | ( gconsym ) | (квалифицированный конструктор) |
varop | -> | varsym | `varid ` | (оператор переменной) |
qvarop | -> | qvarsym | `qvarid ` | (квалифицированный оператор переменной) |
conop | -> | consym | `conid ` | (оператор конструктора) |
qconop | -> | gconsym | `qconid ` | (квалифицированный оператор конструктора) |
op | -> | varop | conop | (оператор) |
qop | -> | qvarop | qconop | (квалифицированный оператор) |
gconsym | -> | : | qconsym |
Перевод: | |||
общий-конструктор | -> | () | |
| | [] | ||
| | (,{,}) | ||
| | квалифицированный-конструктор | ||
переменная | -> | идентификатор-переменной | ( символ-переменной ) | (переменная) |
квалифицированная-переменная | -> | квалифицированный-идентификатор-переменной | ( квалифицированный-символ-переменной ) | (квалифицированная переменная) |
конструктор | -> | идентификатор-конструктора | ( символ-конструктора ) | (конструктор) |
квалифицированный-конструктор | -> | квалифицированный-идентификатор-конструктора | ( символ-общего-конструктора ) | (квалифицированный конструктор) |
оператор-переменной | -> | символ-переменной | `идентификатор-переменной ` | (оператор переменной) |
квалифицированный-оператор-переменной | -> | квалифицированный-символ-переменной | `квалифицированный-идентификатор-переменной ` | (квалифицированный оператор переменной) |
оператор-конструктора | -> | символ-конструктора | `идентификатор-конструктора ` | (оператор конструктора) |
квалифицированный-оператор-конструктора | -> | символ-общего-конструктора | `квалифицированный-идентификатор-конструктора ` | (квалифицированный оператор конструктора) |
оператор | -> | оператор-переменной | оператор-конструктора | (оператор) |
квалифицированный-оператор | -> | квалифицированный-оператор-переменной | квалифицированный-оператор-конструктора | (квалифицированный оператор) |
символ-общего-конструктора | -> | : | квалифицированный-символ-конструктора |