1use crate::lexer::Op;
2use crate::opcode::Opcode;
3use crate::lexer::{Token, ImmediateValue};
4use crate::section::{CodeSection, DataSection};
5use crate::ast::AST;
6use crate::astnode::{ASTNode, Directive, GlobalDecl, EquDecl, ExternDecl, RodataDecl, Label, ROData};
7use crate::instruction::Instruction;
8use crate::dynsym::{DynamicSymbolMap, RelDynMap};
9use num_traits::FromPrimitive;
10use std::collections::HashMap;
11use crate::errors::CompileError;
12use crate::messages::*;
13use crate::bug;
14
15pub struct ParseResult {
16 pub code_section: CodeSection,
18
19 pub data_section: DataSection,
20
21 pub dynamic_symbols: DynamicSymbolMap,
22
23 pub relocation_data: RelDynMap,
24
25 pub prog_is_static: bool,
28}
29
30pub trait Parse {
32 fn parse(tokens: &[Token]) -> Result<(Self, &[Token]), CompileError>
33 where Self: Sized;
34}
35
36pub trait ParseWithConstMap {
37 fn parse_with_constmap<'a>(tokens: &'a [Token], const_map: &HashMap<String, ImmediateValue>) -> Result<(Self, &'a [Token]), CompileError>
38 where Self: Sized;
39}
40
41impl Parse for GlobalDecl {
42 fn parse(tokens: &[Token]) -> Result<(Self, &[Token]), CompileError> {
43 let Token::Directive(_, span) = &tokens[0] else { bug!("GlobalDecl not a valid directive") };
44 if tokens.len() < 2 {
45 return Err(CompileError::InvalidGlobalDecl { span: span.clone(), custom_label: None });
46 }
47 match &tokens[1] {
48 Token::Identifier(name, span) => Ok((
49 GlobalDecl {
50 entry_label: name.clone(),
51 span: span.clone()
52 },
53 &tokens[2..])),
54 _ => Err(CompileError::InvalidGlobalDecl { span: span.clone(), custom_label: None }),
55 }
56 }
57}
58
59impl ParseWithConstMap for EquDecl {
60 fn parse_with_constmap<'a>(tokens: &'a [Token], const_map: &HashMap<String, ImmediateValue>) -> Result<(Self, &'a [Token]), CompileError> {
61 let Token::Directive(_, span) = &tokens[0] else { bug!("EquDecl not a valid directive") };
62 if tokens.len() < 3 {
63 return Err(CompileError::InvalidEquDecl { span: span.clone(), custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
64 }
65 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 3);
66 if let Some(value) = value {
67 match (
68 &tokens[1],
69 &tokens[2],
70 ) {
72 (
73 Token::Identifier(name, span),
74 Token::Comma(_),
75 ) => {
77 Ok((
78 EquDecl {
79 name: name.clone(),
80 value: Token::ImmediateValue(value, span.clone()),
81 span: span.clone()
82 },
83 &tokens[advance_token_num..]
84 ))
85 }
86 _ => Err(CompileError::InvalidEquDecl { span: span.clone(), custom_label: Some(EXPECTS_IDEN_COM_IMM.to_string()) }),
87 }
88 } else {
89 Err(CompileError::InvalidEquDecl { span: span.clone(), custom_label: Some(EXPECTS_IDEN_COM_IMM.to_string()) })
90 }
91
92 }
93}
94
95impl Parse for ExternDecl {
96 fn parse(tokens: &[Token]) -> Result<(Self, &[Token]), CompileError> {
97 let Token::Directive(_, span) = &tokens[0] else { bug!("ExternDecl not a valid directive") };
98 if tokens.len() < 2 {
99 return Err(CompileError::InvalidExternDecl { span: span.clone(), custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
100 }
101 let mut args = Vec::new();
102 let mut i = 1;
103 while i < tokens.len() {
104 match &tokens[i] {
105 Token::Identifier(name, span) => {
106 args.push(Token::Identifier(name.clone(), span.clone()));
107 i += 1;
108 }
109 _ => {
110 break;
111 }
112 }
113 }
114 if args.is_empty() {
116 Err(CompileError::InvalidExternDecl { span: span.clone(), custom_label: Some(EXPECTS_IDEN.to_string()) })
117 } else {
118 Ok((
119 ExternDecl {
120 args,
121 span: span.clone()
122 },
123 &tokens[i..]
124 ))
125 }
126 }
127}
128
129impl Parse for ROData {
130 fn parse(tokens: &[Token]) -> Result<(Self, &[Token]), CompileError> {
131 let Token::Label(_, span) = &tokens[0] else { bug!("ROData not a valid directive") };
132 if tokens.len() < 3 {
133 return Err(CompileError::InvalidRodataDecl { span: span.clone(), custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
134 }
135
136 let mut args = Vec::new();
137 match (
138 &tokens[0],
139 &tokens[1],
140 &tokens[2],
141 ) {
142 (
143 Token::Label(name, span),
144 Token::Directive(_, _),
145 Token::StringLiteral(_, _)
146 ) => {
147 args.push(tokens[1].clone());
148 args.push(tokens[2].clone());
149 Ok((
150 ROData {
151 name: name.clone(),
152 args,
153 span: span.clone()
154 },
155 &tokens[3..]
156 ))
157 }
158 (
159 Token::Label(name, span),
160 Token::Directive(_, _),
161 Token::ImmediateValue(val, _)
162 ) => {
163 let mut data_vector = vec![val.clone()];
164 let idx = parse_vector_literal(tokens, &mut data_vector, 3);
165 args.push(tokens[1].clone());
166 args.push(Token::VectorLiteral(data_vector, span.clone()));
167 Ok((
168 ROData {
169 name: name.clone(),
170 args,
171 span: span.clone()
172 },
173 &tokens[idx..]
174 ))
175 }
176 _ => Err(CompileError::InvalidRodataDecl { span: span.clone(), custom_label: Some(EXPECTS_LABEL_DIR_STR.to_string()) }),
177 }
178 }
179}
180
181impl ParseWithConstMap for Instruction {
182 fn parse_with_constmap<'a>(tokens: &'a [Token], const_map: &HashMap<String, ImmediateValue>) -> Result<(Self, &'a [Token]), CompileError> {
183 let next_token_num;
184 match &tokens[0] {
185 Token::Opcode(opcode, span) => {
186 let mut opcode = opcode.clone();
187 let mut operands = Vec::new();
188 match opcode {
189 Opcode::Lddw => {
190 if tokens.len() < 4 {
191 return Err(
192 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
196 }
197 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 3);
198 if let Some(value) = value {
199 match (
200 &tokens[1],
201 &tokens[2],
202 ) {
204 (
205 Token::Register(_, _),
206 Token::Comma(_),
207 ) => {
209 operands.push(tokens[1].clone());
210 operands.push(Token::ImmediateValue(value, span.clone()));
211 }
212 _ => {
213 return Err(
214 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_IMM_OR_IDEN.to_string()) });
218 }
219 }
220 next_token_num = advance_token_num;
221 } else {
222 match (
223 &tokens[1],
224 &tokens[2],
225 &tokens[3],
226 ) {
227 (
228 Token::Register(_, _),
229 Token::Comma(_),
230 Token::Identifier(_, _)
231 ) => {
232 operands.push(tokens[1].clone());
233 operands.push(tokens[3].clone());
234 }
235 _ => {
236 return Err(
237 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_IMM_OR_IDEN.to_string()) });
241 }
242 }
243 next_token_num = 4;
244 }
245 }
246 Opcode::Ldxw | Opcode::Ldxh | Opcode::Ldxb | Opcode::Ldxdw => {
247 if tokens.len() < 8 {
248 return Err(
249 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
253 }
254 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 6);
255 if let Some(value) = value {
256 match (
257 &tokens[1],
258 &tokens[2],
259 &tokens[3],
260 &tokens[4],
261 &tokens[5],
262 &tokens[advance_token_num],
264 ) {
265 (
266 Token::Register(_, _),
267 Token::Comma(_),
268 Token::LeftBracket(_),
269 Token::Register(_, _),
270 Token::BinaryOp(_, _),
271 Token::RightBracket(_)
273 ) => {
274 operands.push(tokens[1].clone());
275 operands.push(tokens[4].clone());
276 operands.push(Token::ImmediateValue(value, span.clone()));
277 }
278 _ => {
279 return Err(
280 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_LB_REG_BIOP_IMM_RB.to_string()) });
284 }
285 }
286 next_token_num = advance_token_num + 1;
287 } else {
288 return Err(
289 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_LB_REG_BIOP_IMM_RB.to_string()) });
293 }
294 }
295 Opcode::Stw | Opcode::Sth | Opcode::Stb | Opcode::Stdw => {
296 if tokens.len() < 8 {
297 return Err(
298 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
302 }
303 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 4);
304 if let Some(value) = value {
305 let (value2, advance_token_num2) = inline_and_fold_constant(tokens, const_map, advance_token_num + 2);
307 if let Some(value2) = value2 {
308 match (
309 &tokens[1],
310 &tokens[2],
311 &tokens[3],
312 &tokens[advance_token_num],
314 &tokens[advance_token_num + 1],
315 ) {
317 (
318 Token::LeftBracket(_),
319 Token::Register(_, _),
320 Token::BinaryOp(_, _),
321 Token::RightBracket(_),
323 Token::Comma(_),
324 ) => {
325 operands.push(tokens[2].clone());
326 operands.push(Token::ImmediateValue(value2, span.clone()));
327 operands.push(Token::ImmediateValue(value, span.clone()));
328 }
329 _ => {
330 return Err(
331 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_LB_REG_BIOP_IMM_RB_COM_IMM.to_string()) });
335 }
336 }
337 next_token_num = advance_token_num2;
338 } else {
339 return Err(
340 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_LB_REG_BIOP_IMM_RB_COM_IMM.to_string()) });
344 }
345 } else {
346 return Err(
347 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_LB_REG_BIOP_IMM_RB_COM_IMM.to_string()) });
351 }
352 }
353 | Opcode::Stxb | Opcode::Stxh | Opcode::Stxw | Opcode::Stxdw => {
354 if tokens.len() < 8 {
355 return Err(
356 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
360 }
361 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 4);
362 if let Some(value) = value {
363 match (
364 &tokens[1],
365 &tokens[2],
366 &tokens[3],
367 &tokens[advance_token_num],
369 &tokens[advance_token_num + 1],
370 &tokens[advance_token_num + 2],
371 ) {
372 (
373 Token::LeftBracket(_),
374 Token::Register(_, _),
375 Token::BinaryOp(_, _),
376 Token::RightBracket(_),
378 Token::Comma(_),
379 Token::Register(_, _)
380 ) => {
381 operands.push(tokens[2].clone());
382 operands.push(Token::ImmediateValue(value, span.clone()));
383 operands.push(tokens[advance_token_num + 2].clone());
384 }
385 _ => {
386 return Err(
387 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_LB_REG_BIOP_IMM_RB_COM_REG.to_string()) });
391 }
392 }
393 next_token_num = advance_token_num + 3;
394 } else {
395 return Err(
396 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_LB_REG_BIOP_IMM_RB_COM_REG.to_string()) });
400 }
401 }
402 Opcode::Add32 | Opcode::Sub32 | Opcode::Mul32
403 | Opcode::Div32 | Opcode::Or32 | Opcode::And32
404 | Opcode::Lsh32 | Opcode::Rsh32 | Opcode::Mod32
405 | Opcode::Xor32 | Opcode::Mov32 | Opcode::Arsh32
406 | Opcode::Lmul32 | Opcode::Udiv32 | Opcode::Urem32
407 | Opcode::Sdiv32 | Opcode::Srem32
408 | Opcode::Add64 | Opcode::Sub64 | Opcode::Mul64
409 | Opcode::Div64 | Opcode::Or64 | Opcode::And64
410 | Opcode::Lsh64 | Opcode::Rsh64 | Opcode::Mod64
411 | Opcode::Xor64 | Opcode::Mov64 | Opcode::Arsh64
412 | Opcode::Lmul64 | Opcode::Uhmul64 | Opcode::Udiv64
413 | Opcode::Urem64 | Opcode::Sdiv64 | Opcode::Srem64 => {
414 if tokens.len() < 4 {
415 return Err(
416 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
420 }
421 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 3);
422 if let Some(value) = value {
423 match (
424 &tokens[1],
425 &tokens[2],
426 ) {
428 (
429 Token::Register(_, _),
430 Token::Comma(_),
431 ) => {
433 opcode = FromPrimitive::from_u8((opcode as u8) + 1).expect("Invalid opcode conversion");
434 operands.push(tokens[1].clone());
435 operands.push(Token::ImmediateValue(value, span.clone()));
436 }
437 _ => {
438 return Err(
439 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_IMM.to_string()) });
443 }
444 }
445 next_token_num = advance_token_num;
446 } else {
447 match (
448 &tokens[1],
449 &tokens[2],
450 &tokens[3],
451 ) {
452 (
453 Token::Register(_, _),
454 Token::Comma(_),
455 Token::Register(_, _)
456 ) => {
457 opcode = FromPrimitive::from_u8((opcode as u8) + 2).expect("Invalid opcode conversion");
458 operands.push(tokens[1].clone());
459 operands.push(tokens[3].clone());
460 }
461 _ => {
462 return Err(
463 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_REG.to_string()) });
467 }
468 }
469 next_token_num = 4;
470 }
471 }
472 Opcode::Jeq | Opcode::Jgt | Opcode::Jge
473 | Opcode::Jlt | Opcode::Jle | Opcode::Jset
474 | Opcode::Jne | Opcode::Jsgt | Opcode::Jsge
475 | Opcode::Jslt | Opcode::Jsle => {
476 if tokens.len() < 6 {
477 return Err(
478 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
482 }
483 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 3);
484 if let Some(value) = value {
485 let (jump_val, jump_val_advance_token_num) = inline_and_fold_constant(tokens, const_map, advance_token_num + 1);
486 if let Some(jump_val) = jump_val {
487 match (
488 &tokens[1],
489 &tokens[2],
490 &tokens[advance_token_num],
492 ) {
494 (
495 Token::Register(_, _),
496 Token::Comma(_),
497 Token::Comma(_),
499 ) => {
501 opcode = FromPrimitive::from_u8((opcode as u8) + 1).expect("Invalid opcode conversion");
502 operands.push(tokens[1].clone());
503 operands.push(Token::ImmediateValue(value, span.clone()));
504 operands.push(Token::ImmediateValue(jump_val, span.clone()));
505 }
506 _ => {
507 return Err(
508 CompileError::InvalidInstruction {
509 instruction: opcode.to_string()
510 , span: span.clone()
511 , custom_label: Some(EXPECTS_REG_COM_IMM_COM_IMM_OR_IDEN.to_string()) });
512 }
513 }
514 next_token_num = jump_val_advance_token_num;
515 } else {
516 match (
517 &tokens[1],
518 &tokens[2],
519 &tokens[advance_token_num],
521 &tokens[advance_token_num + 1],
522 ) {
523 (
524 Token::Register(_, _),
525 Token::Comma(_),
526 Token::Comma(_),
528 Token::Identifier(_, _)
529 ) => {
530 opcode = FromPrimitive::from_u8((opcode as u8) + 1).expect("Invalid opcode conversion");
531 operands.push(tokens[1].clone());
532 operands.push(Token::ImmediateValue(value, span.clone()));
533 operands.push(tokens[advance_token_num + 1].clone());
534 }
535 _ => {
536 return Err(
537 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_IMM_COM_IMM_OR_IDEN.to_string()) });
541 }
542 }
543 next_token_num = advance_token_num + 2;
544 }
545 } else {
546 let (jump_val, jump_val_advance_token_num) = inline_and_fold_constant(tokens, const_map, advance_token_num + 1);
547 if let Some(jump_val) = jump_val {
548 match (
549 &tokens[1],
550 &tokens[2],
551 &tokens[3],
552 &tokens[4],
553 ) {
555 (
556 Token::Register(_, _),
557 Token::Comma(_),
558 Token::Register(_, _),
559 Token::Comma(_),
560 ) => {
562 opcode = FromPrimitive::from_u8((opcode as u8) + 2).expect("Invalid opcode conversion");
564 operands.push(tokens[1].clone());
565 operands.push(tokens[3].clone());
566 operands.push(Token::ImmediateValue(jump_val, span.clone()));
567 }
568 _ => {
569 return Err(
570 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_IMM_COM_IMM_OR_IDEN.to_string()) });
574 }
575 }
576 next_token_num = jump_val_advance_token_num;
577 } else {
578 match (
579 &tokens[1],
580 &tokens[2],
581 &tokens[3],
582 &tokens[4],
583 &tokens[5],
584 ) {
585 (
586 Token::Register(_, _),
587 Token::Comma(_),
588 Token::Register(_, _),
589 Token::Comma(_),
590 Token::Identifier(_, _)
591 ) => {
592 opcode = FromPrimitive::from_u8((opcode as u8) + 2).expect("Invalid opcode conversion");
594 operands.push(tokens[1].clone());
595 operands.push(tokens[3].clone());
596 operands.push(tokens[5].clone());
597 }
598 _ => {
599 return Err(
600 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG_COM_IMM_COM_IMM_OR_IDEN.to_string()) });
604 }
605 }
606 next_token_num = 6;
607 }
608 }
609 }
610 Opcode::Neg32 | Opcode::Neg64 => {
611 if tokens.len() < 2 {
612 return Err(
613 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
617 }
618 match &tokens[1] {
619 Token::Register(_, _) => {
620 operands.push(tokens[1].clone());
621 }
622 _ => {
623 return Err(
624 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_REG.to_string()) });
628 }
629 }
630 next_token_num = 2;
631 }
632 Opcode::Ja => {
633 if tokens.len() < 2 {
634 return Err(
635 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
639 }
640 let (value, advance_token_num) = inline_and_fold_constant(tokens, const_map, 1);
641 if let Some(value) = value {
642 operands.push(Token::ImmediateValue(value, span.clone()));
643 next_token_num = advance_token_num;
644 } else {
645 match &tokens[1] {
646 Token::Identifier(_, _) => {
647 operands.push(tokens[1].clone());
648 }
649 _ => {
650 return Err(
651 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_IDEN.to_string()) });
655 }
656 }
657 next_token_num = 2;
658 }
659 }
660 Opcode::Call => {
661 if tokens.len() < 2 {
662 return Err(
663 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_MORE_OPERAND.to_string()) });
667 }
668 match &tokens[1] {
669 Token::Identifier(_, _) => {
670 operands.push(tokens[1].clone());
671 }
672 _ => {
673 return Err(
674 CompileError::InvalidInstruction { instruction: opcode.to_string() , span: span.clone() , custom_label: Some(EXPECTS_IDEN.to_string()) });
678 }
679 }
680 next_token_num = 2;
681 }
682 Opcode::Exit => {
683 next_token_num = 1;
684 }
685 _ => {
686 bug!("invalid opcode: {}", opcode.to_str());
687 }
688 }
689 Ok((
690 Instruction {
691 opcode,
692 operands,
693 span: span.clone()
694 },
695 &tokens[next_token_num..]
696 ))
697 }
698 _ => {
699 bug!("invalid instruction");
700 }
701 }
702
703 }
704}
705
706fn parse_vector_literal(tokens: &[Token], stack: &mut Vec<ImmediateValue>, start_idx: usize) -> usize {
707 let mut idx = start_idx;
708 while idx < tokens.len() - 1 {
709 match (&tokens[idx], &tokens[idx + 1]) {
710 (Token::Comma(_), Token::ImmediateValue(val, _)) => {
711 stack.push(val.clone());
712 idx += 2;
713 }
714 _ => {
715 break;
716 }
717 }
718 }
719 idx
720}
721
722fn fold_top(stack: &mut Vec<Token>) {
723 if stack.len() < 3 {
724 return;
725 }
726
727 if let (
728 Token::ImmediateValue(val1, _),
729 Token::BinaryOp(op, _),
730 Token::ImmediateValue(val2, span),
731 ) = (
732 stack[stack.len() - 3].clone(),
733 stack[stack.len() - 2].clone(),
734 stack[stack.len() - 1].clone(),
735 ) {
736 let result = match op {
737 Op::Add => val1.clone() + val2.clone(),
738 Op::Sub => val1.clone() - val2.clone(),
739 Op::Mul => val1.clone() * val2.clone(),
740 Op::Div => val1.clone() / val2.clone(),
741 };
742 stack.pop();
743 stack.pop();
744 stack.pop();
745 stack.push(Token::ImmediateValue(result, span));
746 }
747}
748
749fn inline_and_fold_constant(
750 tokens: &[Token],
751 const_map: &std::collections::HashMap<String, ImmediateValue>,
752 start_idx: usize
753) -> (Option<ImmediateValue>, usize) {
754 inline_and_fold_constant_with_map(tokens, Some(const_map), start_idx)
755}
756
757fn inline_and_fold_constant_with_map(
758 tokens: &[Token],
759 const_map: Option<&std::collections::HashMap<String, ImmediateValue>>,
760 start_idx: usize,
761) -> (Option<ImmediateValue>, usize) {
762 let mut stack: Vec<Token> = Vec::new();
763 let mut expect_number = true;
764 let mut idx = start_idx;
765
766 while idx < tokens.len() {
767 match &tokens[idx] {
768 Token::ImmediateValue(val, span) if expect_number => {
769 stack.push(Token::ImmediateValue(val.clone(), span.clone()));
770 expect_number = false;
771
772 if stack.len() > 2 {
774 if let Token::BinaryOp(op, _) = &stack[stack.len() - 2] {
775 if matches!(op, Op::Mul | Op::Div) {
776 fold_top(&mut stack);
777 }
778 }
779 }
780 }
781
782 Token::Identifier(name, span) if expect_number => {
783 if let Some(const_map) = const_map {
784 if let Some(val) = const_map.get(name) {
785 stack.push(Token::ImmediateValue(val.clone(), span.clone()));
786 expect_number = false;
787
788 if stack.len() > 2 {
789 if let Token::BinaryOp(op, _) = &stack[stack.len() - 2] {
790 if matches!(op, Op::Mul | Op::Div) {
791 fold_top(&mut stack);
792 }
793 }
794 }
795 } else {
796 return (None, idx);
797 }
798 } else {
799 return (None, idx);
801 }
802 }
803
804 Token::BinaryOp(op, span) => {
805 match op {
806 Op::Sub if expect_number => {
807 stack.push(Token::ImmediateValue(ImmediateValue::Int(0), span.clone()));
809 stack.push(Token::BinaryOp(Op::Sub, span.clone()));
810 }
811 _ => {
812 stack.push(Token::BinaryOp(op.clone(), span.clone()));
813 }
814 }
815 expect_number = true;
816 }
817
818 Token::LeftParen(span) => {
819 let (inner_val, new_idx) = inline_and_fold_constant_with_map(tokens, const_map, idx + 1);
821 idx = new_idx;
822 if let Some(v) = inner_val {
823 stack.push(Token::ImmediateValue(v, span.clone()));
824 expect_number = false;
825
826 if stack.len() > 2 {
827 if let Token::BinaryOp(op, _) = &stack[stack.len() - 2] {
828 if matches!(op, Op::Mul | Op::Div) {
829 fold_top(&mut stack);
830 }
831 }
832 }
833 } else {
834 return (None, idx);
835 }
836 continue; }
838
839 Token::RightParen(_) => {
840 while stack.len() > 2 {
842 fold_top(&mut stack);
843 }
844 if let Token::ImmediateValue(v, _) = &stack[0] {
845 return (Some(v.clone()), idx + 1);
846 } else {
847 return (None, idx + 1);
848 }
849 }
850
851 _ => {
852 break;
854 }
855 }
856 idx += 1;
857 }
858
859 while stack.len() > 2 {
861 fold_top(&mut stack);
862 }
863
864 if let Some(Token::ImmediateValue(v, _)) = stack.pop() {
865 (Some(v), idx)
866 } else {
867 (None, idx)
868 }
869}
870
871pub fn parse_tokens(mut tokens: &[Token]) -> Result<ParseResult, Vec<CompileError>> {
872 let mut ast = AST::new();
873
874 let mut rodata_phase = false;
875 let mut accum_offset = 0;
876 let mut rodata_accum_offset = 0;
877 let mut const_map = HashMap::<String, ImmediateValue>::new();
878 let mut label_spans = HashMap::<String, std::ops::Range<usize>>::new();
879 let mut errors = Vec::new();
880
881 while !tokens.is_empty() {
882 match &tokens[0] {
883 Token::Directive(name, span) => {
884 match name.as_str() {
885 "global" | "globl" => {
886 match GlobalDecl::parse(tokens) {
887 Ok((node, rest)) => {
888 ast.entry_label = Some(node.get_entry_label());
889 ast.nodes.push(ASTNode::GlobalDecl { global_decl: node });
890 tokens = rest;
891 }
892 Err(e) => {
893 errors.push(e);
894 tokens = &tokens[1..];
895 }
896 }
897 }
898 "extern" => {
899 match ExternDecl::parse(tokens) {
900 Ok((node, rest)) => {
901 ast.nodes.push(ASTNode::ExternDecl { extern_decl: node });
902 tokens = rest;
903 }
904 Err(e) => {
905 errors.push(e);
906 tokens = &tokens[1..];
907 }
908 }
909 }
910 "text" => {
911 rodata_phase = false;
912 tokens = &tokens[1..];
913 }
914 "rodata" => {
915 ast.nodes.push(ASTNode::RodataDecl { rodata_decl: RodataDecl { span: span.clone() } });
916 rodata_phase = true;
917 tokens = &tokens[1..];
918 }
919 "equ" => {
920 match EquDecl::parse_with_constmap(tokens, &const_map) {
921 Ok((node, rest)) => {
922 const_map.insert(node.get_name(), node.get_val());
923 ast.nodes.push(ASTNode::EquDecl { equ_decl: node });
924 tokens = rest;
925 }
926 Err(e) => {
927 errors.push(e);
928 tokens = &tokens[1..];
929 }
930 }
931 }
932 "section" => {
933 ast.nodes.push(ASTNode::Directive { directive: Directive { name: name.clone(), args: Vec::new(), span: span.clone() } });
934 tokens = &tokens[1..];
935 }
936 _ => {
937 errors.push(CompileError::InvalidDirective { directive: name.clone(), span: span.clone(), custom_label: None });
938 tokens = &tokens[1..];
939 }
940 }
941 }
942 Token::Label(name, span) => {
943 if rodata_phase {
944 match ROData::parse(tokens) {
945 Ok((rodata, rest)) => {
946 if label_spans.contains_key(name) {
947 let original_span = label_spans.get(name).cloned().unwrap_or(span.clone());
948 errors.push(CompileError::DuplicateLabel { label: name.clone(), span: span.clone(), original_span, custom_label: Some(LABEL_REDEFINED.to_string()) });
949 } else {
950 label_spans.insert(name.clone(), span.clone());
951 if let Err(e) = rodata.verify() {
952 errors.push(e);
953 }
954 }
955 let rodata_size = rodata.get_size();
956 ast.rodata_nodes.push(ASTNode::ROData { rodata, offset: rodata_accum_offset });
957 rodata_accum_offset += rodata_size;
958 tokens = rest;
959 }
960 Err(e) => {
961 errors.push(e);
962 tokens = &tokens[1..];
963 }
964 }
965 } else {
966 if label_spans.contains_key(name) {
967 let original_span = label_spans.get(name).cloned().unwrap_or(span.clone());
968 errors.push(CompileError::DuplicateLabel { label: name.clone(), span: span.clone(), original_span, custom_label: Some(LABEL_REDEFINED.to_string()) });
969 } else {
970 label_spans.insert(name.clone(), span.clone());
971 }
972 ast.nodes.push(ASTNode::Label { label: Label { name: name.clone(), span: span.clone() }, offset: accum_offset });
973 tokens = &tokens[1..];
974 }
975 }
976 Token::Opcode(_, _) => {
977 match Instruction::parse_with_constmap(tokens, &const_map) {
978 Ok((inst, rest)) => {
979 let offset = accum_offset;
980 accum_offset += inst.get_size();
981 ast.nodes.push(ASTNode::Instruction { instruction: inst, offset });
982 tokens = rest;
983 }
984 Err(e) => {
985 errors.push(e);
986 tokens = &tokens[1..];
987 }
988 }
989 }
990 _ => {
991 tokens = &tokens[1..];
992 }
993 }
994 }
995
996 if !errors.is_empty() {
997 return Err(errors);
998 }
999
1000 ast.set_text_size(accum_offset);
1001 ast.set_rodata_size(rodata_accum_offset);
1002
1003
1004 let parse_result = ast.build_program();
1005 if let Ok(parse_result) = parse_result {
1006 return Ok(parse_result);
1007 } else {
1008 return Err(parse_result.err().unwrap());
1009 }
1010}