Приложение A: Грамматика
Это приложение — плотный справочник. Для изучения языка читайте книгу, начиная с Предисловия.
Лексические элементы
Комментарии
// однострочный
/* многострочный комментарий */Идентификаторы
identifier = letter (letter | digit | "_")*stable_id = "#" alphanumeric+qualified_name = identifier ("." identifier)*quoted_string = '"' (any_char - '"' | '\"')* '"'Зарезервированные ключевые слова (файлы .arch)
type, in,labels, required, cascade, append,override, drop, subscribes,process, view, subprocess, do,if, else, switch, each, try, catch,parallel, fail, finish,focus, group, by, layout, include, exclude,true, falseЗарезервированные ключевые слова (только в файлах package.archspace)
use, from, as, export, dependenciesname, version и widgets распознаются как имена полей в грамматике манифеста, но не являются зарезервированными словами — они нигде не затеняют идентификаторы.
Виды не являются ключевыми словами
Виды модулей (service, database, system, …), виды фасетов и виды интерфейсов (command, query, event, …) не являются зарезервированными ключевыми словами — это пользовательские идентификаторы, вводимые декларациями type module …, type facet …, type interface ….
Базовые виды. module, facet, interface — предзарегистрированные базовые виды; это идентификаторы, не ключевые слова. process и view — предзарегистрированные базовые виды и зарезервированные ключевые слова, потому что их тела имеют специализированные грамматические правила.
Операторы и пунктуация
{ } ( ) [ ] : , . > =>Стрелка процесса — > (одиночный «больше»). Фрагменты грамматики ниже это отражают.
Грамматика (EBNF)
Верхний уровень
program = declaration* ;
declaration = type_decl | module_decl | process_decl | view_decl | subprocess_decl ;Декларации типов
type_decl = "export"? "type" stable_id? parent_kind identifier type_body? ;
parent_kind = identifier ; (* валидатор отвергает 'process' и 'view' *)
type_body = "{" type_member* "}" ;
type_member = type_field_decl | type_label_block | type_subdecl ;
type_field_decl = field_modifier* ( "required" field_path | field_path ":" value ) ;
field_modifier = "cascade" | "append" ;
field_path = identifier ("." identifier)* ;
type_label_block = "labels" "{" type_label_member* "}" ;
type_label_member = ( "required" identifier ("." identifier)* | identifier ("." identifier)* ":" value | drop_stmt ) ;
type_subdecl = "required"? ( facet_decl | interface_decl | module_decl ) ;
value = identifier | quoted_string | number | "true" | "false" ;Декларации модулей
module_decl = kind_name stable_id? identifier in_clause? module_body? ;
kind_name = identifier ; (* зарегистрированный вид модуля *)
in_clause = "in" qualified_name ;
module_body = "{" module_member* "}" ;
module_member = field_assignment | description | labels_block | facet_decl | interface_decl | module_decl (* вложенные подмодули *) | process_decl (* процесс, привязанный к модулю *) | subprocess_decl (* переиспользуемый помощник *) | drop_stmt | override_decl ;
description = quoted_string ;
field_assignment = field_path ":" value ;
labels_block = "labels" "{" label_entry* "}" ;
label_entry = label_key ":" value | "drop" label_key ;
label_key = identifier ("." identifier)* ;
drop_stmt = "drop" qualified_name ;
override_decl = "override" ( facet_decl | interface_decl | module_decl ) ;Декларации фасетов
facet_decl = facet_kind identifier facet_body? ;
facet_kind = "facet" | identifier ; (* "facet" или пользовательский *)
facet_body = "{" facet_member* "}" ;
facet_member = field_assignment | description | labels_block | facet_decl (* вложенные фасеты *) | interface_decl | drop_stmt | override_decl ;Декларации интерфейсов
interface_decl = kind_name identifier interface_body? ;
kind_name = identifier ; (* зарегистрированный вид интерфейса *)
interface_body = "{" interface_member* "}" ;
interface_member = field_assignment | description | labels_block | subscription | drop_stmt ;
subscription = "subscribes" ":" qualified_name ;Декларации процессов
process_decl = "process" stable_id? identifier in_clause? "{" process_body "}" ;
process_body = process_member* ;
process_member = process_step | description | subprocess_decl ;
process_step = step_simple | step_if | step_switch | step_parallel | step_each | step_try | step_do | step_fail | step_finish ;
step_simple = module_ref ">" interface_ref step_label? ;
module_ref = qualified_name ; (* разрешается в модуль или актор *)interface_ref = qualified_name ; (* разрешается в лист-интерфейс *)
step_label = ":" quoted_string ;
step_if = "if" condition step_body ("else" "if" condition step_body)* ("else" step_body)? ;condition = identifier | quoted_string ;
step_switch = "switch" condition? "{" switch_case+ "}" ;switch_case = case_label step_body ;case_label = identifier | quoted_string ;
step_parallel = "parallel" "{" parallel_branch+ "}" ;parallel_branch = ":" process_step | "{" process_step* "}" ;
step_each = "each" identifier "in" qualified_name step_body ;
step_try = "try" step_body ("catch" catch_label? step_body)* ;catch_label = identifier | quoted_string ;
step_body = "{" process_step* "}" | ":" process_step ;
step_do = "do" identifier arg_list? ;arg_list = "(" arg ("," arg)* ")" ;arg = identifier | quoted_string ;
step_fail = "fail" quoted_string? ;step_finish = "finish" quoted_string? ;
subprocess_decl = "subprocess" stable_id? identifier param_list? "{" process_body "}" ;param_list = "(" identifier ("," identifier)* ")" ;Декларации проекций
view_decl = "view" stable_id? identifier "{" view_body "}" ;
view_body = view_member* ;
view_member = view_focus | view_group | view_layout | view_include | view_exclude | description ;
view_focus = "focus" label_key ":" value ;view_group = "group" "by" label_key ;view_layout = "layout" ("elk" | "dagre" | "force" | "manual") ;view_include = "include" pattern_list ;view_exclude = "exclude" pattern_list ;
pattern_list = quoted_string ("," quoted_string)* ;Грамматика package.archspace
manifest = manifest_field* ;
manifest_field = name_field | version_field | widgets_field | dependencies_block | use_decl ;
name_field = "name" ":" dotted_name ;version_field = "version" ":" quoted_string ;widgets_field = "widgets" ":" quoted_string ;
dependencies_block = "dependencies" "{" dep_entry* "}" ;dep_entry = dotted_name ":" quoted_string ","? ;
use_decl = "export"? "use" use_targets "from" dotted_name ;use_targets = "*" | use_import ("," use_import)* ;use_import = identifier ("as" identifier)? ;
dotted_name = identifier ("." identifier)+ ;Расширение файла
.arch для исходных файлов. package.archspace для манифеста.
Кодировка
UTF-8.
Пробельные символы
Синтаксически не значимы вне строк в кавычках и комментариев. Отступы рекомендованы для читаемости; стандартная библиотека использует 4 пробела.
Многострочные строки
Строка в кавычках может занимать несколько строк. Лексер автоматически снимает отступ: ведущая строка из одних пробелов и минимальный общий отступ на остальных строках срезаются. Распознаётся только одно экранирование: \".
Строки в тройных кавычках ("""…""") — сырые: без экранирований, без интерполяции.
См. также
- Приложение B: Ключевые слова — что делает каждое зарезервированное слово
- Приложение C: Виды стандартной библиотеки — встроенные виды модулей и интерфейсов
- Глава 1: Установка — для начала работы