1use std;
2use std::collections::HashMap;
3use std::iter::Peekable;
4
5use byteorder::{ByteOrder, LittleEndian};
6
7use ::opcodes::{AddressingMode, OpCode};
8use assembler::token::{ImmediateBase, LexerToken, ParserToken};
9
10#[derive(Debug, PartialEq)]
11pub struct ParserError {
12 pub message: String,
13}
14
15impl ParserError {
16 fn expected_immediate(line: u32) -> ParserError {
17 ParserError::from(format!("Immediate value expected. Line {}", line))
18 }
19
20 fn expected_instruction(line: u32) -> ParserError {
21 ParserError::from(format!("Instruction expected. Line {}", line))
22 }
23
24 fn invalid_opcode_addressing_mode_combination(line: u32) -> ParserError {
25 ParserError::from(format!("Invalid addressing mode for opcode. Line {}", line))
26 }
27
28 fn unexpected_eol(line: u32) -> ParserError {
29 ParserError::from(format!("Unexpected end of line. Line {}", line))
30 }
31
32 fn expected_eol(line: u32) -> ParserError {
33 ParserError::from(format!("Expected end of line. Line {}", line))
34 }
35
36 fn cannot_parse_address(line: u32) -> ParserError {
37 ParserError::from(format!("Unable to parse address. Line {}", line))
38 }
39
40 fn unexpected_token(line: u32) -> ParserError {
41 ParserError::from(format!("Unexpected token. Line {}", line))
42 }
43
44 fn address_out_of_bounds(line: u32) -> ParserError {
45 ParserError::from(format!("Address too large. Line {}", line))
46 }
47
48 fn expected_address(line: u32) -> ParserError {
49 ParserError::from(format!("Unexpected token, expected address. Line {}", line))
50 }
51
52 fn cannot_parse_immediate(line: u32) -> ParserError {
53 ParserError::from(format!("Unable to parse immedate value. Line {}", line))
54 }
55
56 fn unknown_identifier(line: u32) -> ParserError {
57 ParserError::from(format!("Unknown identifier. Line {}", line))
58 }
59}
60
61impl From<String> for ParserError {
62 fn from(error: String) -> ParserError {
63 ParserError { message: error }
64 }
65}
66
67impl<'a> From<&'a str> for ParserError {
68 fn from(error: &str) -> ParserError {
69 ParserError { message: error.into() }
70 }
71}
72
73#[derive(Clone, Debug, PartialEq)]
74pub struct Variable(LexerToken);
75
76pub struct Parser {
77 symbol_table: HashMap<String, Variable>,
78 line: u32,
79}
80
81impl Parser {
83 pub fn new() -> Parser {
84 Parser {
85 symbol_table: HashMap::new(),
86 line: 0,
87 }
88 }
89
90 pub fn parse(&mut self, tokens: Vec<Vec<LexerToken>>) -> Result<Vec<ParserToken>, ParserError> {
91 let mut result = Vec::new();
92
93 for line in &tokens {
94 let mut added_label = false;
95 self.line += 1;
96
97 let mut peeker = line.iter().peekable();
98
99 if let None = peeker.peek() {
101 continue;
102 }
103
104 let next = *peeker.peek().unwrap();
105
106 if let &LexerToken::Ident(ref ident) = next {
107 if Self::is_opcode(ident.clone()) {
109 let mut opcode = self.consume_opcode(&mut peeker, ident.clone())?;
111 result.append(&mut opcode);
112 } else {
113 let original_ident = peeker.next().unwrap();
115 if let None = peeker.peek() {
117 result.push(ParserToken::Label(ident.clone()));
118 continue;
119 }
120
121 let next = *peeker.peek().unwrap();
123 if let &LexerToken::Colon = next {
124 result.push(ParserToken::Label(ident.clone()));
125 continue;
126 }
127
128 if let &LexerToken::Ident(ref ident) = next {
130 if let &LexerToken::Ident(ref original_ident) = original_ident {
132 result.push(ParserToken::Label(original_ident.clone()));
133 }
134
135 if !Self::is_opcode(ident.clone()) {
136 return Err(ParserError::expected_instruction(self.line));
137 } else {
138 let mut opcode = self.consume_opcode(&mut peeker, ident.clone())?;
140 result.append(&mut opcode);
141 }
142 } else if let &LexerToken::Assignment = next {
143 peeker.next(); if let None = peeker.peek() {
146 return Err(ParserError::unexpected_eol(self.line));
147 }
148
149 let next = *peeker.peek().unwrap();
150 if let &LexerToken::Address(ref address) = next {
151 self.symbol_table
152 .insert(ident.clone(),
153 Variable(LexerToken::Address(address.clone())));
154 } else if let &LexerToken::Ident(ref var_ident) = next {
155 self.symbol_table
157 .insert(ident.clone(),
158 Variable(LexerToken::Ident(var_ident.clone())));
159 }
160 }
161 }
162 } else if let &LexerToken::Period = next {
163 peeker.next();
165 if let None = peeker.peek() {
166 return Err(ParserError::unexpected_eol(self.line));
167 }
168
169 let next = *peeker.peek().unwrap();
170 if let &LexerToken::Ident(ref directive) = next {
171 let directive = directive.to_uppercase();
173 match &directive[..] {
174 "ORG" => {
175 result.push(self.consume_org_directive(&mut peeker)?);
176 }
177 "BYTE" => {
178 result.push(self.consume_byte_directive(&mut peeker)?);
179 }
180 _ => return Err(ParserError::unknown_identifier(self.line)),
181 }
182 }
183 }
184 }
185
186 Ok(result)
187 }
188
189 fn is_opcode<S>(mnemonic: S) -> bool
190 where S: Into<String>
191 {
192 if let Some(opcode) = OpCode::from_mnemonic(mnemonic) {
193 true
194 } else {
195 false
196 }
197 }
198
199 fn consume_opcode<'a, I, S>(&mut self,
200 mut peeker: &mut Peekable<I>,
201 ident: S)
202 -> Result<Vec<ParserToken>, ParserError>
203 where I: Iterator<Item = &'a LexerToken>,
204 S: Into<String> + std::fmt::Display + Clone
205 {
206 peeker.next();
208
209 if let None = peeker.peek() {
212 if let Some(opcode) =
213 OpCode::from_mnemonic_and_addressing_mode(ident.clone(), AddressingMode::Implied) {
214 return Ok(vec![ParserToken::OpCode(opcode)]);
215 } else if let Some(opcode) =
216 OpCode::from_mnemonic_and_addressing_mode(ident.clone(),
217 AddressingMode::Accumulator) {
218 return Ok(vec![ParserToken::OpCode(opcode)]);
219 } else {
220 return Err(ParserError::invalid_opcode_addressing_mode_combination(self.line));
221 }
222 } else {
223 let mut next = (*peeker.peek().unwrap()).clone();
225 next = if let LexerToken::Ident(ref label) = next {
226 if let Ok(variable) = self.get_variable_value(label.clone()) {
228 variable.clone().0
229 } else {
230 let ident = ident.clone().into().to_uppercase();
232 let addressing_mode = if ident == "JMP" || ident == "JSR" {
233 AddressingMode::Absolute
234 } else {
235 AddressingMode::Relative
236 };
237
238 if let Some(opcode) =
239 OpCode::from_mnemonic_and_addressing_mode(ident.clone(), addressing_mode) {
240 return Ok(vec![ParserToken::OpCode(opcode),
241 ParserToken::LabelArg(label.clone())]);
242 } else {
243 return Err(ParserError::invalid_opcode_addressing_mode_combination(self.line));
244 }
245 }
246 } else {
247 next.clone()
248 };
249 if let LexerToken::Address(ref address) = next {
250 if address.len() <= 4 {
252 let addressing_mode = if address.len() <= 2 {
254 AddressingMode::ZeroPage
256 } else {
257 AddressingMode::Absolute
258 };
259 let bytes = self.parse_address_bytes(address)?;
260 peeker.next();
262 if let None = peeker.peek() {
263 if let Some(opcode) =
265 OpCode::from_mnemonic_and_addressing_mode(ident, addressing_mode) {
266 let mut final_vec = vec![ParserToken::OpCode(opcode)];
268 for b in bytes {
270 final_vec.push(ParserToken::RawByte(b));
271 }
272 return Ok(final_vec);
273 } else {
274 return Err(ParserError::invalid_opcode_addressing_mode_combination(self.line));
275 }
276 }
277
278 let next = *peeker.peek().unwrap();
282 if let &LexerToken::Comma = next {
283 peeker.next();
285 if let None = peeker.peek() {
287 return Err(ParserError::unexpected_eol(self.line));
288 }
289
290 let next = *peeker.peek().unwrap();
291 if let &LexerToken::Ident(ref register) = next {
292 let register = register.to_uppercase();
293 if register != "X" && register != "Y" {
294 return Err(ParserError::unexpected_token(self.line));
295 }
296 let addressing_mode = if register == "X" {
297 if addressing_mode == AddressingMode::ZeroPage {
298 AddressingMode::ZeroPageX
299 } else {
300 AddressingMode::AbsoluteX
301 }
302 } else {
303 if addressing_mode == AddressingMode::ZeroPage {
304 AddressingMode::ZeroPageY
305 } else {
306 AddressingMode::AbsoluteY
307 }
308 };
309 if let Some(opcode) =
310 OpCode::from_mnemonic_and_addressing_mode(ident, addressing_mode) {
311 let mut final_vec = vec![ParserToken::OpCode(opcode)];
313 for b in bytes {
315 final_vec.push(ParserToken::RawByte(b));
316 }
317 return Ok(final_vec);
318 } else {
319 return Err(ParserError::invalid_opcode_addressing_mode_combination(self.line));
320 }
321 } else {
322 return Err(ParserError::unexpected_token(self.line));
323 }
324 } else {
325 return Err(ParserError::unexpected_token(self.line));
326 }
327 let next = *peeker.peek().unwrap();
328
329 } else {
330 return Err(ParserError::cannot_parse_address(self.line));
331 }
332 } else if let LexerToken::OpenParenthesis = next {
333 let addressing_mode = AddressingMode::Indirect;
335 peeker.next(); if let None = peeker.peek() {
339 return Err(ParserError::unexpected_eol(self.line));
340 }
341
342 let mut next = (*peeker.peek().unwrap()).clone();
344 next = if let LexerToken::Ident(ref label) = next {
345 if let Ok(variable) = self.get_variable_value(label.clone()) {
347 variable.clone().0
348 } else {
349 next.clone()
350 }
351 } else {
352 next.clone()
353 };
354 if let LexerToken::Address(ref address) = next {
355 if address.len() > 4 {
356 return Err(ParserError::address_out_of_bounds(self.line));
357 }
358
359 let bytes = self.parse_address_bytes(address)?;
360
361 peeker.next();
363 if let None = peeker.peek() {
364 return Err(ParserError::unexpected_eol(self.line));
365 }
366 let next = *peeker.peek().unwrap();
367 if let &LexerToken::Comma = next {
368 peeker.next(); if let None = peeker.peek() {
371 return Err(ParserError::unexpected_eol(self.line));
372 }
373
374 let next = *peeker.peek().unwrap();
375 if let &LexerToken::Ident(ref register) = next {
376 let register = register.to_uppercase();
377 if register != "X" {
378 return Err(ParserError::unexpected_token(self.line));
379 }
380
381 peeker.next(); if let None = peeker.peek() {
384 return Err(ParserError::unexpected_eol(self.line));
385 }
386
387 let next = *peeker.peek().unwrap();
388 if let &LexerToken::CloseParenthesis = next {
389 peeker.next();
390 if let Some(opcode) = OpCode::from_mnemonic_and_addressing_mode(ident, AddressingMode::IndirectX) {
392 return Ok(vec![ParserToken::OpCode(opcode), ParserToken::RawByte(bytes[0])]);
395 } else {
396 return Err(ParserError::invalid_opcode_addressing_mode_combination(self.line));
397 }
398 } else {
399 return Err(ParserError::unexpected_token(self.line));
400 }
401 } else {
402 return Err(ParserError::unexpected_token(self.line));
403 }
404 } else if let &LexerToken::CloseParenthesis = next {
405 let addressing_mode = AddressingMode::IndirectY;
407 peeker.next(); if let None = peeker.peek() {
410 if let Some(opcode) = OpCode::from_mnemonic_and_addressing_mode(ident, AddressingMode::Indirect) {
413 if address.len() != 4 {
416 return Err(ParserError::address_out_of_bounds(self.line));
417 }
418 let mut final_vec = vec![ParserToken::OpCode(opcode)];
419 for b in bytes {
420 final_vec.push(ParserToken::RawByte(b));
421 }
422 return Ok(final_vec);
423 } else {
424 return Err(ParserError::invalid_opcode_addressing_mode_combination(self.line));
425 }
426 }
427
428 let next = *peeker.peek().unwrap();
430 if let &LexerToken::Comma = next {
431 peeker.next(); if let None = peeker.peek() {
434 return Err(ParserError::unexpected_eol(self.line));
435 }
436
437 let next = *peeker.peek().unwrap();
438 if let &LexerToken::Ident(ref register) = next {
439 let register = register.to_uppercase();
440 if register != "Y" {
442 return Err(ParserError::unexpected_token(self.line));
443 }
444 if let Some(opcode) = OpCode::from_mnemonic_and_addressing_mode(ident, AddressingMode::IndirectY) {
445 let mut final_vec = vec![ParserToken::OpCode(opcode)];
447 for b in bytes {
448 final_vec.push(ParserToken::RawByte(b));
449 }
450
451 return Ok(final_vec);
452 } else {
453 return Err(ParserError::invalid_opcode_addressing_mode_combination(self.line));
454 }
455 } else {
456 return Err(ParserError::unexpected_token(self.line));
457 }
458 } else {
459 return Err(ParserError::unexpected_token(self.line));
460 }
461 } else {
462 return Err(ParserError::unexpected_token(self.line));
463 }
464 } else {
465 return Err(ParserError::cannot_parse_address(self.line));
466 }
467 } else if let LexerToken::Immediate(ref immediate, base) = next {
468 peeker.next(); if let Ok(val) = u8::from_str_radix(&immediate[..],
470 if base == ImmediateBase::Base10 {
471 10
472 } else {
473 16
474 }) {
475 if let Some(opcode) =
476 OpCode::from_mnemonic_and_addressing_mode(ident,
477 AddressingMode::Immediate) {
478 return Ok(vec![ParserToken::OpCode(opcode), ParserToken::RawByte(val)]);
479 } else {
480 return Err(ParserError::invalid_opcode_addressing_mode_combination(self.line));
481 }
482 } else {
483 return Err(ParserError::cannot_parse_immediate(self.line));
484 }
485 } else {
486 return Err(ParserError::expected_address(self.line));
487 }
488 }
489
490 unreachable!();
491 }
492
493 fn consume_org_directive<'a, I>(&mut self,
494 mut peeker: &mut Peekable<I>)
495 -> Result<ParserToken, ParserError>
496 where I: Iterator<Item = &'a LexerToken>
497 {
498 peeker.next();
500 if let None = peeker.peek() {
501 return Err(ParserError::expected_address(self.line));
502 }
503
504 let next = peeker.next().unwrap();
505
506 if let &LexerToken::Address(ref address) = next {
507 let bytes = self.parse_address_bytes(address)?;
508 return Ok(ParserToken::OrgDirective(LittleEndian::read_u16(&bytes)));
509 } else {
510 return Err(ParserError::expected_address(self.line));
511 }
512 }
513
514 fn consume_byte_directive<'a, I>(&mut self,
515 mut peeker: &mut Peekable<I>)
516 -> Result<ParserToken, ParserError>
517 where I: Iterator<Item = &'a LexerToken>
518 {
519 let mut result = Vec::new();
520
521 peeker.next();
523 if let None = peeker.peek() {
524 return Err(ParserError::expected_immediate(self.line));
525 }
526
527 loop {
528 let mut next = peeker.next().unwrap();
529 if let &LexerToken::Ident(ref ident) = next {
530 let variable = self.get_variable_value(ident.clone())?;
531 if let LexerToken::Immediate(ref value, base) = variable.0 {
532 let immediate = self.unwrap_immediate(&value[..], base);
533 result.push(immediate);
534 } else {
535 return Err(ParserError::expected_immediate(self.line));
536 }
537 } else if let &LexerToken::Immediate(ref value, base) = next {
538 let immediate = self.unwrap_immediate(&value[..], base);
539 result.push(immediate);
540 } else {
541 return Err(ParserError::expected_immediate(self.line));
542 }
543
544 if let None = peeker.peek() {
546 break;
547 }
548
549 let next = peeker.next().unwrap();
550 if let &LexerToken::Comma = next {
551 } else {
553 break;
554 }
555 }
556
557 Ok(ParserToken::RawBytes(result))
558 }
559
560 fn unwrap_immediate<S>(&self, value: S, base: ImmediateBase) -> u8
561 where S: Into<String>
562 {
563 let base = match base {
564 ImmediateBase::Base10 => 10,
565 ImmediateBase::Base16 => 16,
566 };
567
568 let value = value.into();
569 let immediate = u8::from_str_radix(&value[..], base).unwrap();
570
571 immediate
572 }
573
574 fn parse_address_bytes(&self, address: &str) -> Result<Vec<u8>, ParserError> {
575 if let Ok(addr) = u16::from_str_radix(address, 16) {
576 if address.len() <= 2 {
577 return Ok(vec![addr as u8]);
578 } else {
579 let low_byte = addr as u8;
580 let high_byte = (addr >> 0x08) as u8;
581 return Ok(vec![low_byte, high_byte]);
582 }
583 } else {
584 Err(ParserError::cannot_parse_address(self.line))
585 }
586 }
587
588 fn get_variable_value<S>(&self, ident: S) -> Result<Variable, ParserError>
589 where S: Into<String>
590 {
591 let ident = ident.into();
592
593 if let Some(ref var) = self.symbol_table.get(&ident) {
594 let var = var.clone();
595 if let LexerToken::Ident(ref ident) = var.0 {
596 return self.get_variable_value(ident.clone());
598 } else {
599 return Ok(Variable(var.clone().0));
600 }
601 } else {
602 return Err(ParserError::unknown_identifier(self.line));
603 }
604 }
605}
606
607#[cfg(test)]
608mod tests {
609 use super::*;
610 use ::assembler::token::{ImmediateBase, LexerToken, ParserToken};
611 use ::opcodes::{AddressingMode, OpCode};
612
613 #[test]
614 fn can_parse_labels_via_lonely_label() {
615 let tokens = vec![vec![LexerToken::Ident("MAIN".into())],
616 vec![LexerToken::Ident("START".into())]];
617
618 let mut parser = Parser::new();
619 let result = parser.parse(tokens).unwrap();
620
621 assert_eq!(&[ParserToken::Label("MAIN".into()), ParserToken::Label("START".into())],
622 &result[..]);
623 }
624
625 #[test]
626 fn can_parse_labels_via_colon_terminator() {
627 let tokens = vec![vec![LexerToken::Ident("MAIN".into())], vec![LexerToken::Colon]];
628
629 let mut parser = Parser::new();
630 let result = parser.parse(tokens).unwrap();
631
632 assert_eq!(&[ParserToken::Label("MAIN".into())], &result[..]);
633 }
634
635 #[test]
636 fn can_parse_opcodes_after_labels_on_one_line() {
637 let tokens = vec![vec![LexerToken::Ident("MAIN".into()),
638 LexerToken::Ident("LDA".into()),
639 LexerToken::Address("4400".into())]];
640
641 let mut parser = Parser::new();
642 let result = parser.parse(tokens).unwrap();
643
644 assert_eq!(&[ParserToken::Label("MAIN".into()),
645 ParserToken::OpCode(OpCode::from_mnemonic_and_addressing_mode("LDA", AddressingMode::Absolute).unwrap()),
646 ParserToken::RawByte(0),
647 ParserToken::RawByte(68)],
648 &result[..]);
649 }
650
651 #[test]
652 fn can_parse_double_labels_on_one_line() {
653 let tokens = vec![vec![LexerToken::Ident("MAIN".into()),
654 LexerToken::Ident("START".into())]];
655
656 let mut parser = Parser::new();
657 let result = parser.parse(tokens);
658
659 assert_eq!(Err(ParserError::expected_instruction(1)), result);
660 }
661
662 #[test]
663 fn can_parse_opcode_with_implied_addressing_mode() {
664 let tokens = vec![vec![LexerToken::Ident("CLC".into())]];
665
666 let mut parser = Parser::new();
667 let result = parser.parse(tokens).unwrap();
668
669 assert_eq!(&[ParserToken::OpCode(OpCode::from_mnemonic_and_addressing_mode("CLC", AddressingMode::Implied).unwrap())], &result[..]);
670 }
671
672 #[test]
673 fn can_parse_opcode_with_correct_absolute_x_addressing_mode() {
674 let tokens = vec![vec![LexerToken::Ident("MAIN".into()),
675 LexerToken::Ident("LDA".into()),
676 LexerToken::Address("4400".into()),
677 LexerToken::Comma,
678 LexerToken::Ident("X".into())]];
679
680 let mut parser = Parser::new();
681 let result = parser.parse(tokens).unwrap();
682
683 assert_eq!(&[ParserToken::Label("MAIN".into()),
684 ParserToken::OpCode(OpCode::from_mnemonic_and_addressing_mode("LDA", AddressingMode::AbsoluteX).unwrap()),
685 ParserToken::RawByte(0),
686 ParserToken::RawByte(68)],
687 &result[..]);
688 }
689
690 #[test]
691 fn errors_on_incorrect_zero_page_y_usage() {
692 let tokens = vec![vec![LexerToken::Ident("LDA".into()),
694 LexerToken::Address("44".into()),
695 LexerToken::Comma,
696 LexerToken::Ident("Y".into())]];
697
698 let mut parser = Parser::new();
699 let result = parser.parse(tokens);
700
701 assert_eq!(Err(ParserError::invalid_opcode_addressing_mode_combination(1)),
702 result);
703 }
704
705 #[test]
706 fn can_handle_correct_zero_page_y_usage() {
707 let tokens = vec![vec![LexerToken::Ident("LDX".into()),
709 LexerToken::Address("44".into()),
710 LexerToken::Comma,
711 LexerToken::Ident("Y".into())]];
712
713 let mut parser = Parser::new();
714 let result = parser.parse(tokens).unwrap();
715
716 assert_eq!(&[
717 ParserToken::OpCode(OpCode::from_mnemonic_and_addressing_mode("LDX", AddressingMode::ZeroPageY).unwrap()),
718 ParserToken::RawByte(68)],
719 &result[..]);
720 }
721
722 #[test]
723 fn can_parse_indirect_x_addressing() {
724 let tokens = vec![vec![LexerToken::Ident("LDA".into()),
725 LexerToken::OpenParenthesis,
726 LexerToken::Address("44".into()),
727 LexerToken::Comma,
728 LexerToken::Ident("X".into()),
729 LexerToken::CloseParenthesis]];
730
731 let mut parser = Parser::new();
732 let result = parser.parse(tokens).unwrap();
733
734 assert_eq!(&[
735 ParserToken::OpCode(OpCode::from_mnemonic_and_addressing_mode("LDA", AddressingMode::IndirectX).unwrap()),
736 ParserToken::RawByte(68)],
737 &result[..]);
738 }
739
740 #[test]
741 fn errors_on_incorrect_indirect_x_addressing() {
742 let tokens = vec![vec![LexerToken::Ident("LDA".into()),
743 LexerToken::OpenParenthesis,
744 LexerToken::Address("44".into()),
745 LexerToken::Comma,
746 LexerToken::Ident("B".into()),
747 LexerToken::CloseParenthesis]];
748
749 let mut parser = Parser::new();
750 let result = parser.parse(tokens);
751
752 assert_eq!(Err(ParserError::unexpected_token(1)), result);
753 }
754
755 #[test]
756 fn errors_on_indirect_addressing_early_eol() {
757 let tokens = vec![vec![LexerToken::Ident("LDA".into()),
758 LexerToken::OpenParenthesis,
759 LexerToken::Address("44".into()),
760 LexerToken::Comma,
761 LexerToken::Ident("X".into())]];
762
763 let mut parser = Parser::new();
764 let result = parser.parse(tokens);
765
766 assert_eq!(Err(ParserError::unexpected_eol(1)), result);
767 }
768
769 #[test]
770 fn can_parse_indirect_jump_instruction() {
771 let tokens = vec![vec![LexerToken::Ident("JMP".into()),
772 LexerToken::OpenParenthesis,
773 LexerToken::Address("4400".into()),
774 LexerToken::CloseParenthesis]];
775
776 let mut parser = Parser::new();
777 let result = parser.parse(tokens).unwrap();
778
779 assert_eq!(&[
780 ParserToken::OpCode(OpCode::from_mnemonic_and_addressing_mode("JMP", AddressingMode::Indirect).unwrap()),
781 ParserToken::RawByte(0),
782 ParserToken::RawByte(68)],
783 &result[..]);
784 }
785
786 #[test]
787 fn errors_on_eight_bit_indirect_jump_instruction() {
788 let tokens = vec![vec![LexerToken::Ident("JMP".into()),
789 LexerToken::OpenParenthesis,
790 LexerToken::Address("44".into()),
791 LexerToken::CloseParenthesis]];
792
793 let mut parser = Parser::new();
794 let result = parser.parse(tokens);
795
796 assert_eq!(Err(ParserError::address_out_of_bounds(1)), result);
797 }
798
799 #[test]
800 fn can_parse_implied_stack_instructions() {
801 let tokens = vec![vec![LexerToken::Ident("PHA".into())]];
802
803 let mut parser = Parser::new();
804 let result = parser.parse(tokens).unwrap();
805
806 assert_eq!(&[
807 ParserToken::OpCode(OpCode::from_mnemonic_and_addressing_mode("PHA", AddressingMode::Implied).unwrap())],
808 &result[..]);
809 }
810
811 #[test]
812 fn errors_on_incorrect_opcode_addressing_mode_with_variable() {
813 let tokens = vec![vec![LexerToken::Ident("MAIN_ADDRESS".into()),
814 LexerToken::Assignment,
815 LexerToken::Address("00".into())],
816 vec![LexerToken::Ident("JMP".into()),
817 LexerToken::Ident("MAIN_ADDRESS".into())]];
818
819 let mut parser = Parser::new();
820 let result = parser.parse(tokens);
821
822 assert_eq!(Err(ParserError::invalid_opcode_addressing_mode_combination(2)),
823 result);
824 }
825
826 #[test]
827 fn can_parse_directives() {
828 let tokens = vec![vec![LexerToken::Period,
829 LexerToken::Ident("ORG".into()),
830 LexerToken::Address("C000".into())]];
831
832 let mut parser = Parser::new();
833 let result = parser.parse(tokens).unwrap();
834
835 assert_eq!(&[ParserToken::OrgDirective(0xC000)], &result[..]);
836 }
837}