sbpf_assembler/parser.rs
1use crate::ast::AST;
2use crate::astnode::{
3 ASTNode, Directive, EquDecl, ExternDecl, GlobalDecl, Label, ROData, RodataDecl,
4};
5use crate::bug;
6use crate::dynsym::{DynamicSymbolMap, RelDynMap};
7use crate::errors::CompileError;
8use crate::instruction::Instruction;
9use crate::lexer::Op;
10use crate::lexer::{ImmediateValue, Token};
11use crate::messages::*;
12use crate::section::{CodeSection, DataSection};
13use num_traits::FromPrimitive;
14use sbpf_common::opcode::Opcode;
15use std::collections::HashMap;
16
17pub struct ParseResult {
18 // TODO: parse result is basically 1. static part 2. dynamic part of the program
19 pub code_section: CodeSection,
20
21 pub data_section: DataSection,
22
23 pub dynamic_symbols: DynamicSymbolMap,
24
25 pub relocation_data: RelDynMap,
26
27 // TODO: this can be removed and dynamic-ness should just be
28 // determined by if there's any dynamic symbol
29 pub prog_is_static: bool,
30}
31
32// for now, we only return one error per parse for simpler error handling
33pub trait Parse {
34 fn parse(tokens: &[Token]) -> Result<(Self, &[Token]), CompileError>
35 where
36 Self: Sized;
37}
38
39pub trait ParseWithConstMap {
40 fn parse_with_constmap<'a>(
41 tokens: &'a [Token],
42 const_map: &HashMap<String, ImmediateValue>,
43 ) -> Result<(Self, &'a [Token]), CompileError>
44 where
45 Self: Sized;
46}
47
48impl Parse for GlobalDecl {
49 fn parse(tokens: &[Token]) -> Result<(Self, &[Token]), CompileError> {
50 let Token::Directive(_, span) = &tokens[0] else {
51 bug!("GlobalDecl not a valid directive")
52 };
53 if tokens.len() < 2 {
54 return Err(CompileError::InvalidGlobalDecl {
55 span: span.clone(),
56 custom_label: None,
57 });
58 }
59 match &tokens[1] {
60 Token::Identifier(name, span) => Ok((
61 GlobalDecl {
62 entry_label: name.clone(),
63 span: span.clone(),
64 },
65 &tokens[2..],
66 )),
67 _ => Err(CompileError::InvalidGlobalDecl {
68 span: span.clone(),
69 custom_label: None,
70 }),
71 }
72 }
73}
74
75impl ParseWithConstMap for EquDecl {
76 fn parse_with_constmap<'a>(
77 tokens: &'a [Token],
78 const_map: &HashMap<String, ImmediateValue>,
79 ) -> Result<(Self, &'a [Token]), CompileError> {
80 let Token::Directive(_, span) = &tokens[0] else {
81 bug!("EquDecl not a valid directive")
82 };
83 if tokens.len() < 3 {
84 return Err(CompileError::InvalidEquDecl {
85 span: span.clone(),
86 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
87 });
88 }
89 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 3);
90 if let Some(value) = value {
91 match (
92 &tokens[1], &tokens[2],
93 // third operand is folded to an immediate value
94 ) {
95 (
96 Token::Identifier(name, span),
97 Token::Comma(_),
98 // third operand is folded to an immediate value
99 ) => Ok((
100 EquDecl {
101 name: name.clone(),
102 value: Token::ImmediateValue(value, span.clone()),
103 span: span.clone(),
104 },
105 &tokens[advance_token_num..],
106 )),
107 _ => Err(CompileError::InvalidEquDecl {
108 span: span.clone(),
109 custom_label: Some(EXPECTS_IDEN_COM_IMM.to_string()),
110 }),
111 }
112 } else {
113 Err(CompileError::InvalidEquDecl {
114 span: span.clone(),
115 custom_label: Some(EXPECTS_IDEN_COM_IMM.to_string()),
116 })
117 }
118 }
119}
120
121impl Parse for ExternDecl {
122 fn parse(tokens: &[Token]) -> Result<(Self, &[Token]), CompileError> {
123 let Token::Directive(_, span) = &tokens[0] else {
124 bug!("ExternDecl not a valid directive")
125 };
126 if tokens.len() < 2 {
127 return Err(CompileError::InvalidExternDecl {
128 span: span.clone(),
129 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
130 });
131 }
132 let mut args = Vec::new();
133 let mut i = 1;
134 while i < tokens.len() {
135 match &tokens[i] {
136 Token::Identifier(name, span) => {
137 args.push(Token::Identifier(name.clone(), span.clone()));
138 i += 1;
139 }
140 _ => {
141 break;
142 }
143 }
144 }
145 //
146 if args.is_empty() {
147 Err(CompileError::InvalidExternDecl {
148 span: span.clone(),
149 custom_label: Some(EXPECTS_IDEN.to_string()),
150 })
151 } else {
152 Ok((
153 ExternDecl {
154 args,
155 span: span.clone(),
156 },
157 &tokens[i..],
158 ))
159 }
160 }
161}
162
163impl Parse for ROData {
164 fn parse(tokens: &[Token]) -> Result<(Self, &[Token]), CompileError> {
165 let Token::Label(_, span) = &tokens[0] else {
166 bug!("ROData not a valid directive")
167 };
168 if tokens.len() < 3 {
169 return Err(CompileError::InvalidRodataDecl {
170 span: span.clone(),
171 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
172 });
173 }
174
175 let mut args = Vec::new();
176 match (&tokens[0], &tokens[1], &tokens[2]) {
177 (Token::Label(name, span), Token::Directive(_, _), Token::StringLiteral(_, _)) => {
178 args.push(tokens[1].clone());
179 args.push(tokens[2].clone());
180 Ok((
181 ROData {
182 name: name.clone(),
183 args,
184 span: span.clone(),
185 },
186 &tokens[3..],
187 ))
188 }
189 (Token::Label(name, span), Token::Directive(_, _), Token::ImmediateValue(val, _)) => {
190 let mut data_vector = vec![val.clone()];
191 let idx = parse_vector_literal(tokens, &mut data_vector, 3);
192 args.push(tokens[1].clone());
193 args.push(Token::VectorLiteral(data_vector, span.clone()));
194 Ok((
195 ROData {
196 name: name.clone(),
197 args,
198 span: span.clone(),
199 },
200 &tokens[idx..],
201 ))
202 }
203 _ => Err(CompileError::InvalidRodataDecl {
204 span: span.clone(),
205 custom_label: Some(EXPECTS_LABEL_DIR_STR.to_string()),
206 }),
207 }
208 }
209}
210
211impl ParseWithConstMap for Instruction {
212 fn parse_with_constmap<'a>(
213 tokens: &'a [Token],
214 const_map: &HashMap<String, ImmediateValue>,
215 ) -> Result<(Self, &'a [Token]), CompileError> {
216 let next_token_num;
217 match &tokens[0] {
218 Token::Opcode(opcode, span) => {
219 let mut opcode = *opcode;
220 let mut operands = Vec::new();
221 match opcode {
222 Opcode::Lddw => {
223 if tokens.len() < 4 {
224 return Err(CompileError::InvalidInstruction {
225 //
226 instruction: opcode.to_string(), //
227 span: span.clone(), //
228 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
229 });
230 }
231 let (value, advance_token_num) =
232 inline_and_fold_constant(tokens, const_map, 3);
233 if let Some(value) = value {
234 match (
235 &tokens[1],
236 &tokens[2],
237 // Third operand is folded to an immediate value
238 ) {
239 (
240 Token::Register(_, _),
241 Token::Comma(_),
242 // Third operand is folded to an immediate value
243 ) => {
244 operands.push(tokens[1].clone());
245 operands.push(Token::ImmediateValue(value, span.clone()));
246 }
247 _ => {
248 return Err(CompileError::InvalidInstruction {
249 //
250 instruction: opcode.to_string(), //
251 span: span.clone(), //
252 custom_label: Some(EXPECTS_REG_COM_IMM_OR_IDEN.to_string()),
253 });
254 }
255 }
256 next_token_num = advance_token_num;
257 } else {
258 match (&tokens[1], &tokens[2], &tokens[3]) {
259 (
260 Token::Register(_, _),
261 Token::Comma(_),
262 Token::Identifier(_, _),
263 ) => {
264 operands.push(tokens[1].clone());
265 operands.push(tokens[3].clone());
266 }
267 _ => {
268 return Err(CompileError::InvalidInstruction {
269 //
270 instruction: opcode.to_string(), //
271 span: span.clone(), //
272 custom_label: Some(EXPECTS_REG_COM_IMM_OR_IDEN.to_string()),
273 });
274 }
275 }
276 next_token_num = 4;
277 }
278 }
279 Opcode::Ldxw | Opcode::Ldxh | Opcode::Ldxb | Opcode::Ldxdw => {
280 if tokens.len() < 8 {
281 return Err(CompileError::InvalidInstruction {
282 //
283 instruction: opcode.to_string(), //
284 span: span.clone(), //
285 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
286 });
287 }
288 let (value, advance_token_num) =
289 inline_and_fold_constant(tokens, const_map, 6);
290 if let Some(value) = value {
291 match (
292 &tokens[1],
293 &tokens[2],
294 &tokens[3],
295 &tokens[4],
296 &tokens[5],
297 // Sixth operand is folded to an immediate value
298 &tokens[advance_token_num],
299 ) {
300 (
301 Token::Register(_, _),
302 Token::Comma(_),
303 Token::LeftBracket(_),
304 Token::Register(_, _),
305 Token::BinaryOp(_, _),
306 // Sixth operand is folded to an immediate value
307 Token::RightBracket(_),
308 ) => {
309 operands.push(tokens[1].clone());
310 operands.push(tokens[4].clone());
311 operands.push(Token::ImmediateValue(value, span.clone()));
312 }
313 _ => {
314 return Err(CompileError::InvalidInstruction {
315 //
316 instruction: opcode.to_string(), //
317 span: span.clone(), //
318 custom_label: Some(
319 EXPECTS_REG_COM_LB_REG_BIOP_IMM_RB.to_string(),
320 ),
321 });
322 }
323 }
324 next_token_num = advance_token_num + 1;
325 } else {
326 return Err(CompileError::InvalidInstruction {
327 //
328 instruction: opcode.to_string(), //
329 span: span.clone(), //
330 custom_label: Some(EXPECTS_REG_COM_LB_REG_BIOP_IMM_RB.to_string()),
331 });
332 }
333 }
334 Opcode::Stw | Opcode::Sth | Opcode::Stb | Opcode::Stdw => {
335 if tokens.len() < 8 {
336 return Err(CompileError::InvalidInstruction {
337 //
338 instruction: opcode.to_string(), //
339 span: span.clone(), //
340 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
341 });
342 }
343 let (value, advance_token_num) =
344 inline_and_fold_constant(tokens, const_map, 4);
345 if let Some(value) = value {
346 // Now we need to fold the second immediate value (after the comma)
347 let (value2, advance_token_num2) =
348 inline_and_fold_constant(tokens, const_map, advance_token_num + 2);
349 if let Some(value2) = value2 {
350 match (
351 &tokens[1],
352 &tokens[2],
353 &tokens[3],
354 // Fourth operand is folded to an immediate value
355 &tokens[advance_token_num],
356 &tokens[advance_token_num + 1],
357 // Sixth operand is also folded to an immediate value
358 ) {
359 (
360 Token::LeftBracket(_),
361 Token::Register(_, _),
362 Token::BinaryOp(_, _),
363 // Fourth operand is folded to an immediate value
364 Token::RightBracket(_),
365 Token::Comma(_),
366 ) => {
367 operands.push(tokens[2].clone());
368 operands.push(Token::ImmediateValue(value2, span.clone()));
369 operands.push(Token::ImmediateValue(value, span.clone()));
370 }
371 _ => {
372 return Err(CompileError::InvalidInstruction {
373 //
374 instruction: opcode.to_string(), //
375 span: span.clone(), //
376 custom_label: Some(
377 EXPECTS_LB_REG_BIOP_IMM_RB_COM_IMM.to_string(),
378 ),
379 });
380 }
381 }
382 next_token_num = advance_token_num2;
383 } else {
384 return Err(CompileError::InvalidInstruction {
385 //
386 instruction: opcode.to_string(), //
387 span: span.clone(), //
388 custom_label: Some(
389 EXPECTS_LB_REG_BIOP_IMM_RB_COM_IMM.to_string(),
390 ),
391 });
392 }
393 } else {
394 return Err(CompileError::InvalidInstruction {
395 //
396 instruction: opcode.to_string(), //
397 span: span.clone(), //
398 custom_label: Some(EXPECTS_LB_REG_BIOP_IMM_RB_COM_IMM.to_string()),
399 });
400 }
401 }
402 Opcode::Stxb | Opcode::Stxh | Opcode::Stxw | Opcode::Stxdw => {
403 if tokens.len() < 8 {
404 return Err(CompileError::InvalidInstruction {
405 //
406 instruction: opcode.to_string(), //
407 span: span.clone(), //
408 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
409 });
410 }
411 let (value, advance_token_num) =
412 inline_and_fold_constant(tokens, const_map, 4);
413 if let Some(value) = value {
414 match (
415 &tokens[1],
416 &tokens[2],
417 &tokens[3],
418 // Fourth operand is folded to an immediate value
419 &tokens[advance_token_num],
420 &tokens[advance_token_num + 1],
421 &tokens[advance_token_num + 2],
422 ) {
423 (
424 Token::LeftBracket(_),
425 Token::Register(_, _),
426 Token::BinaryOp(_, _),
427 // Fourth operand is folded to an immediate value
428 Token::RightBracket(_),
429 Token::Comma(_),
430 Token::Register(_, _),
431 ) => {
432 operands.push(tokens[2].clone());
433 operands.push(Token::ImmediateValue(value, span.clone()));
434 operands.push(tokens[advance_token_num + 2].clone());
435 }
436 _ => {
437 return Err(CompileError::InvalidInstruction {
438 //
439 instruction: opcode.to_string(), //
440 span: span.clone(), //
441 custom_label: Some(
442 EXPECTS_LB_REG_BIOP_IMM_RB_COM_REG.to_string(),
443 ),
444 });
445 }
446 }
447 next_token_num = advance_token_num + 3;
448 } else {
449 return Err(CompileError::InvalidInstruction {
450 //
451 instruction: opcode.to_string(), //
452 span: span.clone(), //
453 custom_label: Some(EXPECTS_LB_REG_BIOP_IMM_RB_COM_REG.to_string()),
454 });
455 }
456 }
457 Opcode::Add32
458 | Opcode::Sub32
459 | Opcode::Mul32
460 | Opcode::Div32
461 | Opcode::Or32
462 | Opcode::And32
463 | Opcode::Lsh32
464 | Opcode::Rsh32
465 | Opcode::Mod32
466 | Opcode::Xor32
467 | Opcode::Mov32
468 | Opcode::Arsh32
469 | Opcode::Lmul32
470 | Opcode::Udiv32
471 | Opcode::Urem32
472 | Opcode::Sdiv32
473 | Opcode::Srem32
474 | Opcode::Add64
475 | Opcode::Sub64
476 | Opcode::Mul64
477 | Opcode::Div64
478 | Opcode::Or64
479 | Opcode::And64
480 | Opcode::Lsh64
481 | Opcode::Rsh64
482 | Opcode::Mod64
483 | Opcode::Xor64
484 | Opcode::Mov64
485 | Opcode::Arsh64
486 | Opcode::Lmul64
487 | Opcode::Uhmul64
488 | Opcode::Udiv64
489 | Opcode::Urem64
490 | Opcode::Sdiv64
491 | Opcode::Srem64 => {
492 if tokens.len() < 4 {
493 return Err(CompileError::InvalidInstruction {
494 //
495 instruction: opcode.to_string(), //
496 span: span.clone(), //
497 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
498 });
499 }
500 let (value, advance_token_num) =
501 inline_and_fold_constant(tokens, const_map, 3);
502 if let Some(value) = value {
503 match (
504 &tokens[1],
505 &tokens[2],
506 // Third operand is folded to an immediate value
507 ) {
508 (
509 Token::Register(_, _),
510 Token::Comma(_),
511 // Third operand is folded to an immediate value
512 ) => {
513 opcode = FromPrimitive::from_u8((opcode as u8) + 1)
514 .expect("Invalid opcode conversion");
515 operands.push(tokens[1].clone());
516 operands.push(Token::ImmediateValue(value, span.clone()));
517 }
518 _ => {
519 return Err(CompileError::InvalidInstruction {
520 //
521 instruction: opcode.to_string(), //
522 span: span.clone(), //
523 custom_label: Some(EXPECTS_REG_COM_IMM.to_string()),
524 });
525 }
526 }
527 next_token_num = advance_token_num;
528 } else {
529 match (&tokens[1], &tokens[2], &tokens[3]) {
530 (Token::Register(_, _), Token::Comma(_), Token::Register(_, _)) => {
531 opcode = FromPrimitive::from_u8((opcode as u8) + 2)
532 .expect("Invalid opcode conversion");
533 operands.push(tokens[1].clone());
534 operands.push(tokens[3].clone());
535 }
536 _ => {
537 return Err(CompileError::InvalidInstruction {
538 //
539 instruction: opcode.to_string(), //
540 span: span.clone(), //
541 custom_label: Some(EXPECTS_REG_COM_REG.to_string()),
542 });
543 }
544 }
545 next_token_num = 4;
546 }
547 }
548 Opcode::Be | Opcode::Le => {
549 if tokens.len() < 4 {
550 return Err(CompileError::InvalidInstruction {
551 //
552 instruction: opcode.to_string(), //
553 span: span.clone(), //
554 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
555 });
556 }
557 let (value, advance_token_num) =
558 inline_and_fold_constant(tokens, const_map, 3);
559 if let Some(value) = value {
560 match (
561 &tokens[1],
562 &tokens[2],
563 // Third operand is folded to an immediate value
564 ) {
565 (
566 Token::Register(_, _),
567 Token::Comma(_),
568 // Third operand is folded to an immediate value
569 ) => {
570 operands.push(tokens[1].clone());
571 operands.push(Token::ImmediateValue(value, span.clone()));
572 }
573 _ => {
574 return Err(CompileError::InvalidInstruction {
575 //
576 instruction: opcode.to_string(), //
577 span: span.clone(), //
578 custom_label: Some(EXPECTS_REG_COM_IMM.to_string()),
579 });
580 }
581 }
582 next_token_num = advance_token_num;
583 } else {
584 return Err(CompileError::InvalidInstruction {
585 //
586 instruction: opcode.to_string(), //
587 span: span.clone(), //
588 custom_label: Some(EXPECTS_REG_COM_IMM.to_string()),
589 });
590 }
591 }
592 Opcode::Jeq
593 | Opcode::Jgt
594 | Opcode::Jge
595 | Opcode::Jlt
596 | Opcode::Jle
597 | Opcode::Jset
598 | Opcode::Jne
599 | Opcode::Jsgt
600 | Opcode::Jsge
601 | Opcode::Jslt
602 | Opcode::Jsle => {
603 if tokens.len() < 6 {
604 return Err(CompileError::InvalidInstruction {
605 //
606 instruction: opcode.to_string(), //
607 span: span.clone(), //
608 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
609 });
610 }
611 let (value, advance_token_num) =
612 inline_and_fold_constant(tokens, const_map, 3);
613 if let Some(value) = value {
614 let (jump_val, jump_val_advance_token_num) =
615 inline_and_fold_constant(tokens, const_map, advance_token_num + 1);
616 if let Some(jump_val) = jump_val {
617 match (
618 &tokens[1],
619 &tokens[2],
620 // Third operand is folded to an immediate value
621 &tokens[advance_token_num],
622 // Fifth operand is folded to an immediate value
623 ) {
624 (
625 Token::Register(_, _),
626 Token::Comma(_),
627 // Third operand is folded to an immediate value
628 Token::Comma(_),
629 // Fifth operand is folded to an immediate value
630 ) => {
631 opcode = FromPrimitive::from_u8((opcode as u8) + 1)
632 .expect("Invalid opcode conversion");
633 operands.push(tokens[1].clone());
634 operands.push(Token::ImmediateValue(value, span.clone()));
635 operands
636 .push(Token::ImmediateValue(jump_val, span.clone()));
637 }
638 _ => {
639 return Err(CompileError::InvalidInstruction {
640 instruction: opcode.to_string(),
641 span: span.clone(),
642 custom_label: Some(
643 EXPECTS_REG_COM_IMM_COM_IMM_OR_IDEN.to_string(),
644 ),
645 });
646 }
647 }
648 next_token_num = jump_val_advance_token_num;
649 } else {
650 match (
651 &tokens[1],
652 &tokens[2],
653 // Third operand is folded to an immediate value
654 &tokens[advance_token_num],
655 &tokens[advance_token_num + 1],
656 ) {
657 (
658 Token::Register(_, _),
659 Token::Comma(_),
660 // Third operand is folded to an immediate value
661 Token::Comma(_),
662 Token::Identifier(_, _),
663 ) => {
664 opcode = FromPrimitive::from_u8((opcode as u8) + 1)
665 .expect("Invalid opcode conversion");
666 operands.push(tokens[1].clone());
667 operands.push(Token::ImmediateValue(value, span.clone()));
668 operands.push(tokens[advance_token_num + 1].clone());
669 }
670 _ => {
671 return Err(CompileError::InvalidInstruction {
672 //
673 instruction: opcode.to_string(), //
674 span: span.clone(), //
675 custom_label: Some(
676 EXPECTS_REG_COM_IMM_COM_IMM_OR_IDEN.to_string(),
677 ),
678 });
679 }
680 }
681 next_token_num = advance_token_num + 2;
682 }
683 } else {
684 let (jump_val, jump_val_advance_token_num) =
685 inline_and_fold_constant(tokens, const_map, advance_token_num + 1);
686 if let Some(jump_val) = jump_val {
687 match (
688 &tokens[1], &tokens[2], &tokens[3],
689 &tokens[4],
690 // Fifth operand is folded to an immediate value
691 ) {
692 (
693 Token::Register(_, _),
694 Token::Comma(_),
695 Token::Register(_, _),
696 Token::Comma(_),
697 // Fifth operand is folded to an immediate value
698 ) => {
699 // turn "invalid opcode" to a bug
700 opcode = FromPrimitive::from_u8((opcode as u8) + 2)
701 .expect("Invalid opcode conversion");
702 operands.push(tokens[1].clone());
703 operands.push(tokens[3].clone());
704 operands
705 .push(Token::ImmediateValue(jump_val, span.clone()));
706 }
707 _ => {
708 return Err(CompileError::InvalidInstruction {
709 //
710 instruction: opcode.to_string(), //
711 span: span.clone(), //
712 custom_label: Some(
713 EXPECTS_REG_COM_IMM_COM_IMM_OR_IDEN.to_string(),
714 ),
715 });
716 }
717 }
718 next_token_num = jump_val_advance_token_num;
719 } else {
720 match (&tokens[1], &tokens[2], &tokens[3], &tokens[4], &tokens[5]) {
721 (
722 Token::Register(_, _),
723 Token::Comma(_),
724 Token::Register(_, _),
725 Token::Comma(_),
726 Token::Identifier(_, _),
727 ) => {
728 // turn "invalid opcode" to a bug
729 opcode = FromPrimitive::from_u8((opcode as u8) + 2)
730 .expect("Invalid opcode conversion");
731 operands.push(tokens[1].clone());
732 operands.push(tokens[3].clone());
733 operands.push(tokens[5].clone());
734 }
735 _ => {
736 return Err(CompileError::InvalidInstruction {
737 //
738 instruction: opcode.to_string(), //
739 span: span.clone(), //
740 custom_label: Some(
741 EXPECTS_REG_COM_IMM_COM_IMM_OR_IDEN.to_string(),
742 ),
743 });
744 }
745 }
746 next_token_num = 6;
747 }
748 }
749 }
750 Opcode::Neg32 | Opcode::Neg64 => {
751 if tokens.len() < 2 {
752 return Err(CompileError::InvalidInstruction {
753 //
754 instruction: opcode.to_string(), //
755 span: span.clone(), //
756 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
757 });
758 }
759 match &tokens[1] {
760 Token::Register(_, _) => {
761 operands.push(tokens[1].clone());
762 }
763 _ => {
764 return Err(CompileError::InvalidInstruction {
765 //
766 instruction: opcode.to_string(), //
767 span: span.clone(), //
768 custom_label: Some(EXPECTS_REG.to_string()),
769 });
770 }
771 }
772 next_token_num = 2;
773 }
774 Opcode::Ja => {
775 if tokens.len() < 2 {
776 return Err(CompileError::InvalidInstruction {
777 //
778 instruction: opcode.to_string(), //
779 span: span.clone(), //
780 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
781 });
782 }
783 let (value, advance_token_num) =
784 inline_and_fold_constant(tokens, const_map, 1);
785 if let Some(value) = value {
786 operands.push(Token::ImmediateValue(value, span.clone()));
787 next_token_num = advance_token_num;
788 } else {
789 match &tokens[1] {
790 Token::Identifier(_, _) => {
791 operands.push(tokens[1].clone());
792 }
793 _ => {
794 return Err(CompileError::InvalidInstruction {
795 //
796 instruction: opcode.to_string(), //
797 span: span.clone(), //
798 custom_label: Some(EXPECTS_IDEN.to_string()),
799 });
800 }
801 }
802 next_token_num = 2;
803 }
804 }
805 Opcode::Call => {
806 if tokens.len() < 2 {
807 return Err(CompileError::InvalidInstruction {
808 //
809 instruction: opcode.to_string(), //
810 span: span.clone(), //
811 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
812 });
813 }
814 match &tokens[1] {
815 Token::Identifier(_, _) => {
816 operands.push(tokens[1].clone());
817 }
818 _ => {
819 return Err(CompileError::InvalidInstruction {
820 //
821 instruction: opcode.to_string(), //
822 span: span.clone(), //
823 custom_label: Some(EXPECTS_IDEN.to_string()),
824 });
825 }
826 }
827 next_token_num = 2;
828 }
829 Opcode::Callx => {
830 if tokens.len() < 2 {
831 return Err(CompileError::InvalidInstruction {
832 //
833 instruction: opcode.to_string(), //
834 span: span.clone(), //
835 custom_label: Some(EXPECTS_MORE_OPERAND.to_string()),
836 });
837 }
838 match &tokens[1] {
839 Token::Register(_, _) => {
840 operands.push(tokens[1].clone());
841 }
842 _ => {
843 return Err(CompileError::InvalidInstruction {
844 //
845 instruction: opcode.to_string(), //
846 span: span.clone(), //
847 custom_label: Some(EXPECTS_IDEN.to_string()),
848 });
849 }
850 }
851 next_token_num = 2;
852 }
853 Opcode::Exit => {
854 next_token_num = 1;
855 }
856 _ => {
857 bug!("invalid opcode: {}", opcode.to_str());
858 }
859 }
860 Ok((
861 Instruction {
862 opcode,
863 operands,
864 span: span.clone(),
865 },
866 &tokens[next_token_num..],
867 ))
868 }
869 _ => {
870 bug!("invalid instruction");
871 }
872 }
873 }
874}
875
876fn parse_vector_literal(
877 tokens: &[Token],
878 stack: &mut Vec<ImmediateValue>,
879 start_idx: usize,
880) -> usize {
881 let mut idx = start_idx;
882 while idx < tokens.len() - 1 {
883 match (&tokens[idx], &tokens[idx + 1]) {
884 (Token::Comma(_), Token::ImmediateValue(val, _)) => {
885 stack.push(val.clone());
886 idx += 2;
887 }
888 _ => {
889 break;
890 }
891 }
892 }
893 idx
894}
895
896fn fold_top(stack: &mut Vec<Token>) {
897 if stack.len() < 3 {
898 return;
899 }
900
901 if let (
902 Token::ImmediateValue(val1, _),
903 Token::BinaryOp(op, _),
904 Token::ImmediateValue(val2, span),
905 ) = (
906 stack[stack.len() - 3].clone(),
907 stack[stack.len() - 2].clone(),
908 stack[stack.len() - 1].clone(),
909 ) {
910 let result = match op {
911 Op::Add => val1.clone() + val2.clone(),
912 Op::Sub => val1.clone() - val2.clone(),
913 Op::Mul => val1.clone() * val2.clone(),
914 Op::Div => val1.clone() / val2.clone(),
915 };
916 stack.pop();
917 stack.pop();
918 stack.pop();
919 stack.push(Token::ImmediateValue(result, span));
920 }
921}
922
923fn inline_and_fold_constant(
924 tokens: &[Token],
925 const_map: &std::collections::HashMap<String, ImmediateValue>,
926 start_idx: usize,
927) -> (Option<ImmediateValue>, usize) {
928 inline_and_fold_constant_with_map(tokens, Some(const_map), start_idx)
929}
930
931fn inline_and_fold_constant_with_map(
932 tokens: &[Token],
933 const_map: Option<&std::collections::HashMap<String, ImmediateValue>>,
934 start_idx: usize,
935) -> (Option<ImmediateValue>, usize) {
936 let mut stack: Vec<Token> = Vec::new();
937 let mut expect_number = true;
938 let mut idx = start_idx;
939
940 while idx < tokens.len() {
941 match &tokens[idx] {
942 Token::ImmediateValue(val, span) if expect_number => {
943 stack.push(Token::ImmediateValue(val.clone(), span.clone()));
944 expect_number = false;
945
946 // Immediately fold * / if top
947 if stack.len() > 2 {
948 if let Token::BinaryOp(op, _) = &stack[stack.len() - 2] {
949 if matches!(op, Op::Mul | Op::Div) {
950 fold_top(&mut stack);
951 }
952 }
953 }
954 }
955
956 Token::Identifier(name, span) if expect_number => {
957 if let Some(const_map) = const_map {
958 if let Some(val) = const_map.get(name) {
959 stack.push(Token::ImmediateValue(val.clone(), span.clone()));
960 expect_number = false;
961
962 if stack.len() > 2 {
963 if let Token::BinaryOp(op, _) = &stack[stack.len() - 2] {
964 if matches!(op, Op::Mul | Op::Div) {
965 fold_top(&mut stack);
966 }
967 }
968 }
969 } else {
970 return (None, idx);
971 }
972 } else {
973 // error out would be better here
974 return (None, idx);
975 }
976 }
977
978 Token::BinaryOp(op, span) => {
979 match op {
980 Op::Sub if expect_number => {
981 // unary minus → 0 - expr
982 stack.push(Token::ImmediateValue(ImmediateValue::Int(0), span.clone()));
983 stack.push(Token::BinaryOp(Op::Sub, span.clone()));
984 }
985 _ => {
986 stack.push(Token::BinaryOp(op.clone(), span.clone()));
987 }
988 }
989 expect_number = true;
990 }
991
992 Token::LeftParen(span) => {
993 // Parse inside parentheses
994 let (inner_val, new_idx) =
995 inline_and_fold_constant_with_map(tokens, const_map, idx + 1);
996 idx = new_idx;
997 if let Some(v) = inner_val {
998 stack.push(Token::ImmediateValue(v, span.clone()));
999 expect_number = false;
1000
1001 if stack.len() > 2 {
1002 if let Token::BinaryOp(op, _) = &stack[stack.len() - 2] {
1003 if matches!(op, Op::Mul | Op::Div) {
1004 fold_top(&mut stack);
1005 }
1006 }
1007 }
1008 } else {
1009 return (None, idx);
1010 }
1011 continue; // skip normal idx++
1012 }
1013
1014 Token::RightParen(_) => {
1015 // fold remaining + and -
1016 while stack.len() > 2 {
1017 fold_top(&mut stack);
1018 }
1019 if let Token::ImmediateValue(v, _) = &stack[0] {
1020 return (Some(v.clone()), idx + 1);
1021 } else {
1022 return (None, idx + 1);
1023 }
1024 }
1025
1026 _ => {
1027 // Unexpected token, stop
1028 break;
1029 }
1030 }
1031 idx += 1;
1032 }
1033
1034 // Final fold at the end of expression
1035 while stack.len() > 2 {
1036 fold_top(&mut stack);
1037 }
1038
1039 if let Some(Token::ImmediateValue(v, _)) = stack.pop() {
1040 (Some(v), idx)
1041 } else {
1042 (None, idx)
1043 }
1044}
1045
1046pub fn parse_tokens(mut tokens: &[Token]) -> Result<ParseResult, Vec<CompileError>> {
1047 let mut ast = AST::new();
1048
1049 let mut rodata_phase = false;
1050 let mut accum_offset = 0;
1051 let mut rodata_accum_offset = 0;
1052 let mut const_map = HashMap::<String, ImmediateValue>::new();
1053 let mut label_spans = HashMap::<String, std::ops::Range<usize>>::new();
1054 let mut errors = Vec::new();
1055
1056 while !tokens.is_empty() {
1057 match &tokens[0] {
1058 Token::Directive(name, span) => match name.as_str() {
1059 "global" | "globl" => match GlobalDecl::parse(tokens) {
1060 Ok((node, rest)) => {
1061 ast.entry_label = Some(node.get_entry_label());
1062 ast.nodes.push(ASTNode::GlobalDecl { global_decl: node });
1063 tokens = rest;
1064 }
1065 Err(e) => {
1066 errors.push(e);
1067 tokens = &tokens[1..];
1068 }
1069 },
1070 "extern" => match ExternDecl::parse(tokens) {
1071 Ok((node, rest)) => {
1072 ast.nodes.push(ASTNode::ExternDecl { extern_decl: node });
1073 tokens = rest;
1074 }
1075 Err(e) => {
1076 errors.push(e);
1077 tokens = &tokens[1..];
1078 }
1079 },
1080 "text" => {
1081 rodata_phase = false;
1082 tokens = &tokens[1..];
1083 }
1084 "rodata" => {
1085 ast.nodes.push(ASTNode::RodataDecl {
1086 rodata_decl: RodataDecl { span: span.clone() },
1087 });
1088 rodata_phase = true;
1089 tokens = &tokens[1..];
1090 }
1091 "equ" => match EquDecl::parse_with_constmap(tokens, &const_map) {
1092 Ok((node, rest)) => {
1093 const_map.insert(node.get_name(), node.get_val());
1094 ast.nodes.push(ASTNode::EquDecl { equ_decl: node });
1095 tokens = rest;
1096 }
1097 Err(e) => {
1098 errors.push(e);
1099 tokens = &tokens[1..];
1100 }
1101 },
1102 "section" => {
1103 ast.nodes.push(ASTNode::Directive {
1104 directive: Directive {
1105 name: name.clone(),
1106 args: Vec::new(),
1107 span: span.clone(),
1108 },
1109 });
1110 tokens = &tokens[1..];
1111 }
1112 _ => {
1113 errors.push(CompileError::InvalidDirective {
1114 directive: name.clone(),
1115 span: span.clone(),
1116 custom_label: None,
1117 });
1118 tokens = &tokens[1..];
1119 }
1120 },
1121 Token::Label(name, span) => {
1122 if rodata_phase {
1123 match ROData::parse(tokens) {
1124 Ok((rodata, rest)) => {
1125 if label_spans.contains_key(name) {
1126 let original_span =
1127 label_spans.get(name).cloned().unwrap_or(span.clone());
1128 errors.push(CompileError::DuplicateLabel {
1129 label: name.clone(),
1130 span: span.clone(),
1131 original_span,
1132 custom_label: Some(LABEL_REDEFINED.to_string()),
1133 });
1134 } else {
1135 label_spans.insert(name.clone(), span.clone());
1136 if let Err(e) = rodata.verify() {
1137 errors.push(e);
1138 }
1139 }
1140 let rodata_size = rodata.get_size();
1141 ast.rodata_nodes.push(ASTNode::ROData {
1142 rodata,
1143 offset: rodata_accum_offset,
1144 });
1145 rodata_accum_offset += rodata_size;
1146 tokens = rest;
1147 }
1148 Err(e) => {
1149 errors.push(e);
1150 tokens = &tokens[1..];
1151 }
1152 }
1153 } else {
1154 if label_spans.contains_key(name) {
1155 let original_span = label_spans.get(name).cloned().unwrap_or(span.clone());
1156 errors.push(CompileError::DuplicateLabel {
1157 label: name.clone(),
1158 span: span.clone(),
1159 original_span,
1160 custom_label: Some(LABEL_REDEFINED.to_string()),
1161 });
1162 } else {
1163 label_spans.insert(name.clone(), span.clone());
1164 }
1165 ast.nodes.push(ASTNode::Label {
1166 label: Label {
1167 name: name.clone(),
1168 span: span.clone(),
1169 },
1170 offset: accum_offset,
1171 });
1172 tokens = &tokens[1..];
1173 }
1174 }
1175 Token::Opcode(_, _) => match Instruction::parse_with_constmap(tokens, &const_map) {
1176 Ok((inst, rest)) => {
1177 let offset = accum_offset;
1178 accum_offset += inst.get_size();
1179 ast.nodes.push(ASTNode::Instruction {
1180 instruction: inst,
1181 offset,
1182 });
1183 tokens = rest;
1184 }
1185 Err(e) => {
1186 errors.push(e);
1187 tokens = &tokens[1..];
1188 }
1189 },
1190 _ => {
1191 tokens = &tokens[1..];
1192 }
1193 }
1194 }
1195
1196 if !errors.is_empty() {
1197 return Err(errors);
1198 }
1199
1200 ast.set_text_size(accum_offset);
1201 ast.set_rodata_size(rodata_accum_offset);
1202
1203 let parse_result = ast.build_program();
1204 if let Ok(parse_result) = parse_result {
1205 Ok(parse_result)
1206 } else {
1207 Err(parse_result.err().unwrap())
1208 }
1209}