@andrivet/z80-assembler 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.json +35 -0
  4. package/.github/workflows/node.js.yml +47 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc +3 -0
  7. package/.vscode/extensions.json +7 -0
  8. package/README.md +53 -27
  9. package/apps/.gitkeep +0 -0
  10. package/apps/z80-assembler-app/.eslintrc.json +18 -0
  11. package/apps/z80-assembler-app/index.html +16 -0
  12. package/apps/z80-assembler-app/postcss.config.js +24 -0
  13. package/apps/z80-assembler-app/project.json +70 -0
  14. package/apps/z80-assembler-app/public/favicon.ico +0 -0
  15. package/apps/z80-assembler-app/public/logo.png +0 -0
  16. package/apps/z80-assembler-app/public/logo192.png +0 -0
  17. package/apps/z80-assembler-app/public/logo512.png +0 -0
  18. package/apps/z80-assembler-app/public/manifest.json +25 -0
  19. package/apps/z80-assembler-app/public/robots.txt +3 -0
  20. package/apps/z80-assembler-app/src/app/app.module.css +0 -0
  21. package/apps/z80-assembler-app/src/app/app.tsx +122 -0
  22. package/apps/z80-assembler-app/src/app/binary.tsx +39 -0
  23. package/apps/z80-assembler-app/src/app/editor.tsx +228 -0
  24. package/apps/z80-assembler-app/src/app/errors.tsx +31 -0
  25. package/apps/z80-assembler-app/src/app/footer.tsx +20 -0
  26. package/apps/z80-assembler-app/src/app/header.tsx +57 -0
  27. package/apps/z80-assembler-app/src/app/misc.ts +13 -0
  28. package/apps/z80-assembler-app/src/app/opcodes.tsx +335 -0
  29. package/apps/z80-assembler-app/src/assets/.gitkeep +0 -0
  30. package/apps/z80-assembler-app/src/assets/images/logo192.png +0 -0
  31. package/apps/z80-assembler-app/src/main.tsx +22 -0
  32. package/apps/z80-assembler-app/src/styles.css +8 -0
  33. package/apps/z80-assembler-app/tailwind.config.js +28 -0
  34. package/apps/z80-assembler-app/tsconfig.app.json +22 -0
  35. package/apps/z80-assembler-app/tsconfig.json +21 -0
  36. package/apps/z80-assembler-app/tsconfig.spec.json +23 -0
  37. package/apps/z80-assembler-app/vite.config.ts +64 -0
  38. package/assets/images/compile.png +0 -0
  39. package/assets/images/logo.png +0 -0
  40. package/assets/images/menu.png +0 -0
  41. package/assets/images/opcodes-load8.png +0 -0
  42. package/assets/images/opcodes.png +0 -0
  43. package/assets/images/open-dir.png +0 -0
  44. package/assets/images/z80-assembler-app.png +0 -0
  45. package/docs/assembly.md +551 -0
  46. package/docs/images/ZX81-0x00.png +0 -0
  47. package/docs/images/ZX81-0x0B.png +0 -0
  48. package/docs/images/ZX81-0x0C.png +0 -0
  49. package/docs/images/ZX81-0x0D.png +0 -0
  50. package/docs/images/ZX81-0x0E.png +0 -0
  51. package/docs/images/ZX81-0x0F.png +0 -0
  52. package/docs/images/ZX81-0x10.png +0 -0
  53. package/docs/images/ZX81-0x11.png +0 -0
  54. package/docs/images/ZX81-0x12.png +0 -0
  55. package/docs/images/ZX81-0x13.png +0 -0
  56. package/docs/images/ZX81-0x14.png +0 -0
  57. package/docs/images/ZX81-0x15.png +0 -0
  58. package/docs/images/ZX81-0x16.png +0 -0
  59. package/docs/images/ZX81-0x17.png +0 -0
  60. package/docs/images/ZX81-0x18.png +0 -0
  61. package/docs/images/ZX81-0x19.png +0 -0
  62. package/docs/images/ZX81-0x1A.png +0 -0
  63. package/docs/images/ZX81-0x1B.png +0 -0
  64. package/docs/images/ZX81-0x1C.png +0 -0
  65. package/docs/images/ZX81-0x1D.png +0 -0
  66. package/docs/images/ZX81-0x1E.png +0 -0
  67. package/docs/images/ZX81-0x1F.png +0 -0
  68. package/docs/images/ZX81-0x20.png +0 -0
  69. package/docs/images/ZX81-0x21.png +0 -0
  70. package/docs/images/ZX81-0x22.png +0 -0
  71. package/docs/images/ZX81-0x23.png +0 -0
  72. package/docs/images/ZX81-0x24.png +0 -0
  73. package/docs/images/ZX81-0x25.png +0 -0
  74. package/docs/images/ZX81-0x26.png +0 -0
  75. package/docs/images/ZX81-0x27.png +0 -0
  76. package/docs/images/ZX81-0x28.png +0 -0
  77. package/docs/images/ZX81-0x29.png +0 -0
  78. package/docs/images/ZX81-0x2A.png +0 -0
  79. package/docs/images/ZX81-0x2B.png +0 -0
  80. package/docs/images/ZX81-0x2C.png +0 -0
  81. package/docs/images/ZX81-0x2D.png +0 -0
  82. package/docs/images/ZX81-0x2E.png +0 -0
  83. package/docs/images/ZX81-0x2F.png +0 -0
  84. package/docs/images/ZX81-0x30.png +0 -0
  85. package/docs/images/ZX81-0x31.png +0 -0
  86. package/docs/images/ZX81-0x32.png +0 -0
  87. package/docs/images/ZX81-0x33.png +0 -0
  88. package/docs/images/ZX81-0x34.png +0 -0
  89. package/docs/images/ZX81-0x35.png +0 -0
  90. package/docs/images/ZX81-0x36.png +0 -0
  91. package/docs/images/ZX81-0x37.png +0 -0
  92. package/docs/images/ZX81-0x38.png +0 -0
  93. package/docs/images/ZX81-0x39.png +0 -0
  94. package/docs/images/ZX81-0x3A.png +0 -0
  95. package/docs/images/ZX81-0x3B.png +0 -0
  96. package/docs/images/ZX81-0x3C.png +0 -0
  97. package/docs/images/ZX81-0x3D.png +0 -0
  98. package/docs/images/ZX81-0x3E.png +0 -0
  99. package/docs/images/ZX81-0x3F.png +0 -0
  100. package/docs/images/ZX81-0x80.png +0 -0
  101. package/docs/images/ZX81-0x8B.png +0 -0
  102. package/docs/images/ZX81-0x8C.png +0 -0
  103. package/docs/images/ZX81-0x8D.png +0 -0
  104. package/docs/images/ZX81-0x8E.png +0 -0
  105. package/docs/images/ZX81-0x8F.png +0 -0
  106. package/docs/images/ZX81-0x90.png +0 -0
  107. package/docs/images/ZX81-0x91.png +0 -0
  108. package/docs/images/ZX81-0x92.png +0 -0
  109. package/docs/images/ZX81-0x93.png +0 -0
  110. package/docs/images/ZX81-0x94.png +0 -0
  111. package/docs/images/ZX81-0x95.png +0 -0
  112. package/docs/images/ZX81-0x96.png +0 -0
  113. package/docs/images/ZX81-0x97.png +0 -0
  114. package/docs/images/ZX81-0x98.png +0 -0
  115. package/docs/images/ZX81-0x99.png +0 -0
  116. package/docs/images/ZX81-0x9A.png +0 -0
  117. package/docs/images/ZX81-0x9B.png +0 -0
  118. package/docs/images/ZX81-0x9C.png +0 -0
  119. package/docs/images/ZX81-0x9D.png +0 -0
  120. package/docs/images/ZX81-0x9E.png +0 -0
  121. package/docs/images/ZX81-0x9F.png +0 -0
  122. package/docs/images/ZX81-0xA0.png +0 -0
  123. package/docs/images/ZX81-0xA1.png +0 -0
  124. package/docs/images/ZX81-0xA2.png +0 -0
  125. package/docs/images/ZX81-0xA3.png +0 -0
  126. package/docs/images/ZX81-0xA4.png +0 -0
  127. package/docs/images/ZX81-0xA5.png +0 -0
  128. package/docs/images/ZX81-0xA6.png +0 -0
  129. package/docs/images/ZX81-0xA7.png +0 -0
  130. package/docs/images/ZX81-0xA8.png +0 -0
  131. package/docs/images/ZX81-0xA9.png +0 -0
  132. package/docs/images/ZX81-0xAA.png +0 -0
  133. package/docs/images/ZX81-0xAB.png +0 -0
  134. package/docs/images/ZX81-0xAC.png +0 -0
  135. package/docs/images/ZX81-0xAD.png +0 -0
  136. package/docs/images/ZX81-0xAE.png +0 -0
  137. package/docs/images/ZX81-0xAF.png +0 -0
  138. package/docs/images/ZX81-0xB0.png +0 -0
  139. package/docs/images/ZX81-0xB1.png +0 -0
  140. package/docs/images/ZX81-0xB2.png +0 -0
  141. package/docs/images/ZX81-0xB3.png +0 -0
  142. package/docs/images/ZX81-0xB4.png +0 -0
  143. package/docs/images/ZX81-0xB5.png +0 -0
  144. package/docs/images/ZX81-0xB6.png +0 -0
  145. package/docs/images/ZX81-0xB7.png +0 -0
  146. package/docs/images/ZX81-0xB8.png +0 -0
  147. package/docs/images/ZX81-0xB9.png +0 -0
  148. package/docs/images/ZX81-0xBA.png +0 -0
  149. package/docs/images/ZX81-0xBB.png +0 -0
  150. package/docs/images/ZX81-0xBC.png +0 -0
  151. package/docs/images/ZX81-0xBD.png +0 -0
  152. package/docs/images/ZX81-0xBE.png +0 -0
  153. package/docs/images/ZX81-0xBF.png +0 -0
  154. package/libs/.gitkeep +0 -0
  155. package/libs/z80-assembler/.eslintrc.json +18 -0
  156. package/libs/z80-assembler/package.json +20 -0
  157. package/libs/z80-assembler/project.json +35 -0
  158. package/{CHANGELOG.md → libs/z80-assembler/public/CHANGELOG.md} +5 -1
  159. package/libs/z80-assembler/public/README.md +54 -0
  160. package/{index.d.ts → libs/z80-assembler/src/index.ts} +1 -1
  161. package/libs/z80-assembler/src/lib/assets/code/basic-end.zx81 +4 -0
  162. package/libs/z80-assembler/src/lib/assets/code/basic-line1.zx81 +4 -0
  163. package/libs/z80-assembler/src/lib/assets/code/basic-line2.zx81 +9 -0
  164. package/libs/z80-assembler/src/lib/assets/code/characters.zx81 +190 -0
  165. package/libs/z80-assembler/src/lib/assets/code/display.zx81 +50 -0
  166. package/libs/z80-assembler/src/lib/assets/code/system-variables.zx81 +46 -0
  167. package/{lib/compiler/Assets.d.ts → libs/z80-assembler/src/lib/compiler/Assets.ts} +6 -1
  168. package/libs/z80-assembler/src/lib/compiler/Ast.ts +545 -0
  169. package/libs/z80-assembler/src/lib/compiler/Compiler.test.ts +2141 -0
  170. package/libs/z80-assembler/src/lib/compiler/Compiler.ts +185 -0
  171. package/libs/z80-assembler/src/lib/compiler/Formatter.ts +43 -0
  172. package/libs/z80-assembler/src/lib/compiler/Generator.ts +255 -0
  173. package/libs/z80-assembler/src/lib/compiler/Labels.ts +165 -0
  174. package/libs/z80-assembler/src/lib/grammar/LowLevel.ts +163 -0
  175. package/libs/z80-assembler/src/lib/grammar/Parse.ts +128 -0
  176. package/libs/z80-assembler/src/lib/grammar/z80.peg +1252 -0
  177. package/libs/z80-assembler/src/lib/grammar/z80.ts +10649 -0
  178. package/libs/z80-assembler/src/lib/types/Error.ts +105 -0
  179. package/{lib/types/Types.d.ts → libs/z80-assembler/src/lib/types/Types.ts} +26 -11
  180. package/libs/z80-assembler/tsconfig.json +23 -0
  181. package/libs/z80-assembler/tsconfig.lib.json +10 -0
  182. package/libs/z80-assembler/tsconfig.spec.json +19 -0
  183. package/libs/z80-assembler/vite.config.ts +58 -0
  184. package/nx.json +57 -0
  185. package/package.json +52 -14
  186. package/tsconfig.base.json +22 -0
  187. package/index.js +0 -312
  188. package/index.mjs +0 -6441
  189. package/lib/compiler/Ast.d.ts +0 -210
  190. package/lib/compiler/Compiler.d.ts +0 -53
  191. package/lib/compiler/Formatter.d.ts +0 -23
  192. package/lib/compiler/Generator.d.ts +0 -40
  193. package/lib/compiler/Labels.d.ts +0 -47
  194. package/lib/grammar/LowLevel.d.ts +0 -68
  195. package/lib/grammar/Parse.d.ts +0 -48
  196. package/lib/grammar/z80.d.ts +0 -2938
  197. package/lib/types/Error.d.ts +0 -62
@@ -0,0 +1,1252 @@
1
+ ---
2
+ /**
3
+ * Z80 Assembler in Typescript
4
+ *
5
+ * File: z80.peg
6
+ * Description: PEG grammar of the Z80 assembly language
7
+ * Author: Sebastien Andrivet
8
+ * License: GPLv3
9
+ * Copyrights: Copyright (C) 2023 Sebastien Andrivet
10
+ */
11
+ import {
12
+ r_bits,
13
+ dd_bits,
14
+ qq_bits,
15
+ ss_bits,
16
+ pp_bits,
17
+ rr_bits,
18
+ cc_bits,
19
+ jj_bits,
20
+ p_bits,
21
+ imode
22
+ } from "./LowLevel";
23
+
24
+ import {
25
+ parseNumber,
26
+ parseZX81Char,
27
+ parseSimpleEscape,
28
+ parseOctalEscape,
29
+ parseHexadecimalEscape} from './Parse';
30
+ import {LinesInfo, Address} from '../types/Types';
31
+
32
+ import {
33
+ EvalFunc,
34
+ AstElements,
35
+ binaryOperation,
36
+ binaryOperations,
37
+ unaryOperation,
38
+ unaryOperations,
39
+ operatorOr,
40
+ operatorXor,
41
+ operatorAnd,
42
+ operatorLeftShift,
43
+ operatorRightShift,
44
+ operatorAdd,
45
+ operatorSub,
46
+ operatorMul,
47
+ operatorDiv,
48
+ operatorModulo,
49
+ operatorPlus,
50
+ operatorNeg,
51
+ operatorInvert,
52
+ operatorIdentity,
53
+ value16LE,
54
+ value8,
55
+ index,
56
+ jrOffset,
57
+ jrRelativeOffset,
58
+ dataBytes,
59
+ dataWords,
60
+ dataBlock,
61
+ labelValue,
62
+ value
63
+ } from '../compiler/Ast';
64
+
65
+ import {setOutputName, setDevice, includeFile} from '../compiler/Compiler';
66
+ ---
67
+
68
+ // Start (top level symbol) of the grammar
69
+ start := lines=Lines $ // Les followed by the end of the code
70
+
71
+ // Names of the registers for the different opcodes (the names are from the Z80 CPU User Manual)
72
+ r := 'a' | 'b' | 'c' | 'd' | 'e' | 'h' | 'l'
73
+ dd := 'bc' | 'de' | 'hl' | 'sp'
74
+ ss := dd
75
+ qq := 'bc' | 'de' | 'hl' | 'af'
76
+ pp := 'bc' | 'de' | 'ix' | 'sp'
77
+ rr := 'bc' | 'de' | 'iy' | 'sp'
78
+
79
+ // 8-bit values
80
+ // Note: binary is before hexadecimal because 0b is ambiguous
81
+ n :=
82
+ pos=@ binary=binary .value = number { return parseNumber(pos, binary.raw, 2, 1); } |
83
+ pos=@ hexadecimal=hexadecimal .value = number { return parseNumber(pos, hexadecimal.raw, 16, 1); } |
84
+ pos=@ octal=octal .value = number { return parseNumber(pos, octal.raw, 8, 1); } |
85
+ pos=@ decimal=decimal .value = number { return parseNumber(pos, decimal.raw, 10, 1); }
86
+
87
+ // 16-bit values
88
+ // Note: binary is before hexadecimal because 0b is ambiguous
89
+ nn :=
90
+ pos=@ binary=binary .value = number { return parseNumber(pos, binary.raw, 2, 2); } |
91
+ pos=@ hexadecimal=hexadecimal .value = number { return parseNumber(pos, hexadecimal.raw, 16, 2); } |
92
+ pos=@ octal=octal .value = number { return parseNumber(pos, octal.raw, 8, 2); } |
93
+ pos=@ decimal=decimal .value = number { return parseNumber(pos, decimal.raw, 10, 2); }
94
+
95
+ // A decimal unsigned value with the different allowed syntaxes
96
+ decimal :=
97
+ raw='[0-9]+' 'd'?
98
+
99
+ // A binary value with the different allowed syntaxes
100
+ binary :=
101
+ {'0b' | '%'} raw='[0-1]+' |
102
+ raw='[0-1]+' 'b'
103
+
104
+ // An octal value with the different allowed syntaxes
105
+ octal :=
106
+ {'0q' | '0o' | '@'} raw='[0-7]+' |
107
+ raw='[0-7]+' {'q' | 'o'}
108
+
109
+ // An hexadecimal value with the different allowed syntaxes
110
+ // To avoid ambiguity, hexadecimal values are not allowed to be followed by an alphanumerical character
111
+ hexadecimal :=
112
+ {'0x' | '\$' | '#'} raw='[0-9a-f]+' |
113
+ raw='[0-9a-f]+' 'h' !'[0-9a-z]'
114
+
115
+ // Different names used in the Z80 CPU User Manual for 8-bit values
116
+ d := n
117
+ e := n
118
+ p := n
119
+
120
+ // A bit value
121
+ b := raw='[0-7]' .value = number { return parseInt(raw); }
122
+
123
+ // Conditional flags for jumps
124
+ cc := 'nz' | 'z' | 'nc' | 'c' | 'po' | 'pe' | 'p' | 'm' | 's'
125
+ // Conditional flags for djnz
126
+ jj := 'c' | 'nc' | 'z' | 'nz'
127
+
128
+ __ := '[ \t]+' // Mandatory space
129
+ _ := '[ \t]*' // Optional space
130
+ eos := '[ \t]*(;|\r\n|\n|//)' // End of statement
131
+ eol := '\r\n|\n' // End of line
132
+
133
+ // Lines is a list of lines (can be empty)
134
+ Lines :=
135
+ Line*
136
+
137
+ // A line is either an equality or a statement
138
+ Line :=
139
+ LineEqual | LineStatement
140
+
141
+ // An equality is a label (mandatory) followed by an equality directive, an optional comment and an end of line.
142
+ LineEqual :=
143
+ label=LabelDeclaration _ equal=EqualDirective _ comment=Comment? eol
144
+
145
+ // A line with a statement is an optional label, followed by a statement, an optional comment and an end of line.
146
+ LineStatement :=
147
+ label=LabelDeclaration? _ statement=Statement? _ comment=Comment? eol
148
+
149
+ // A statement is either an include, an instruction or a directive
150
+ Statement :=
151
+ inc=IncludeDirective
152
+ .info = LinesInfo { return inc.info; } |
153
+
154
+ ins=Instruction
155
+ .elements = AstElements { return ins.elements; } |
156
+
157
+ dir=Directive
158
+ .elements = AstElements { return dir.elements; }
159
+ .address = Address { return dir.address; }
160
+
161
+ // An equality directive is 'equ' (or an alias) followed by an expression
162
+ EqualDirective :=
163
+ '\.?equ|eq|=' __ e=Expression
164
+
165
+ // A directive is either a data directive, an origin directive, an output directive or a device directive
166
+ Directive :=
167
+ data=DataDirective
168
+ .elements = AstElements { return data.elements; }
169
+ .address = Address { return null; } |
170
+
171
+ origin=OriginDirective
172
+ .elements = AstElements { return []; }
173
+ .address = Address { return origin.address.value; } |
174
+
175
+ directive=OutputDirective
176
+ .elements = AstElements { return []; }
177
+ .address = Address { return null; } |
178
+
179
+ directive=DeviceDirective
180
+ .elements = AstElements { return []; }
181
+ .address = Address { return null; } |
182
+
183
+ directive=EndDirective
184
+ .elements = AstElements { return []; }
185
+ .address = Address { return null; }
186
+
187
+ // Names not allowed for a label
188
+ ForbiddenNames :=
189
+ '\.?block|\.?equ|\.?org|\.?include|\.?output|\.?device|\.?end|\.?byte' |
190
+ 'call|cpdr|cpir|defb|defm|defs|defw|djnz|eq|halt|indr|inir|lddr|ldir|otdr|otir|outd|outi|push|reti|retn|rlca|rrca|\.?word' |
191
+ 'adc|add|and|bit|ccf|cpd|cpi|cpl|daa|dec|exx|inc|ind|ini|ldd|ldi|neg|nop|org|out|pop|res|ret|rla' |
192
+ 'rlc|rld|rra|rrc|rrd|rst|sbc|scf|set|sla|sra|srl|sub|xor' |
193
+ 'cp|db|di|dm|ds|dw|ei|eq|ex|im|in|jp|jr|ld|or|rl|rr'
194
+
195
+ // A forbidden label is a name not allowed for a label followed by a space, a tabulation, the character ':' or an end of line.
196
+ ForbiddenLabel :=
197
+ ForbiddenNames '[ \t:\r\n]'
198
+
199
+ // A label can't have a forbidden name. It is a name or the special pseudo label $ (PC).
200
+ Label :=
201
+ !ForbiddenLabel pos=@ name='[a-z_\.][a-z0-9_!\?#@\.\$]*|\$'
202
+
203
+ // A label declaration can't have a forbidden name. It is a name optionally followed by a ':' character.
204
+ LabelDeclaration :=
205
+ !ForbiddenLabel pos=@ name='[a-z_\.][a-z0-9_!\?#@\.\$]*' '\:'?
206
+
207
+
208
+ // An expression is a bitwise OR expression
209
+ Expression :=
210
+ e1=BitwiseOrExpression
211
+ .eval = EvalFunc { return e1.eval; }
212
+
213
+ // Precedences: unary, multiplicative, additive, shift, and, xor, or
214
+ // Associativity: left to right
215
+
216
+ // A bitwise OR expression is a list of bitwise OR expressions (eventually empty) followed by a bitwise XOR expression
217
+ BitwiseOrExpression :=
218
+ left={e=BitwiseOrExpression _ '\|'}? _ right=BitwiseXOrExpression
219
+ .eval = EvalFunc { return binaryOperation(left, right, operatorOr); }
220
+
221
+ // A bitwise XOR expression is a list of bitwise XOR expressions (eventually empty) followed by a bitwise AND expression
222
+ BitwiseXOrExpression :=
223
+ left={e=BitwiseXOrExpression _ '\^'}? _ right=BitwiseAndExpression
224
+ .eval = EvalFunc { return binaryOperation(left, right, operatorXor); }
225
+
226
+ // A bitwise AND expression is a list of bitwise AND expressions (eventually empty) followed by a bitwise Shift expression
227
+ BitwiseAndExpression :=
228
+ left={e=BitwiseAndExpression _ '\&'}? _ right=ShiftExpression
229
+ .eval = EvalFunc { return binaryOperation(left, right, operatorAnd); }
230
+
231
+ // A bitwise Shift expression is a list of bitwise Shift expressions (eventually empty) followed by an Additive expression
232
+ ShiftExpression :=
233
+ left={e=ShiftExpression _ op={'<<' | '>>'}}? _ right=AdditiveExpression
234
+ .eval = EvalFunc { return binaryOperations(left, right, {'<<': operatorLeftShift, '>>': operatorRightShift}); }
235
+
236
+ // An Additive expression is a list of Additive expressions (eventually empty) followed by a Multiplicative expression
237
+ AdditiveExpression :=
238
+ left={e=AdditiveExpression _ op={'\+' | '\-'}}? _ right=MultiplicativeExpression
239
+ .eval = EvalFunc { return binaryOperations(left, right, {'+': operatorAdd, '-': operatorSub}); }
240
+
241
+ // A Multiplicative expression is a list of Multiplicative expressions (eventually empty) followed by an Unary expression
242
+ MultiplicativeExpression :=
243
+ left={e=MultiplicativeExpression _ op={'\*' | '%' | '/'}}? _ right=UnaryExpression
244
+ .eval = EvalFunc { return binaryOperations(left, right, {'*': operatorMul, '/': operatorDiv, '%': operatorModulo} ); }
245
+
246
+ // An Unary expression is an optional unary operator followed by a Primary expression
247
+ UnaryExpression :=
248
+ op={'~' | '\+' | '\-'} _ e=PrimaryExpression
249
+ .eval = EvalFunc { return unaryOperations(e, op, {'~': operatorInvert, '+': operatorPlus, '-': operatorNeg} ); } |
250
+
251
+ e=PrimaryExpression
252
+ .eval = EvalFunc { return unaryOperation(e, operatorIdentity); }
253
+
254
+ // A Primary expression is a either a number, a label or an expression enclosed in parenthesis
255
+ PrimaryExpression :=
256
+ nn=nn
257
+ .eval = EvalFunc { return value(nn.value); } |
258
+
259
+ pos=@ label=Label
260
+ .eval = EvalFunc { return labelValue(pos, label.name); } |
261
+
262
+ '\(' e=BitwiseOrExpression '\)'
263
+ .eval = EvalFunc { return unaryOperation(e, operatorIdentity); }
264
+
265
+ // A 8-bit register is the name of a 8-bit register but can't be followed by characters such as alphanumerical
266
+ // or symbols. This is to distinguish registers from labels
267
+ Reg8 :=
268
+ reg=r &'[^a-z0-9_!\?#@\.]'
269
+
270
+ // IX register with an (optional) offset
271
+ IX :=
272
+ 'ix' offset={ _ s={'\+' | '\-'} _ pos=@ d=Expression }?
273
+
274
+ // IY register with an (optional) offset
275
+ IY :=
276
+ 'iy' offset={ _ s={'\+' | '\-'} _ pos=@ d=Expression }?
277
+
278
+ // An instruction
279
+ Instruction :=
280
+ Load8Instruction |
281
+ Load16Instruction |
282
+ ExchangeInstruction |
283
+ BlockInstruction |
284
+ ArithmeticLogic8Instruction |
285
+ IncrementDecrement8Instruction |
286
+ GeneralPurposeArithmeticInstruction |
287
+ ArithmeticLogic16Instruction |
288
+ RotateShiftInstruction |
289
+ BitManipulationInstruction |
290
+ JumpInstruction |
291
+ CallInstruction |
292
+ ReturnInstruction |
293
+ InputInstruction |
294
+ OutputInstruction |
295
+ CpuControlGroupInstruction
296
+
297
+ // 8-bit Load
298
+ Load8Instruction :=
299
+ // LD r, r'
300
+ 'ld' __ r0=Reg8 _ ',' _ r1=Reg8 &eos
301
+ .elements = AstElements { return [0b01000000 | r_bits(r0.reg, 3) | r_bits(r1.reg)]; } |
302
+
303
+ // LD r, (HL)
304
+ 'ld' __ r=r _ ',' _ '\(' 'hl' '\)' &eos
305
+ .elements = AstElements { return [0b01000110 | r_bits(r, 3)]; } |
306
+
307
+ // LD r, (IX+d)
308
+ 'ld' __ r=r _ ',' _ '\(' _ i=IX _ '\)' &eos
309
+ .elements = AstElements { return [0xDD, 0b01000110 | r_bits(r, 3), index(i.offset)]; } |
310
+
311
+ // LD r, (IY+d)
312
+ 'ld' __ r=r _ ',' _ '\(' _ i=IY _ '\)' &eos
313
+ .elements = AstElements { return [0xFD, 0b01000110 | r_bits(r, 3), index(i.offset)]; } |
314
+
315
+ // LD (HL), r
316
+ 'ld' __ '\(' _ 'hl' _ '\)' _ ',' _ r=r &eos
317
+ .elements = AstElements { return [0b01110000 | r_bits(r)]; } |
318
+
319
+ // LD (IX+d), r
320
+ 'ld' __ '\(' _ i=IX _ '\)' _ ',' _ r=r &eos
321
+ .elements = AstElements { return [0xDD, 0b01110000 | r_bits(r), index(i.offset)]; } |
322
+
323
+ // LD (IY+d), r
324
+ 'ld' __ '\(' _ i=IY _ '\)' _ ',' _ r=r &eos
325
+ .elements = AstElements { return [0xFD, 0b01110000 | r_bits(r), index(i.offset)]; } |
326
+
327
+ // LD (HL), n
328
+ 'ld' __ '\(' 'hl' '\)' _ ',' _ pos=@ n=Expression &eos
329
+ .elements = AstElements { return [0x36, value8(pos, n)]; } |
330
+
331
+ // LD (IX+d), n
332
+ 'ld' __ '\(' _ i=IX _ '\)' _ ',' _ pos=@ n=Expression &eos
333
+ .elements = AstElements { return [0xDD, 0x36, index(i.offset), value8(pos, n)]; } |
334
+
335
+ // LD (IY+d), n
336
+ 'ld' __ '\(' _ i=IY _ '\)' _ ',' _ pos=@ n=Expression &eos
337
+ .elements = AstElements { return [0xFD, 0x36, index(i.offset), value8(pos, n)]; } |
338
+
339
+ // LD A, (BC)
340
+ 'ld' __ 'a' _ ',' _ '\(' _ 'bc' _ '\)' &eos
341
+ .elements = AstElements { return [0x0A]; } |
342
+
343
+ // LD A, (DE)
344
+ 'ld' __ 'a' _ ',' _ '\(' _ 'de' _ '\)' &eos
345
+ .elements = AstElements { return [0x1A]; } |
346
+
347
+ // LD A, (nn)
348
+ 'ld' __ 'a' _ ',' _ '\(' _ pos=@ ee=Expression _ '\)' &eos
349
+ .elements = AstElements { return [0x3A, value16LE(pos, ee)]; } |
350
+
351
+ // LD (BC), A
352
+ 'ld' __ '\(' _ 'bc' _ '\)' _ ',' _ 'a' &eos
353
+ .elements = AstElements { return [0x02]; } |
354
+
355
+ // LD (DE), A
356
+ 'ld' __ '\(' _ 'de' _ '\)' _ ',' _ 'a' &eos
357
+ .elements = AstElements { return [0x12]; } |
358
+
359
+ // LD (nn), A
360
+ 'ld' __ '\(' _ pos=@ ee=Expression _ '\)' _ ',' _ 'a' &eos
361
+ .elements = AstElements { return [0x32, value16LE(pos, ee)]; } |
362
+
363
+ // LD A, I
364
+ 'ld' __ 'a' _ ',' _ 'i' &eos
365
+ .elements = AstElements { return [0xED, 0x57]; } |
366
+
367
+ // LD A, R
368
+ 'ld' __ 'a' _ ',' _ 'r' &eos
369
+ .elements = AstElements { return [0xED, 0x5F]; } |
370
+
371
+ // LD I, A
372
+ 'ld' __ 'i' _ ',' _ 'a' &eos
373
+ .elements = AstElements { return [0xED, 0x47]; } |
374
+
375
+ // LD R, A
376
+ 'ld' __ 'r' _ ',' _ 'a' &eos
377
+ .elements = AstElements { return [0xED, 0x4F]; } |
378
+
379
+ // Have to be after the others to avoid ambiguity on n=Expression
380
+ // LD r, n
381
+ // Have to be before LD r,r' because it is ambiguous
382
+ 'ld' __ r=Reg8 _ ',' _ pos=@ n=Expression &eos
383
+ .elements = AstElements { return [0b00000110 | r_bits(r.reg, 3), value8(pos, n)]; }
384
+
385
+ // 16-bit Load
386
+ Load16Instruction :=
387
+ // LD IX, (nn)
388
+ 'ld' __ 'ix' _ ',' _ '\(' _ pos=@ ee=Expression _ '\)' &eos
389
+ .elements = AstElements { return [0xDD, 0x2A, value16LE(pos, ee)]; } |
390
+
391
+ // LD IY, (nn)
392
+ 'ld' __ 'iy' _ ',' _ '\(' _ pos=@ ee=Expression _ '\)' &eos
393
+ .elements = AstElements { return [0xFD, 0x2A, value16LE(pos, ee)]; } |
394
+
395
+ // LD IX, nn
396
+ 'ld' __ 'ix' _ ',' _ pos=@ ee=Expression &eos
397
+ .elements = AstElements { return [0xDD, 0x21, value16LE(pos, ee)]; } |
398
+
399
+ // LD IY, nn
400
+ 'ld' __ 'iy' _ ',' _ pos=@ ee=Expression &eos
401
+ .elements = AstElements { return [0xFD, 0x21, value16LE(pos, ee)]; } |
402
+
403
+ // LD HL, (nn)
404
+ 'ld' __ 'hl' _ ',' _ '\(' _ pos=@ ee=Expression _ '\)' &eos
405
+ .elements = AstElements { return [0x2A, value16LE(pos, ee)]; } |
406
+
407
+ // LD dd, (nn)
408
+ 'ld' __ dd=dd _ ',' _ '\(' _ pos=@ ee=Expression _ '\)' &eos
409
+ .elements = AstElements { return [0xED, 0b01001011 | dd_bits(dd, 4), value16LE(pos, ee)]; } |
410
+
411
+ // LD (nn), HL
412
+ 'ld' __ '\(' _ pos=@ ee=Expression _ '\)' _ ',' _ 'hl' &eos
413
+ .elements = AstElements { return [0x22, value16LE(pos, ee)]; } |
414
+
415
+ // LD (nn), dd
416
+ 'ld' __ '\(' _ pos=@ ee=Expression _ '\)' _ ',' _ dd=dd &eos
417
+ .elements = AstElements { return [0xED, 0b01000011 | dd_bits(dd, 4), value16LE(pos, ee)]; } |
418
+
419
+ // LD (nn), IX
420
+ 'ld' __ '\(' _ pos=@ ee=Expression _ '\)' _ ',' _ 'ix' &eos
421
+ .elements = AstElements { return [0xDD, 0x22, value16LE(pos, ee)]; } |
422
+
423
+ // LD (nn), IY
424
+ 'ld' __ '\(' _ pos=@ ee=Expression _ '\)' _ ',' _ 'iy' &eos
425
+ .elements = AstElements { return [0xFD, 0x22, value16LE(pos, ee)]; } |
426
+
427
+ // LD SP, HL
428
+ 'ld' __ 'sp' _ ',' _ 'hl' &eos
429
+ .elements = AstElements { return [0xF9]; } |
430
+
431
+ // LD SP, IX
432
+ 'ld' __ 'sp' _ ',' _ 'ix' &eos
433
+ .elements = AstElements { return [0xDD, 0xF9]; } |
434
+
435
+ // LD SP, IY
436
+ 'ld' __ 'sp' _ ',' _ 'iy' &eos
437
+ .elements = AstElements { return [0xFD, 0xF9]; } |
438
+
439
+ // Have to be after the other LD instructions
440
+ // LD dd, nn
441
+ 'ld' __ dd=dd _ ',' _ pos=@ ee=Expression &eos
442
+ .elements = AstElements { return [0b00000001 | dd_bits(dd, 4), value16LE(pos, ee)]; } |
443
+
444
+ // PUSH qq
445
+ 'push' __ qq=qq &eos
446
+ .elements = AstElements { return [0b11000101 | qq_bits(qq, 4)]; } |
447
+
448
+ // PUSH IX
449
+ 'push' __ 'ix' &eos
450
+ .elements = AstElements { return [0xDD, 0xE5]; } |
451
+
452
+ // PUSH IY
453
+ 'push' __ 'iy' &eos
454
+ .elements = AstElements { return [0xFD, 0xE5]; } |
455
+
456
+ // POP qq
457
+ 'pop' __ qq=qq &eos
458
+ .elements = AstElements { return [0b11000001 | qq_bits(qq, 4)]; } |
459
+
460
+ // POP IX
461
+ 'pop' __ 'ix' &eos
462
+ .elements = AstElements { return [0xDD, 0xE1]; } |
463
+
464
+ // POP IY
465
+ 'pop' __ 'iy' &eos
466
+ .elements = AstElements { return [0xFD, 0xE1]; }
467
+
468
+ // Exchange
469
+ ExchangeInstruction :=
470
+ // EX DE, HL
471
+ 'ex' __ 'de' _ ',' _ 'hl' &eos
472
+ .elements = AstElements { return [0xEB]; } |
473
+
474
+ // EX AF, AF'
475
+ 'ex' __ 'af' _ ',' _ 'af\'' &eos
476
+ .elements = AstElements { return [0x08]; } |
477
+
478
+ // EXX
479
+ 'exx' &eos
480
+ .elements = AstElements { return [0xD9]; } |
481
+
482
+ // EX (SP), HL
483
+ 'ex' __ '\(' 'sp' '\)' _ ',' _ 'hl' &eos
484
+ .elements = AstElements { return [0xE3]; } |
485
+
486
+ // EX (SP), IX
487
+ 'ex' __ '\(' 'sp' '\)' _ ',' _ 'ix' &eos
488
+ .elements = AstElements { return [0xDD, 0xE3]; } |
489
+
490
+ // EX (SP), IY
491
+ 'ex' __ '\(' 'sp' '\)' _ ',' _ 'iy' &eos
492
+ .elements = AstElements { return [0xFD, 0xE3]; }
493
+
494
+ // Block Transfer and Search
495
+ BlockInstruction :=
496
+ // Have to be before ldi
497
+ // LDIR
498
+ 'ldir' &eos
499
+ .elements = AstElements { return [0xED, 0xB0]; } |
500
+
501
+ // LDI
502
+ 'ldi' &eos
503
+ .elements = AstElements { return [0xED, 0xA0]; } |
504
+
505
+ // LDDR
506
+ 'lddr' &eos
507
+ .elements = AstElements { return [0xED, 0xB8]; } |
508
+
509
+ // LDD
510
+ 'ldd' &eos
511
+ .elements = AstElements { return [0xED, 0xA8]; } |
512
+
513
+ // CPIR
514
+ 'cpir' &eos
515
+ .elements = AstElements { return [0xED, 0xB1]; } |
516
+
517
+ // CPI
518
+ 'cpi' &eos
519
+ .elements = AstElements { return [0xED, 0xA1]; } |
520
+
521
+ // CPDR
522
+ 'cpdr' &eos
523
+ .elements = AstElements { return [0xED, 0xB9]; } |
524
+
525
+ // CPD
526
+ 'cpd' &eos
527
+ .elements = AstElements { return [0xED, 0xA9]; }
528
+
529
+ // 8-bit Arithmetic
530
+ ArithmeticLogic8Instruction :=
531
+ // ADD A, (HL)
532
+ 'add' __ {'a' _ ',' _}? '\(' _ 'hl'_ '\)' &eos
533
+ .elements = AstElements { return [0x86]; } |
534
+
535
+ // ADD A, (IX+d)
536
+ 'add' __ {'a' _ ',' _}? '\(' _ i=IX _ '\)' &eos
537
+ .elements = AstElements { return [0xDD, 0x86, index(i.offset)]; } |
538
+
539
+ // ADD A, (IY+d)
540
+ 'add' __ {'a' _ ',' _}? '\(' _ i=IY _ '\)' &eos
541
+ .elements = AstElements { return [0xFD, 0x86, index(i.offset)]; } |
542
+
543
+ // ADD A, r
544
+ 'add' __ {'a' _ ',' _}? r=r &eos
545
+ .elements = AstElements { return [0b10000000 | r_bits(r)]; } |
546
+
547
+ // ADD A, n
548
+ 'add' __ {'a' _ ',' _}? pos=@ n=Expression &eos
549
+ .elements = AstElements { return [0xC6, value8(pos, n)]; } |
550
+
551
+ // ADC A, (HL)
552
+ 'adc' __ {'a' _ ',' _}? '\(' _ 'hl'_ '\)' &eos
553
+ .elements = AstElements { return [0x8E]; } |
554
+
555
+ // ADC (IX+d)
556
+ 'adc' __ {'a' _ ',' _}? '\(' _ i=IX _ '\)' &eos
557
+ .elements = AstElements { return [0xDD, 0x8E, index(i.offset)]; } |
558
+
559
+ // ADC (IY+d)
560
+ 'adc' __ {'a' _ ',' _}? '\(' _ i=IY _ '\)' &eos
561
+ .elements = AstElements { return [0xFD, 0x8E, index(i.offset)]; } |
562
+
563
+ // ADC A, r
564
+ 'adc' __ {'a' _ ',' _}? r=r &eos
565
+ .elements = AstElements { return [0b10001000 | r_bits(r)]; } |
566
+
567
+ // ADC A, n
568
+ 'adc' __ {'a' _ ',' _}? pos=@ n=Expression &eos
569
+ .elements = AstElements { return [0xCE, value8(pos, n)]; } |
570
+
571
+ // SUB A, (HL)
572
+ 'sub' __ {'a' _ ',' _}? '\(' _ 'hl'_ '\)' &eos
573
+ .elements = AstElements { return [0x96]; } |
574
+
575
+ // SUB (IX+d)
576
+ 'sub' __ {'a' _ ',' _}? '\(' _ i=IX _ '\)' &eos
577
+ .elements = AstElements { return [0xDD, 0x96, index(i.offset)]; } |
578
+
579
+ // SUB (IY+d)
580
+ 'sub' __ {'a' _ ',' _}? '\(' _ i=IY _ '\)' &eos
581
+ .elements = AstElements { return [0xFD, 0x96, index(i.offset)]; } |
582
+
583
+ // SUB A, r
584
+ 'sub' __ {'a' _ ',' _}? r=r &eos
585
+ .elements = AstElements { return [0b10010000 | r_bits(r)]; } |
586
+
587
+ // SUB A, n
588
+ 'sub' __ {'a' _ ',' _}? pos=@ n=Expression &eos
589
+ .elements = AstElements { return [0xD6, value8(pos, n)]; } |
590
+
591
+ // SBC A, (HL)
592
+ 'sbc' __ {'a' _ ',' _}? '\(' _ 'hl'_ '\)' &eos
593
+ .elements = AstElements { return [0x9E]; } |
594
+
595
+ // SBC (IX+d)
596
+ 'sbc' __ {'a' _ ',' _}? '\(' _ i=IX _ '\)' &eos
597
+ .elements = AstElements { return [0xDD, 0x9E, index(i.offset)]; } |
598
+
599
+ // SBC (IY+d)
600
+ 'sbc' __ {'a' _ ',' _}? '\(' _ i=IY _ '\)' &eos
601
+ .elements = AstElements { return [0xFD, 0x9E, index(i.offset)]; } |
602
+
603
+ // SBC A, r
604
+ 'sbc' __ {'a' _ ',' _}? r=r &eos
605
+ .elements = AstElements { return [0b10011000 | r_bits(r)]; } |
606
+
607
+ // SBC A, n
608
+ 'sbc' __ {'a' _ ',' _}? pos=@ n=Expression &eos
609
+ .elements = AstElements { return [0xDE, value8(pos, n)]; } |
610
+
611
+ // AND A, (HL)
612
+ 'and' __ {'a' _ ',' _}? '\(' _ 'hl'_ '\)' &eos
613
+ .elements = AstElements { return [0xA6]; } |
614
+
615
+ // AND (IX+d)
616
+ 'and' __ {'a' _ ',' _}? '\(' _ i=IX _ '\)' &eos
617
+ .elements = AstElements { return [0xDD, 0xA6, index(i.offset)]; } |
618
+
619
+ // AND (IY+d)
620
+ 'and' __ {'a' _ ',' _}? '\(' _ i=IY _ '\)' &eos
621
+ .elements = AstElements { return [0xFD, 0xA6, index(i.offset)]; } |
622
+
623
+ // AND A, r
624
+ 'and' __ {'a' _ ',' _}? r=r &eos
625
+ .elements = AstElements { return [0b10100000 | r_bits(r)]; } |
626
+
627
+ // AND A, n
628
+ 'and' __ {'a' _ ',' _}? pos=@ n=Expression &eos
629
+ .elements = AstElements { return [0xE6, value8(pos, n)]; } |
630
+
631
+ // OR A, (HL)
632
+ 'or' __ {'a' _ ',' _}? '\(' _ 'hl'_ '\)' &eos
633
+ .elements = AstElements { return [0xB6]; } |
634
+
635
+ // OR (IX+d)
636
+ 'or' __ {'a' _ ',' _}? '\(' _ i=IX _ '\)' &eos
637
+ .elements = AstElements { return [0xDD, 0xB6, index(i.offset)]; } |
638
+
639
+ // OR (IY+d)
640
+ 'or' __ {'a' _ ',' _}? '\(' _ i=IY _ '\)' &eos
641
+ .elements = AstElements { return [0xFD, 0xB6, index(i.offset)]; } |
642
+
643
+ // OR A, r
644
+ 'or' __ {'a' _ ',' _}? r=r &eos
645
+ .elements = AstElements { return [0b10110000 | r_bits(r)]; } |
646
+
647
+ // OR A, n
648
+ 'or' __ {'a' _ ',' _}? pos=@ n=Expression &eos
649
+ .elements = AstElements { return [0xF6, value8(pos, n)]; } |
650
+
651
+ // XOR A, (HL)
652
+ 'xor' __ {'a' _ ',' _}? '\(' _ 'hl'_ '\)' &eos
653
+ .elements = AstElements { return [0xAE]; } |
654
+
655
+ // XOR (IX+d)
656
+ 'xor' __ {'a' _ ',' _}? '\(' _ i=IX _ '\)' &eos
657
+ .elements = AstElements { return [0xDD, 0xAE, index(i.offset)]; } |
658
+
659
+ // XOR (IY+d)
660
+ 'xor' __ {'a' _ ',' _}? '\(' _ i=IY _ '\)' &eos
661
+ .elements = AstElements { return [0xFD, 0xAE, index(i.offset)]; } |
662
+
663
+ // XOR A, r
664
+ 'xor' __ {'a' _ ',' _}? r=r &eos
665
+ .elements = AstElements { return [0b10101000 | r_bits(r)]; } |
666
+
667
+ // XOR A, n
668
+ 'xor' __ {'a' _ ',' _}? pos=@ n=Expression &eos
669
+ .elements = AstElements { return [0xEE, value8(pos, n)]; } |
670
+
671
+ // CP A, (HL)
672
+ 'cp' __ {'a' _ ',' _}? '\(' _ 'hl'_ '\)' &eos
673
+ .elements = AstElements { return [0xBE]; } |
674
+
675
+ // CP (IX+d)
676
+ 'cp' __ {'a' _ ',' _}? '\(' _ i=IX _ '\)' &eos
677
+ .elements = AstElements { return [0xDD, 0xBE, index(i.offset)]; } |
678
+
679
+ // CP (IY+d)
680
+ 'cp' __ {'a' _ ',' _}? '\(' _ i=IY _ '\)' &eos
681
+ .elements = AstElements { return [0xFD, 0xBE, index(i.offset)]; } |
682
+
683
+ // CP A, r
684
+ 'cp' __ {'a' _ ',' _}? r=r &eos
685
+ .elements = AstElements { return [0b10111000 | r_bits(r)]; } |
686
+
687
+ // CP A, n
688
+ 'cp' __ {'a' _ ',' _}? pos=@ n=Expression &eos
689
+ .elements = AstElements { return [0xFE, value8(pos, n)]; }
690
+
691
+
692
+ // 8-bit Increment and Decrement
693
+ IncrementDecrement8Instruction :=
694
+ // INC r
695
+ 'inc' __ r=r &eos
696
+ .elements = AstElements { return [0b00000100 | r_bits(r, 3)]; } |
697
+
698
+ // INC (HL)
699
+ 'inc' __ '\(' _ 'hl' _ '\)' &eos
700
+ .elements = AstElements { return [0x34]; } |
701
+
702
+ // INC (IX+d)
703
+ 'inc' __ '\(' _ i=IX _ '\)' &eos
704
+ .elements = AstElements { return [0xDD, 0x34, index(i.offset)]; } |
705
+
706
+ // INC (IY+d)
707
+ 'inc' __ '\(' _ i=IY _ '\)' &eos
708
+ .elements = AstElements { return [0xFD, 0x34, index(i.offset)]; } |
709
+
710
+ // DEC r
711
+ 'dec' __ r=r &eos
712
+ .elements = AstElements { return [0b00000101 | r_bits(r, 3)]; } |
713
+
714
+ // DEC (HL)
715
+ 'dec' __ '\(' _ 'hl' _ '\)' &eos
716
+ .elements = AstElements { return [0x35]; } |
717
+
718
+ // DEC (IX+d)
719
+ 'dec' __ '\(' _ i=IX _ '\)' &eos
720
+ .elements = AstElements { return [0xDD, 0x35, index(i.offset)]; } |
721
+
722
+ // DEC (IY+d)
723
+ 'dec' __ '\(' _ i=IY _ '\)' &eos
724
+ .elements = AstElements { return [0xFD, 0x35, index(i.offset)]; }
725
+
726
+ // General Purpose Arithmetic Instructions
727
+ GeneralPurposeArithmeticInstruction :=
728
+ // DAA
729
+ 'daa' &eos
730
+ .elements = AstElements { return [0x27]; } |
731
+
732
+ // CPL
733
+ 'cpl' &eos
734
+ .elements = AstElements { return [0x2F]; } |
735
+
736
+ // NEG
737
+ 'neg' &eos
738
+ .elements = AstElements { return [0xED, 0x44]; } |
739
+
740
+ // CCF
741
+ 'ccf' &eos
742
+ .elements = AstElements { return [0x3F]; } |
743
+
744
+ // SCF
745
+ 'scf' &eos
746
+ .elements = AstElements { return [0x37]; }
747
+
748
+ // CPU Control Group Instructions
749
+ CpuControlGroupInstruction :=
750
+ // NOP
751
+ 'nop' &eos
752
+ .elements = AstElements { return [0x00]; } |
753
+
754
+ // HALT
755
+ 'halt' &eos
756
+ .elements = AstElements { return [0x76]; } |
757
+
758
+ // DI
759
+ 'di' &eos
760
+ .elements = AstElements { return [0xF3]; } |
761
+
762
+ // EI
763
+ 'ei' &eos
764
+ .elements = AstElements { return [0xFB]; } |
765
+
766
+ // IM 0, IM 1, IM 2
767
+ 'im' __ m='[012]' &eos
768
+ .elements = AstElements { return [0xED, imode(m)]; }
769
+
770
+ // 16-bit Arithmetic
771
+ ArithmeticLogic16Instruction :=
772
+ // ADD HL, ss
773
+ 'add' __ 'hl' _ ',' _ ss=ss &eos
774
+ .elements = AstElements { return [0b00001001 | ss_bits(ss, 4)]; } |
775
+
776
+ // ADC HL, ss
777
+ 'adc' __ 'hl' _ ',' _ ss=ss &eos
778
+ .elements = AstElements { return [0xED, 0b01001010 | ss_bits(ss, 4)]; } |
779
+
780
+ // SBC HL, ss
781
+ 'sbc' __ 'hl' _ ',' _ ss=ss &eos
782
+ .elements = AstElements { return [0xED, 0b01000010 | ss_bits(ss, 4)]; } |
783
+
784
+ // ADD IX, pp
785
+ 'add' __ 'ix' _ ',' _ pp=pp &eos
786
+ .elements = AstElements { return [0xDD, 0b00001001 | pp_bits(pp, 4)]; } |
787
+
788
+ // ADD IY, pp
789
+ 'add' __ 'iy' _ ',' _ rr=rr &eos
790
+ .elements = AstElements { return [0xFD, 0b00001001 | rr_bits(rr, 4)]; } |
791
+
792
+ // INC ss
793
+ 'inc' __ ss=ss &eos
794
+ .elements = AstElements { return [0b00000011 | ss_bits(ss, 4)]; } |
795
+
796
+ // INC IX
797
+ 'inc' __ 'ix' &eos
798
+ .elements = AstElements { return [0xDD, 0x23]; } |
799
+
800
+ // INC IY
801
+ 'inc' __ 'iy' &eos
802
+ .elements = AstElements { return [0xFD, 0x23]; } |
803
+
804
+ // DEC ss
805
+ 'dec' __ ss=ss &eos
806
+ .elements = AstElements { return [0b00001011 | ss_bits(ss, 4)]; } |
807
+
808
+ // DEC IX
809
+ 'dec' __ 'ix' &eos
810
+ .elements = AstElements { return [0xDD, 0x2B]; } |
811
+
812
+ // DEC IY
813
+ 'dec' __ 'iy' &eos
814
+ .elements = AstElements { return [0xFD, 0x2B]; }
815
+
816
+ // Rotate and Shift
817
+ RotateShiftInstruction :=
818
+ // RLCA
819
+ 'rlca' &eos
820
+ .elements = AstElements { return [0x07]; } |
821
+
822
+ // RLA
823
+ 'rla' &eos
824
+ .elements = AstElements { return [0x17]; } |
825
+
826
+ // RRCA
827
+ 'rrca' &eos
828
+ .elements = AstElements { return [0x0F]; } |
829
+
830
+ // RRA
831
+ 'rra' &eos
832
+ .elements = AstElements { return [0x1F]; } |
833
+
834
+ // RLC r
835
+ 'rlc' __ r=r &eos
836
+ .elements = AstElements { return [0xCB, 0b00000000 | r_bits(r)]; } |
837
+
838
+ // RLC (HL)
839
+ 'rlc' __ '\(' _ 'hl' _ '\)' &eos
840
+ .elements = AstElements { return [0xCB, 0x06]; } |
841
+
842
+ // RLC (IX+d)
843
+ 'rlc' __ '\(' _ i=IX _ '\)' &eos
844
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0x06]; } |
845
+
846
+ // RLC (IY+d)
847
+ 'rlc' __ '\(' _ i=IY _ '\)' &eos
848
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0x06]; } |
849
+
850
+ // RL r
851
+ 'rl' __ r=r &eos
852
+ .elements = AstElements { return [0xCB, 0b00010000 | r_bits(r)]; } |
853
+
854
+ // RL (HL)
855
+ 'rl' __ '\(' _ 'hl' _ '\)' &eos
856
+ .elements = AstElements { return [0xCB, 0x16]; } |
857
+
858
+ // RL (IX+d)
859
+ 'rl' __ '\(' _ i=IX _ '\)' &eos
860
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0x16]; } |
861
+
862
+ // RL (IY+d)
863
+ 'rl' __ '\(' _ i=IY _ '\)' &eos
864
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0x16]; } |
865
+
866
+ // RRC r
867
+ 'rrc' __ r=r &eos
868
+ .elements = AstElements { return [0xCB, 0b00001000 | r_bits(r)]; } |
869
+
870
+ // RRC (HL)
871
+ 'rrc' __ '\(' _ 'hl' _ '\)' &eos
872
+ .elements = AstElements { return [0xCB, 0x0E]; } |
873
+
874
+ // RRC (IX+d)
875
+ 'rrc' __ '\(' _ i=IX _ '\)' &eos
876
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0x0E]; } |
877
+
878
+ // RRC (IY+d)
879
+ 'rrc' __ '\(' _ i=IY _ '\)' &eos
880
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0x0E]; } |
881
+
882
+ // RR r
883
+ 'rr' __ r=r &eos
884
+ .elements = AstElements { return [0xCB, 0b00011000 | r_bits(r)]; } |
885
+
886
+ // RR (HL)
887
+ 'rr' __ '\(' _ 'hl' _ '\)' &eos
888
+ .elements = AstElements { return [0xCB, 0x1E]; } |
889
+
890
+ // RR (IX+d)
891
+ 'rr' __ '\(' _ i=IX _ '\)' &eos
892
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0x1E]; } |
893
+
894
+ // RR (IY+d)
895
+ 'rr' __ '\(' _ i=IY _ '\)' &eos
896
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0x1E]; } |
897
+
898
+ // SLA r
899
+ 'sla' __ r=r &eos
900
+ .elements = AstElements { return [0xCB, 0b00100000 | r_bits(r)]; } |
901
+
902
+ // SLA (HL)
903
+ 'sla' __ '\(' _ 'hl' _ '\)' &eos
904
+ .elements = AstElements { return [0xCB, 0x26]; } |
905
+
906
+ // SLA (IX+d)
907
+ 'sla' __ '\(' _ i=IX _ '\)' &eos
908
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0x26]; } |
909
+
910
+ // SLA (IY+d)
911
+ 'sla' __ '\(' _ i=IY _ '\)' &eos
912
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0x26]; } |
913
+
914
+ // SRA r
915
+ 'sra' __ r=r &eos
916
+ .elements = AstElements { return [0xCB, 0b00101000 | r_bits(r)]; } |
917
+
918
+ // SRA (HL)
919
+ 'sra' __ '\(' _ 'hl' _ '\)' &eos
920
+ .elements = AstElements { return [0xCB, 0x2E]; } |
921
+
922
+ // SRA (IX+d)
923
+ 'sra' __ '\(' _ i=IX _ '\)' &eos
924
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0x2E]; } |
925
+
926
+ // SRA (IY+d)
927
+ 'sra' __ '\(' _ i=IY _ '\)' &eos
928
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0x2E]; } |
929
+
930
+ // SRL r
931
+ 'srl' __ r=r &eos
932
+ .elements = AstElements { return [0xCB, 0b00111000 | r_bits(r)]; } |
933
+
934
+ // SRL (HL)
935
+ 'srl' __ '\(' _ 'hl' _ '\)' &eos
936
+ .elements = AstElements { return [0xCB, 0x3E]; } |
937
+
938
+ // SRL (IX+d)
939
+ 'srl' __ '\(' _ i=IX _ '\)' &eos
940
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0x3E]; } |
941
+
942
+ // SRL (IY+d)
943
+ 'srl' __ '\(' _ i=IY _ '\)' &eos
944
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0x3E]; } |
945
+
946
+ // RLD
947
+ 'rld' &eos
948
+ .elements = AstElements { return [0xED, 0x6F]; } |
949
+
950
+ // RRD
951
+ 'rrd' &eos
952
+ .elements = AstElements { return [0xED, 0x67]; }
953
+
954
+ // Bit Manipulation
955
+ BitManipulationInstruction :=
956
+ // BIT b, r
957
+ 'bit' __ b=b _ ',' _ r=r &eos
958
+ .elements = AstElements { return [0xCB, 0b01000000 | (b.value << 3) | r_bits(r)]; } |
959
+
960
+ // BIT b, (HL)
961
+ 'bit' __ b=b _ ',' _ '\(' _ 'hl' _ '\)' &eos
962
+ .elements = AstElements { return [0xCB, 0b01000110 | (b.value << 3)]; } |
963
+
964
+ // BIT b, (IX+d)
965
+ 'bit' __ b=b _ ',' _ '\(' _ i=IX _ '\)' &eos
966
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0b01000110 | (b.value << 3)]; } |
967
+
968
+ // BIT b, (IY+d)
969
+ 'bit' __ b=b _ ',' _ '\(' _ i=IY _ '\)' &eos
970
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0b01000110 | (b.value << 3)]; } |
971
+
972
+ // SET b, r
973
+ 'set' __ b=b _ ',' _ r=r &eos
974
+ .elements = AstElements { return [0xCB, 0b11000000 | (b.value << 3) | r_bits(r)]; } |
975
+
976
+ // SET b, (HL)
977
+ 'set' __ b=b _ ',' _ '\(' _ 'hl' _ '\)' &eos
978
+ .elements = AstElements { return [0xCB, 0b11000110 | (b.value << 3)]; } |
979
+
980
+ // SET b, (IX+d)
981
+ 'set' __ b=b _ ',' _ '\(' _ i=IX _ '\)' &eos
982
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0b11000110 | (b.value << 3)]; } |
983
+
984
+ // SET b, (IY+d)
985
+ 'set' __ b=b _ ',' _ '\(' _ i=IY _ '\)' &eos
986
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0b11000110 | (b.value << 3)]; } |
987
+
988
+ // RES b, r
989
+ 'res' __ b=b _ ',' _ r=r &eos
990
+ .elements = AstElements { return [0xCB, 0b10000000 | (b.value << 3) | r_bits(r)]; } |
991
+
992
+ // RES b, (HL)
993
+ 'res' __ b=b _ ',' _ '\(' _ 'hl' _ '\)' &eos
994
+ .elements = AstElements { return [0xCB, 0b10000110 | (b.value << 3)]; } |
995
+
996
+ // RES b, (IX+d)
997
+ 'res' __ b=b _ ',' _ '\(' _ i=IX _ '\)' &eos
998
+ .elements = AstElements { return [0xDD, 0xCB, index(i.offset), 0b10000110 | (b.value << 3)]; } |
999
+
1000
+ // RES b, (IY+d)
1001
+ 'res' __ b=b _ ',' _ '\(' _ i=IY _ '\)' &eos
1002
+ .elements = AstElements { return [0xFD, 0xCB, index(i.offset), 0b10000110 | (b.value << 3)]; }
1003
+
1004
+ Offset :=
1005
+ pos=@ label=Label
1006
+ .eval = EvalFunc { return labelValue(pos, label.name); } |
1007
+
1008
+ e=Expression
1009
+ .eval = EvalFunc { return e.eval; }
1010
+
1011
+ // Jumps
1012
+ JumpInstruction :=
1013
+ // JP (HL)
1014
+ 'jp' __ '\(' _ 'hl' _ '\)' &eos
1015
+ .elements = AstElements { return [0xE9]; } |
1016
+
1017
+ // JP (IX)
1018
+ 'jp' __ '\(' _ 'ix' _ '\)' &eos
1019
+ .elements = AstElements { return [0xDD, 0xE9]; } |
1020
+
1021
+ // JP (IY)
1022
+ 'jp' __ '\(' _ 'iy' _ '\)' &eos
1023
+ .elements = AstElements { return [0xFD, 0xE9]; } |
1024
+
1025
+ // JP nn
1026
+ 'jp' __ pos=@ ee=Expression &eos
1027
+ .elements = AstElements { return [0xC3, value16LE(pos, ee)]; } |
1028
+
1029
+ // JP CC, nn
1030
+ 'jp' __ cc=cc _ ',' _ pos=@ ee=Expression &eos
1031
+ .elements = AstElements { return [0b11000010 | cc_bits(cc, 3), value16LE(pos, ee)]; } |
1032
+
1033
+ // JR label
1034
+ 'jr' __ pos=@ label=Label &eos
1035
+ .elements = AstElements { return [jj_bits(), jrRelativeOffset(pos, label.name)]; } |
1036
+
1037
+ // JR e
1038
+ 'jr' __ pos=@ e=Expression &eos
1039
+ .elements = AstElements { return [jj_bits(), jrOffset(pos, e)]; } |
1040
+
1041
+ // JR jj, label
1042
+ 'jr' __ jj=jj _ ',' _ pos=@ label=Label &eos
1043
+ .elements = AstElements { return [jj_bits(jj), jrRelativeOffset(pos, label.name)]; } |
1044
+
1045
+ // JR jj, e
1046
+ 'jr' __ jj=jj _ ',' _ pos=@ e=Expression &eos
1047
+ .elements = AstElements { return [jj_bits(jj), jrOffset(pos, e)]; } |
1048
+
1049
+ // DJNZ label
1050
+ 'djnz' __ pos=@ label=Label &eos
1051
+ .elements = AstElements { return [0x10, jrRelativeOffset(pos, label.name)]; } |
1052
+
1053
+ // DJNZ e
1054
+ 'djnz' __ pos=@ e=Expression &eos
1055
+ .elements = AstElements { return [0x10, jrOffset(pos, e)]; }
1056
+
1057
+ // Calls
1058
+ CallInstruction :=
1059
+ // CALL nn
1060
+ 'call' __ pos=@ ee=Expression &eos
1061
+ .elements = AstElements { return [0xCD, value16LE(pos, ee)]; } |
1062
+
1063
+ // CALL cc, nn
1064
+ 'call' __ cc=cc _ ',' _ pos=@ ee=Expression &eos
1065
+ .elements = AstElements { return [0b11000100 | cc_bits(cc, 3), value16LE(pos, ee)]; }
1066
+
1067
+ // Returns
1068
+ ReturnInstruction :=
1069
+ // RET
1070
+ 'ret' &eos
1071
+ .elements = AstElements { return [0xC9]; } |
1072
+
1073
+ // RET cc
1074
+ 'ret' __ cc=cc &eos
1075
+ .elements = AstElements { return [0b11000000 | cc_bits(cc, 3)]; } |
1076
+
1077
+ // RETI
1078
+ 'reti' &eos
1079
+ .elements = AstElements { return [0xED, 0x4D]; } |
1080
+
1081
+ // RETN
1082
+ 'retn' &eos
1083
+ .elements = AstElements { return [0xED, 0x45]; } |
1084
+
1085
+ // RST p
1086
+ 'rst' __ p=p &eos
1087
+ .elements = AstElements { return [0b11000111 | p_bits(p.value, 3)]; }
1088
+
1089
+ // Inputs
1090
+ InputInstruction :=
1091
+ // Have to be before IN A, (n)
1092
+ // IN r, (C)
1093
+ 'in' __ r=r _ ',' _ '\(' 'c' '\)' &eos
1094
+ .elements = AstElements { return [0xED, 0b01000000 | r_bits(r, 3)]; } |
1095
+
1096
+ // IN A, (n)
1097
+ 'in' __ 'a' _ ',' _ '\(' _ pos=@ n=Expression _ '\)' &eos
1098
+ .elements = AstElements { return [0xDB, value8(pos, n)]; } |
1099
+
1100
+ // INI
1101
+ 'ini' &eos
1102
+ .elements = AstElements { return [0xED, 0xA2]; } |
1103
+
1104
+ // INIR
1105
+ 'inir' &eos
1106
+ .elements = AstElements { return [0xED, 0xB2]; } |
1107
+
1108
+ // IND
1109
+ 'ind' &eos
1110
+ .elements = AstElements { return [0xED, 0xAA]; } |
1111
+
1112
+ // INDR
1113
+ 'indr' &eos
1114
+ .elements = AstElements { return [0xED, 0xBA]; }
1115
+
1116
+ // Outputs
1117
+ OutputInstruction :=
1118
+ // Have to be before OUT (n), A
1119
+ // OUT (C), r
1120
+ 'out' __ '\(' 'c' '\)' _ ',' _ r=r &eos
1121
+ .elements = AstElements { return [0xED, 0b01000001 | r_bits(r, 3)]; } |
1122
+
1123
+ // OUT (n), A
1124
+ 'out' __ '\(' _ pos=@ n=Expression _ '\)' _ ',' _ 'a' &eos
1125
+ .elements = AstElements { return [0xD3, value8(pos, n)]; } |
1126
+
1127
+ // OUTI
1128
+ 'outi' &eos
1129
+ .elements = AstElements { return [0xED, 0xA3]; } |
1130
+
1131
+ // OTIR
1132
+ 'otir' &eos
1133
+ .elements = AstElements { return [0xED, 0xB3]; } |
1134
+
1135
+ // OUTD
1136
+ 'outd' &eos
1137
+ .elements = AstElements { return [0xED, 0xAB]; } |
1138
+
1139
+ // OTDR
1140
+ 'otdr' &eos
1141
+ .elements = AstElements { return [0xED, 0xBB]; }
1142
+
1143
+ // Byte directive
1144
+ ByteDirective :=
1145
+ 'db' | 'dm' | '\.?byte' | 'defb' | 'defm'
1146
+
1147
+ // Word directive
1148
+ WordDirective :=
1149
+ 'dw' | '\.?word' | 'defw'
1150
+
1151
+ // Block directive
1152
+ BlockDirective :=
1153
+ '\.?block' | 'defs' | 'ds'
1154
+
1155
+ // A Byte directive contains either characters, strings, or expressions
1156
+ ByteValue :=
1157
+ s=QuottedStr .elements = AstElements { return s.elements; } |
1158
+ s=DoubleQuottedStr .elements = AstElements { return s.elements; } |
1159
+ pos=@ e=Expression .elements = AstElements { return [value8(pos, e)]; }
1160
+
1161
+ // A Word directive contains expressions
1162
+ WordValue :=
1163
+ pos=@ e=Expression .elements = AstElements { return [value16LE(pos, e)]; }
1164
+
1165
+ // A Data directive is either a Byte directive, a Word directive or a Block directive
1166
+ DataDirective :=
1167
+ // byte $FF, ...
1168
+ ByteDirective __ pos0=@ data0=ByteValue data={_ ',' _ inner=ByteValue}* &eos
1169
+ .elements = AstElements { return dataBytes(pos0, data0, data); } |
1170
+
1171
+ // word $FFFF, ...
1172
+ WordDirective __ pos0=@ data0=WordValue data={_ ',' _ inner=WordValue}* &eos
1173
+ .elements = AstElements { return dataWords(pos0, data0, data); } |
1174
+
1175
+ // block length, fill byte
1176
+ BlockDirective __ @pos0=@ nn=Expression data={_ ',' _ pos1=@ b=Expression}? &eos
1177
+ .elements = AstElements { return [dataBlock(pos0, nn, data?.pos1, data?.b)]; }
1178
+
1179
+ // An escape sequence is either simple, in octal or in hexadecimal
1180
+ EscapeSequence :=
1181
+ SimpleEscapeSequence |
1182
+ OctalEscapeSequence |
1183
+ HexadecimalEscapeSequence
1184
+
1185
+ // A simple escape is a backslash followed by a character
1186
+ SimpleEscapeSequence :=
1187
+ pos=@ '\\' raw={'"' | 'n'}
1188
+ .elements = AstElements { return parseSimpleEscape(pos, raw); }
1189
+
1190
+ // An octal escape is a backslash followed by an octal value
1191
+ OctalEscapeSequence :=
1192
+ '\\' pos=@ raw='[0-7]{1,3}'
1193
+ .elements = AstElements { return parseOctalEscape(pos, raw); }
1194
+
1195
+ // An hexadecimal escape is a backslash followed by an 'x' and an hexadecimal value
1196
+ HexadecimalEscapeSequence :=
1197
+ '\\x' pos=@ raw='[0-9a-f]{1,2}'
1198
+ .elements = AstElements { return parseHexadecimalEscape(pos, raw); }
1199
+
1200
+ // A character that is not a quote, a backslash or a newline
1201
+ NoQuoteChar :=
1202
+ pos=@ raw='[^\'\\\n]'
1203
+ .elements = AstElements { return parseZX81Char(pos, raw); }
1204
+
1205
+ // A character is not a double-quote, a backslash or a newline
1206
+ NoDoubleQuoteChar :=
1207
+ pos=@ raw='[^\"\\\n]'
1208
+ .elements = AstElements { return parseZX81Char(pos, raw); }
1209
+
1210
+ // A string literal enclosed in double-quotes and containing either simple characters or escape sequences
1211
+ QuottedStr :=
1212
+ '\'' pos=@ chars={NoQuoteChar | EscapeSequence}+ '\''
1213
+ .elements = AstElements { return chars.reduce((r, c) => { return r.concat(c.elements); }, [] as AstElements); }
1214
+
1215
+ // A string literal is enclosed in double-quotes and contains either simple characters or escape sequences
1216
+ DoubleQuottedStr :=
1217
+ '\"' pos=@ chars={NoDoubleQuoteChar | EscapeSequence}+ '\"'
1218
+ .elements = AstElements { return chars.reduce((r, c) => { return r.concat(c.elements); }, [] as AstElements); }
1219
+
1220
+
1221
+ // A comment starts with '//' or ';' and goes until the end of the statement
1222
+ Comment :=
1223
+ '(//|;)[^\r\n]*'
1224
+
1225
+ // An Origin directive is 'org' (or an alias) followed by a 16-bit value and the end of the statement
1226
+ OriginDirective :=
1227
+ '\.?org' __ address=nn
1228
+
1229
+ // A filename is optionally enclosed in double-quotes and contains a subset of characters.
1230
+ Filename :=
1231
+ '"' raw='[^"\\:\*\?<>\|%#\$,]+' '"' |
1232
+ raw='[^ \t\r\n"\\:\*\?<>\|%#\$,]+'
1233
+
1234
+ // An Include directive starts with 'include' (or an alias) and is followed by a Filename
1235
+ IncludeDirective :=
1236
+ pos=@ '\.?include' __ name=Filename &eos
1237
+ .info = LinesInfo { return includeFile(pos, name.raw); }
1238
+
1239
+ // An Output directive starts with 'output' (or an alias) and is followed by a Filename.
1240
+ // Optionally, it is followed by a comma, 'sld' and an filename
1241
+ OutputDirective :=
1242
+ '\.?output' __ name=Filename sld={_ ',' _ 'sld' __ name=Filename}? &eos
1243
+ .void = void { setOutputName(name.raw, sld?.name.raw); }
1244
+
1245
+ // A Device directive starts with 'device' (or an alias) and is followed by a name (the target)
1246
+ DeviceDirective :=
1247
+ '\.?device' __ raw='[a-zA-Z][0-9a-zA-Z]*' &eos
1248
+ .void = void { setDevice(raw); }
1249
+
1250
+ // A End directive will stop the parsing by eating all the characters
1251
+ EndDirective :=
1252
+ '\.?end' &eos '.*'