cpclib_basic/
binary_parser.rs1use cpclib_common::itertools::Itertools;
2use cpclib_common::winnow;
3use cpclib_common::winnow::combinator::{eof, repeat, terminated};
4use cpclib_common::winnow::{ModalResult, Parser};
5use winnow::binary::{le_u16, u8};
6use winnow::combinator::cut_err;
7
8use crate::binary_parser::winnow::error::ContextError;
9use crate::binary_parser::winnow::token::take;
10use crate::tokens::{BasicTokenPrefixed, *};
11use crate::{BasicLine, BasicProgram};
12
13pub fn program(bytes: &mut &[u8]) -> ModalResult<BasicProgram, ContextError<&'static str>> {
14 let lines: Vec<BasicLine> = repeat(0.., line_or_end.context("Error when parsing a basic line"))
15 .verify(|lines: &Vec<Option<BasicLine>>| lines.last().map(|l| l.is_none()).unwrap_or(true))
16 .map(|mut lines: Vec<Option<BasicLine>>| {
17 lines.pop();
18 lines.into_iter().map(|l| l.unwrap()).collect_vec()
19 })
20 .parse_next(bytes)?;
21
22 Ok(BasicProgram { lines })
23}
24
25pub fn line_or_end(
29 bytes: &mut &[u8]
30) -> ModalResult<Option<BasicLine>, ContextError<&'static str>> {
31 let length = cut_err(le_u16.context("Expecting a line length")).parse_next(bytes)?;
32
33 if length == 0 {
35 return Ok(None);
36 }
37
38 let line_number = cut_err(le_u16.context("Expecting a line number")).parse_next(bytes)?;
39
40 dbg!("Tentative for line", line_number);
41
42 let mut buffer = cut_err(take(length - 4).context("Wrong number of bytes"))
43 .verify(|buffer: &[u8]| buffer[buffer.len() - 1] == 0)
44 .context("Last byte should be 0")
45 .parse_next(bytes)?;
46
47 let tokens = terminated(parse_tokens, eof).parse_next(&mut buffer)?;
48
49 let line = BasicLine {
50 line_number,
51 forced_length: None,
52 tokens
53 };
54
55 dbg!(&line);
56 dbg!(line.to_string());
57
58 Ok(Some(line))
59}
60
61pub fn parse_tokens(bytes: &mut &[u8]) -> ModalResult<Vec<BasicToken>, ContextError<&'static str>> {
62 let mut tokens = Vec::with_capacity(bytes.len());
63 while !bytes.is_empty() {
64 let code = BasicTokenNoPrefix::try_from(u8.parse_next(bytes)?).unwrap();
65
66 match code {
67 BasicTokenNoPrefix::ValueIntegerDecimal8bits => {
68 todo!()
69 },
70
71 BasicTokenNoPrefix::ValueIntegerDecimal16bits => {
72 todo!()
73 },
74
75 BasicTokenNoPrefix::ValueIntegerBinary16bits => {
76 todo!()
77 },
78
79 BasicTokenNoPrefix::ValueIntegerHexadecimal16bits => {
80 let low = u8.parse_next(bytes)?;
81 let high = u8.parse_next(bytes)?;
82 let value = BasicValue::new_integer_by_bytes(low, high);
83 let token = BasicToken::Constant(code, value);
84 tokens.push(token);
85 },
86
87 BasicTokenNoPrefix::AdditionalTokenMarker => {
88 let code2 = BasicTokenPrefixed::try_from(u8.parse_next(bytes)?).unwrap();
89 let token = BasicToken::PrefixedToken(code2);
90 tokens.push(token);
91 },
92
93 _ => {
94 tokens.push(BasicToken::SimpleToken(code));
95 }
96 }
97 }
98
99 Ok(tokens)
100}