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