StrictDoc Documentation
strictdoc/backend/sdoc/grammar/grammar.py
Source file coverage
Path:
strictdoc/backend/sdoc/grammar/grammar.py
Lines:
237
Non-empty lines:
198
Non-empty lines covered with requirements:
198 / 198 (100.0%)
Functions:
0
Functions covered by requirements:
0 / 0 (0.0%)
1
"""
2
@relation(SDOC-SRS-19, SDOC-SRS-127, SDOC-SRS-20, SDOC-SRS-23, SDOC-SRS-145, scope=file)
3
"""
4
 
5
# FIXME: Extract this to a file with a shared set of global constants.
6
# @relation(SDOC-SRS-22, scope=line)
7
REGEX_UID = r"([\w]+[\w()\-\/.: ]*)"
8
REGEX_FIELD_NAME = r"[A-Z]+[A-Za-z0-9_\-]*"
9
 
10
NEGATIVE_MULTILINE_STRING_START = "(?!>>>\n)"
11
NEGATIVE_MULTILINE_STRING_END = "(?!^<<<)"
12
NEGATIVE_RELATIONS = "(?!^RELATIONS)"
13
NEGATIVE_UID = "(?!^UID)"
14
NEGATIVE_INLINE_LINK_START = rf"(?!\[LINK: {REGEX_UID})"
15
NEGATIVE_ANCHOR_START = rf"(?!^\[ANCHOR: {REGEX_UID})"
16
 
17
TEXT_TYPES_GRAMMAR = rf"""
18
TextPart[noskipws]:
19
  (Anchor | InlineLink | NormalString)
20
;
21
 
22
SingleLineTextPart[noskipws]:
23
  (Anchor | InlineLink | /{NEGATIVE_MULTILINE_STRING_START}\S.*/)
24
;
25
 
26
NormalString[noskipws]:
27
  (/(?ms){NEGATIVE_MULTILINE_STRING_END}{NEGATIVE_INLINE_LINK_START}{NEGATIVE_ANCHOR_START}./)+
28
;
29
 
30
InlineLink[noskipws]:
31
  '[LINK: ' value = /{REGEX_UID}/ ']'
32
;
33
 
34
Anchor[noskipws]:
35
  /^\[ANCHOR: /
36
  value = /{REGEX_UID}/ (', ' title = /\w+[\s\w+]*/)?
37
  /\](\Z|\n)/
38
;
39
 
40
// According to the Strict Grammar Rule #3, both SingleLineString and
41
// MultiLineString can never be empty strings.
42
// Both must eventualy start with a non-space character.
43
SingleLineString:
44
  /{NEGATIVE_MULTILINE_STRING_START}\S.*$/
45
;
46
 
47
MultiLineString[noskipws]:
48
  />>>\n/-
49
    parts*=TextPart
50
  /^<<</-
51
;
52
 
53
FieldName[noskipws]:
54
  /{NEGATIVE_UID}{NEGATIVE_RELATIONS}{REGEX_FIELD_NAME}/
55
;
56
"""
57
 
58
FREE_TEXT_PARSER_GRAMMAR = r"""
59
FreeTextContainer[noskipws]:
60
  parts*=TextPart
61
;
62
"""
63
 
64
DOCUMENT_GRAMMAR = rf"""
65
SDocDocument[noskipws]:
66
  '[DOCUMENT]' '\n'
67
  ('MID: ' mid = SingleLineString '\n')?
68
  'TITLE: ' title = SingleLineString '\n'
69
  (config = DocumentConfig)?
70
  (view = DocumentView)?
71
  ('\n' grammar = DocumentGrammar)?
72
  section_contents *= SectionOrRequirement
73
;
74
 
75
DocumentConfig[noskipws]:
76
  ('UID: ' uid = /{REGEX_UID}/ '\n')?
77
  ('VERSION: ' version = SingleLineString '\n')?
78
  ('DATE: ' date = SingleLineString '\n')?
79
  ('CLASSIFICATION: ' classification = SingleLineString '\n')?
80
  (/(REQ_)?PREFIX/ ': ' requirement_prefix = SingleLineString '\n')?
81
  ('ROOT: ' (root = BooleanChoice) '\n')?
82
  ('OPTIONS:' '\n'
83
    ('  ENABLE_MID: ' (enable_mid = BooleanChoice) '\n')?
84
    ('  RELATION_FIELD: ' (relation_field = SingleLineString) '\n')?
85
    ('  MARKUP: ' (markup = MarkupChoice) '\n')?
86
    ('  AUTO_LEVELS: ' (auto_levels = AutoLevelsChoice) '\n')?
87
    ('  LAYOUT: ' (layout = LayoutChoice) '\n')?
88
    ('  ' view_style_tag = /(VIEW_STYLE|REQUIREMENT_STYLE)/ ': '
89
        (requirement_style = RequirementStyleChoice) '\n')?
90
    ('  ' node_in_toc_tag = /(NODE_IN_TOC|REQUIREMENT_IN_TOC)/ ': '
91
        (requirement_in_toc = RequirementHasTitleChoice) '\n'
92
    )?
93
    ('  DEFAULT_VIEW: ' default_view = SingleLineString '\n')?
94
  )?
95
  ('METADATA:' '\n' custom_metadata = DocumentCustomMetadata)?
96
;
97
 
98
DocumentView[noskipws]:
99
  'VIEWS:' '\n'
100
  views += ViewElement
101
;
102
 
103
ViewElement[noskipws]:
104
  '- ID: ' view_id = /{REGEX_UID}/ '\n'
105
  ('  NAME: ' name = SingleLineString '\n')?
106
  '  TAGS:' '\n'
107
  tags += ViewElementTags
108
  ('  HIDDEN_TAGS:' '\n'
109
  hidden_tags += ViewElementHiddenTag)?
110
;
111
 
112
ViewElementTags[noskipws]:
113
  '  - OBJECT_TYPE: ' object_type = SingleLineString '\n'
114
  '    VISIBLE_FIELDS:' '\n'
115
  visible_fields += ViewElementField
116
;
117
 
118
ViewElementField[noskipws]:
119
  '    - NAME: ' name = SingleLineString '\n'
120
  ('      PLACEMENT: ' placement = SingleLineString '\n')?
121
;
122
 
123
ViewElementHiddenTag[noskipws]:
124
  '  - ' hidden_tag = SingleLineString '\n'
125
;
126
 
127
MarkupChoice[noskipws]:
128
  'RST' | 'Text' | 'HTML' | 'Markdown'
129
;
130
 
131
RequirementStyleChoice[noskipws]:
132
  'Plain' | 'Inline' | 'Simple' | 'Narrative' | 'Table' | 'Zebra'
133
;
134
 
135
RequirementHasTitleChoice[noskipws]:
136
  'True' | 'False'
137
;
138
 
139
AutoLevelsChoice[noskipws]:
140
  'On' | 'Off'
141
;
142
 
143
LayoutChoice[noskipws]:
144
  'Default' | 'Website'
145
;
146
 
147
DocumentCustomMetadata[noskipws]:
148
  (entries+=DocumentCustomMetadataKeyValuePair)*
149
;
150
 
151
DocumentCustomMetadataKeyValuePair[noskipws]:
152
  '  ' key=DocumentCustomMetadataKey ': ' value=SingleLineString '\n'
153
;
154
 
155
DocumentCustomMetadataKey: /[a-zA-Z_][a-zA-Z0-9_-]*/;
156
 
157
"""
158
 
159
SECTION_GRAMMAR = rf"""
160
SDocSection[noskipws]:
161
  '[SECTION]'
162
  '\n'
163
  ('MID: ' mid = SingleLineString '\n')?
164
  ('UID: ' uid = /{REGEX_UID}/ '\n')?
165
  ('LEVEL: ' custom_level = SingleLineString '\n')?
166
  'TITLE: ' title = SingleLineString '\n'
167
  (/(REQ_)?PREFIX/ ': ' requirement_prefix = SingleLineString '\n')?
168
  section_contents *= SectionOrRequirement
169
  '\n'
170
  '[/SECTION]'
171
  '\n'
172
;
173
 
174
SectionOrRequirement[noskipws]:
175
  '\n' (SDocSection | SDocCompositeNode | SDocNode | DocumentFromFile)
176
;
177
 
178
DocumentFromFile[noskipws]:
179
  '[DOCUMENT_FROM_FILE]' '\n'
180
  'FILE: ' file = /.+$/ '\n'
181
;
182
 
183
ReservedKeyword[noskipws]:
184
  'DOCUMENT' | 'GRAMMAR' | 'SECTION' | 'DOCUMENT_FROM_FILE'
185
;
186
 
187
SDocNode[noskipws]:
188
  '[' !'SECTION' node_type = RequirementType ']' '\n'
189
  fields += SDocNodeField
190
  (
191
    'RELATIONS:' '\n'
192
    (relations += Reference)
193
  )?
194
;
195
 
196
SDocCompositeNode[noskipws]:
197
  '[[' node_type = RequirementType ']]' '\n'
198
 
199
  fields += SDocNodeField
200
  (
201
    'RELATIONS:' '\n'
202
    (relations += Reference)
203
  )?
204
 
205
  section_contents *= SectionOrRequirement
206
 
207
  '\n'
208
  '[[/' node_type_close = RequirementType ']]' '\n'
209
;
210
 
211
SDocNodeField[noskipws]:
212
  (
213
    field_name = 'MID' ': ' parts+=SingleLineString '\n'
214
    |
215
    field_name = 'UID' ': ' parts+=/{REGEX_UID}/ '\n'
216
    |
217
    field_name = FieldName ':'
218
    (
219
        (' ' parts+=SingleLineTextPart '\n')
220
        |
221
        (
222
          ' '
223
          (
224
            multiline__ = />>>\n/
225
            parts+=TextPart
226
            /^<<</
227
          )
228
          '\n'
229
        )
230
    )
231
  )
232
;
233
 
234
RequirementStatus[noskipws]:
235
  'Draft' | 'Active' | 'Deleted';
236
 
237
"""