OR-1 dataflow CPU sketch
1%YAML 1.2
2---
3# dfasm.sublime-syntax — Context-aware syntax highlighting for Sublime Text
4# Version: 2 (Sublime Text 4)
5#
6# Architecture: Context stacks distinguish port numbers from literal numbers
7# using contextual scoping. All scopes suffixed with .dfasm per design spec.
8#
9# Scope mapping:
10# - Port numbers (in qualified refs): constant.numeric.port.dfasm
11# - Literal numbers (in arguments): constant.numeric.dfasm
12# - Named arg keys (dest=): variable.parameter.dfasm
13# - Opcodes: keyword.other.opcode.dfasm
14#
15# Reference: dfasm.lark grammar, asm/opcodes.py, design plan lines 156-185
16
17name: dfasm
18file_extensions:
19 - dfasm
20scope: source.dfasm
21
22variables:
23 identifier: '[a-zA-Z_][a-zA-Z0-9_]*'
24 hex_lit: '0x[0-9a-fA-F]+'
25 dec_lit: '[0-9]+'
26 opcodes: 'add|sub|inc|dec|shiftl|shiftr|ashiftr|and|or|xor|not|eq|lt|lte|gt|gte|breq|brgt|brge|brof|brty|sweq|swgt|swge|swof|swty|gate|sel|merge|pass|const|free_ctx|read|write|clear|alloc|free|rd_inc|rd_dec|cmp_sw|ior|iow|iorw|load_inst|change_tag|extract_tag|exec'
27
28contexts:
29 main:
30 - match: ';.*$'
31 scope: comment.line.semicolon.dfasm
32
33 - match: '@system\b'
34 scope: keyword.control.pragma.dfasm
35 push: pragma_params
36
37 # Flow operators must be matched before | and < separately
38 # to avoid sregex matching issues with lookbehinds
39 - match: '\|>'
40 scope: keyword.operator.flow.out.dfasm
41
42 - match: '<\|'
43 scope: keyword.operator.flow.in.dfasm
44
45 # Opcodes
46 - match: '\b(?:{{opcodes}})\b'
47 scope: keyword.other.opcode.dfasm
48
49 # Sigils push into qualified_ref contexts
50 - match: '@'
51 scope: punctuation.definition.reference.node.dfasm
52 push: qualified_ref_node_name
53
54 - match: '&'
55 scope: punctuation.definition.reference.label.dfasm
56 push: qualified_ref_label_name
57
58 - match: '\$'
59 scope: punctuation.definition.reference.function.dfasm
60 push: qualified_ref_func_name
61
62 # Macro call: #name
63 - match: '(#)({{identifier}})'
64 captures:
65 1: punctuation.definition.macro.dfasm
66 2: entity.name.function.macro.dfasm
67
68 # Strings with prefixes
69 - match: 'r"'
70 scope: storage.type.string.dfasm
71 push: raw_string
72
73 - match: 'b"'
74 scope: storage.type.string.dfasm
75 push: byte_string
76
77 - match: '"'
78 scope: string.quoted.double.dfasm
79 push: string
80
81 # Character literal
82 - match: "'"
83 scope: string.quoted.single.dfasm
84 push: char_literal
85
86 # Numbers (not in port context)
87 - match: '{{hex_lit}}'
88 scope: constant.numeric.dfasm
89
90 - match: '{{dec_lit}}'
91 scope: constant.numeric.dfasm
92
93 # Named arguments: identifier=value (AC4.4)
94 - match: '({{identifier}})(=)'
95 captures:
96 1: variable.parameter.dfasm
97 2: keyword.operator.assignment.dfasm
98
99 # Assignment operator
100 - match: '='
101 scope: keyword.operator.assignment.dfasm
102
103 # Comma
104 - match: ','
105 scope: punctuation.separator.dfasm
106
107 # Braces for function bodies
108 - match: '\{'
109 scope: punctuation.section.block.dfasm
110 push: func_body
111
112 - match: '\}'
113 scope: punctuation.section.block.dfasm
114
115 # Placement separator (must come after |>)
116 - match: '\|(?!>)'
117 scope: punctuation.separator.placement.dfasm
118
119 # Colon separator (in port specs, but only matched if not in qualified_ref)
120 - match: ':'
121 scope: punctuation.separator.port.dfasm
122
123 # Whitespace
124 - match: '\s+'
125
126 # === Qualified Reference Contexts ===
127 # Separate contexts per sigil to enforce scope mapping
128
129 qualified_ref_node_name:
130 - match: '{{identifier}}'
131 scope: entity.name.tag.dfasm
132 set: qualified_ref_suffix
133 - match: '(?=\S)'
134 pop: true
135
136 qualified_ref_label_name:
137 - match: '{{identifier}}'
138 scope: entity.name.label.dfasm
139 set: qualified_ref_suffix
140 - match: '(?=\S)'
141 pop: true
142
143 qualified_ref_func_name:
144 - match: '{{identifier}}'
145 scope: entity.name.function.dfasm
146 set: qualified_ref_suffix
147 - match: '(?=\S)'
148 pop: true
149
150 qualified_ref_suffix:
151 # Placement: | not followed by >
152 - match: '\|(?!>)'
153 scope: punctuation.separator.placement.dfasm
154 set: placement_name
155
156 # Port: : followed by number or identifier
157 - match: ':'
158 scope: punctuation.separator.port.dfasm
159 set: port_spec
160
161 # No suffix, pop back to main
162 - match: ''
163 pop: true
164
165 placement_name:
166 - match: '{{identifier}}'
167 scope: entity.other.attribute-name.placement.dfasm
168 set: qualified_ref_suffix_after_placement
169 - match: '(?=\S)'
170 pop: true
171
172 qualified_ref_suffix_after_placement:
173 # Port after placement
174 - match: ':'
175 scope: punctuation.separator.port.dfasm
176 set: port_spec
177
178 # No port, pop
179 - match: ''
180 pop: true
181
182 port_spec:
183 # Port identifier (L, R, etc.)
184 - match: '{{identifier}}'
185 scope: entity.other.attribute-name.port.dfasm
186 pop: true
187
188 # Hex number in port position gets constant.numeric.port.dfasm
189 - match: '{{hex_lit}}'
190 scope: constant.numeric.port.dfasm
191 pop: true
192
193 # Decimal number in port position gets constant.numeric.port.dfasm
194 - match: '{{dec_lit}}'
195 scope: constant.numeric.port.dfasm
196 pop: true
197
198 # No valid port spec, pop
199 - match: ''
200 pop: true
201
202 # === Function Body ===
203 func_body:
204 - meta_scope: meta.function.body.dfasm
205
206 - match: '\}'
207 scope: punctuation.section.block.dfasm
208 pop: true
209
210 # Include main context rules inside function body (AC4.5)
211 - include: main
212
213 # === Pragma Parameters ===
214 pragma_params:
215 # param=value pairs
216 - match: '({{identifier}})(=)({{hex_lit}}|{{dec_lit}})'
217 captures:
218 1: variable.parameter.dfasm
219 2: keyword.operator.assignment.dfasm
220 3: constant.numeric.dfasm
221
222 - match: ','
223 scope: punctuation.separator.dfasm
224
225 - match: '(?=;)'
226 pop: true
227
228 - match: '$'
229 pop: true
230
231 - match: '\s+'
232
233 # === String Contexts ===
234 string:
235 - meta_scope: string.quoted.double.dfasm
236
237 - match: '"'
238 scope: string.quoted.double.dfasm
239 pop: true
240
241 - match: "\\\\[ntr0\\\\'\"]"
242 scope: constant.character.escape.dfasm
243
244 - match: '\\x[0-9a-fA-F]{2}'
245 scope: constant.character.escape.dfasm
246
247 - match: '\\'
248 scope: constant.character.escape.dfasm
249
250 raw_string:
251 - meta_scope: string.quoted.double.raw.dfasm
252
253 - match: '"'
254 scope: string.quoted.double.raw.dfasm
255 pop: true
256
257 byte_string:
258 - meta_scope: string.quoted.double.byte.dfasm
259
260 - match: '"'
261 scope: string.quoted.double.byte.dfasm
262 pop: true
263
264 - match: "\\\\[ntr0\\\\'\"]"
265 scope: constant.character.escape.dfasm
266
267 - match: '\\x[0-9a-fA-F]{2}'
268 scope: constant.character.escape.dfasm
269
270 - match: '\\'
271 scope: constant.character.escape.dfasm
272
273 char_literal:
274 - meta_scope: string.quoted.single.dfasm
275
276 - match: "'"
277 scope: string.quoted.single.dfasm
278 pop: true
279
280 - match: "\\\\[ntr0\\\\'\"]"
281 scope: constant.character.escape.dfasm
282
283 - match: '\\x[0-9a-fA-F]{2}'
284 scope: constant.character.escape.dfasm
285
286 - match: '\\'
287 scope: constant.character.escape.dfasm