sbpf_assembler/
parser.rs

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    // TODO: parse result is basically 1. static part 2. dynamic part of the program
17    pub code_section: CodeSection,
18
19    pub data_section: DataSection,
20
21    pub dynamic_symbols: DynamicSymbolMap,
22
23    pub relocation_data: RelDynMap,
24
25    // TODO: this can be removed and dynamic-ness should just be 
26    // determined by if there's any dynamic symbol
27    pub prog_is_static: bool,
28}
29
30// for now, we only return one error per parse for simpler error handling
31pub 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                // third operand is folded to an immediate value
71            ) {
72                (
73                    Token::Identifier(name, span),
74                    Token::Comma(_),
75                    // third operand is folded to an immediate value
76                ) => {
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        //
115        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 {  // 
193                                    instruction: opcode.to_string() //
194                                    , span: span.clone()            //
195                                    , 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                                // Third operand is folded to an immediate value
203                            ) {
204                                (
205                                    Token::Register(_, _),
206                                    Token::Comma(_),
207                                    // Third operand is folded to an immediate value
208                                ) => {
209                                    operands.push(tokens[1].clone());
210                                    operands.push(Token::ImmediateValue(value, span.clone()));
211                                }
212                                _ => {
213                                    return Err(
214                                        CompileError::InvalidInstruction {  //
215                                            instruction: opcode.to_string() //
216                                            , span: span.clone()            //
217                                            , 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 {  //
238                                            instruction: opcode.to_string() //
239                                            , span: span.clone()            //
240                                            , 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 {  //
250                                    instruction: opcode.to_string() //
251                                    , span: span.clone()            //
252                                    , 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                                // Sixth operand is folded to an immediate value
263                                &tokens[advance_token_num],
264                            ) {
265                                (
266                                    Token::Register(_, _),
267                                    Token::Comma(_),
268                                    Token::LeftBracket(_),
269                                    Token::Register(_, _),
270                                    Token::BinaryOp(_, _),
271                                    // Sixth operand is folded to an immediate value 
272                                    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 {  //
281                                            instruction: opcode.to_string() //
282                                            , span: span.clone()            //
283                                            , 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 {  //
290                                    instruction: opcode.to_string() //
291                                    , span: span.clone()            //
292                                    , 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 {  //
299                                    instruction: opcode.to_string() //
300                                    , span: span.clone()            //
301                                    , 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                            // Now we need to fold the second immediate value (after the comma)
306                            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                                    // Fourth operand is folded to an immediate value
313                                    &tokens[advance_token_num],
314                                    &tokens[advance_token_num + 1],
315                                    // Sixth operand is also folded to an immediate value
316                                ) {
317                                    (
318                                        Token::LeftBracket(_),
319                                        Token::Register(_, _),
320                                        Token::BinaryOp(_, _),
321                                        // Fourth operand is folded to an immediate value
322                                        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 {  //
332                                                instruction: opcode.to_string() //
333                                                , span: span.clone()            //
334                                                , 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 {  //
341                                        instruction: opcode.to_string() //
342                                        , span: span.clone()            //
343                                        , custom_label: Some(EXPECTS_LB_REG_BIOP_IMM_RB_COM_IMM.to_string()) });
344                            }
345                        } else {
346                            return Err(
347                                CompileError::InvalidInstruction {  //
348                                    instruction: opcode.to_string() //
349                                    , span: span.clone()            //
350                                    , 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 {  //
357                                    instruction: opcode.to_string() //
358                                    , span: span.clone()            //
359                                    , 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                                // Fourth operand is folded to an immediate value
368                                &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                                    // Fourth operand is folded to an immediate value
377                                    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 {  //
388                                            instruction: opcode.to_string() //
389                                            , span: span.clone()            //
390                                            , 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 {  //
397                                    instruction: opcode.to_string() //
398                                    , span: span.clone()            //
399                                    , 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 {  //
417                                    instruction: opcode.to_string() //
418                                    , span: span.clone()            //
419                                    , 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                                // Third operand is folded to an immediate value
427                            ) {
428                                (
429                                    Token::Register(_, _),
430                                    Token::Comma(_),
431                                    // Third operand is folded to an immediate value
432                                ) => {
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 {  //
440                                            instruction: opcode.to_string() //
441                                            , span: span.clone()            //
442                                            , 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 {  //
464                                            instruction: opcode.to_string() //
465                                            , span: span.clone()            //
466                                            , 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 {  //
479                                    instruction: opcode.to_string() //
480                                    , span: span.clone()            //
481                                    , 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                                    // Third operand is folded to an immediate value
491                                    &tokens[advance_token_num],
492                                    // Fifth operand is folded to an immediate value
493                                ) {
494                                    (
495                                        Token::Register(_, _),
496                                        Token::Comma(_),
497                                        // Third operand is folded to an immediate value
498                                        Token::Comma(_),
499                                        // Fifth operand is folded to an immediate value
500                                    ) => {
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                                    // Third operand is folded to an immediate value
520                                    &tokens[advance_token_num],
521                                    &tokens[advance_token_num + 1],
522                                ) {
523                                    (
524                                        Token::Register(_, _),
525                                        Token::Comma(_),
526                                        // Third operand is folded to an immediate value
527                                        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 {  //
538                                                instruction: opcode.to_string() //
539                                                , span: span.clone()            //
540                                                , 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                                    // Fifth operand is folded to an immediate value
554                                ) {
555                                    (
556                                        Token::Register(_, _),
557                                        Token::Comma(_),
558                                        Token::Register(_, _),
559                                        Token::Comma(_),
560                                        // Fifth operand is folded to an immediate value
561                                    ) => {
562                                        // turn "invalid opcode" to a bug
563                                        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 {  //
571                                                instruction: opcode.to_string() //
572                                                , span: span.clone()            //
573                                                , 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                                        // turn "invalid opcode" to a bug
593                                        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 {  //
601                                                instruction: opcode.to_string() //
602                                                , span: span.clone()            //
603                                                , 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 {  //
614                                    instruction: opcode.to_string() //
615                                    , span: span.clone()            //
616                                    , 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 {  //
625                                        instruction: opcode.to_string() //
626                                        , span: span.clone()            //
627                                        , 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 {  //
636                                    instruction: opcode.to_string() //
637                                    , span: span.clone()            //
638                                    , 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 {  //
652                                            instruction: opcode.to_string() //
653                                            , span: span.clone()            //
654                                            , 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 {  //
664                                    instruction: opcode.to_string() //
665                                    , span: span.clone()            //
666                                    , 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 {  //
675                                        instruction: opcode.to_string() //
676                                        , span: span.clone()            //
677                                        , 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                // Immediately fold * / if top
773                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                    // error out would be better here
800                    return (None, idx);
801                }
802            }
803
804            Token::BinaryOp(op, span) => {
805                match op {
806                    Op::Sub if expect_number => {
807                        // unary minus → 0 - expr
808                        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                // Parse inside parentheses
820                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; // skip normal idx++
837            }
838
839            Token::RightParen(_) => {
840                // fold remaining + and -
841                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                // Unexpected token, stop
853                break;
854            }
855        }
856        idx += 1;
857    }
858
859    // Final fold at the end of expression
860    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}