1use std::collections::BTreeMap;
19use std::collections::HashSet;
20use std::path::{Path, PathBuf};
21
22use crate::config::Dispatch;
23use crate::error::{Error, ErrorKind, Span};
24
25use super::types::*;
26
27#[derive(Debug, Clone, PartialEq, Eq)]
32enum Tok {
33 Ident(String),
34 Str(String),
35 Num(u64),
36 LBrace,
37 RBrace,
38 LAngle,
39 RAngle,
40 Eq,
41 Comma,
42 Eof,
43}
44
45#[derive(Debug, Clone)]
46struct Token {
47 tok: Tok,
48 span: Span,
49}
50
51struct Lexer<'a> {
52 src: &'a [u8],
53 pos: usize,
54 line: usize,
55 col: usize,
56 file: String,
57}
58
59impl<'a> Lexer<'a> {
60 fn new(source: &'a str, filename: &str) -> Self {
61 Self {
62 src: source.as_bytes(),
63 pos: 0,
64 line: 1,
65 col: 1,
66 file: filename.to_string(),
67 }
68 }
69
70 fn span(&self, start_line: usize, start_col: usize, len: usize) -> Span {
71 Span::new(&self.file, start_line, start_col, len)
72 }
73
74 fn peek_byte(&self) -> Option<u8> {
75 self.src.get(self.pos).copied()
76 }
77
78 fn bump(&mut self) -> Option<u8> {
79 let b = self.peek_byte()?;
80 self.pos += 1;
81 if b == b'\n' {
82 self.line += 1;
83 self.col = 1;
84 } else {
85 self.col += 1;
86 }
87 Some(b)
88 }
89
90 fn skip_whitespace_and_comments(&mut self) {
91 loop {
92 match self.peek_byte() {
93 Some(b' ' | b'\t' | b'\n' | b'\r') => {
94 self.bump();
95 }
96 Some(b'#') => {
97 while let Some(b) = self.peek_byte() {
98 if b == b'\n' {
99 break;
100 }
101 self.bump();
102 }
103 }
104 _ => break,
105 }
106 }
107 }
108
109 fn next_token(&mut self) -> Result<Token, Error> {
110 self.skip_whitespace_and_comments();
111 let start_line = self.line;
112 let start_col = self.col;
113 let start_pos = self.pos;
114
115 let b = match self.peek_byte() {
116 Some(b) => b,
117 None => {
118 return Ok(Token {
119 tok: Tok::Eof,
120 span: self.span(start_line, start_col, 0),
121 });
122 }
123 };
124
125 match b {
126 b'{' => {
127 self.bump();
128 Ok(Token {
129 tok: Tok::LBrace,
130 span: self.span(start_line, start_col, 1),
131 })
132 }
133 b'}' => {
134 self.bump();
135 Ok(Token {
136 tok: Tok::RBrace,
137 span: self.span(start_line, start_col, 1),
138 })
139 }
140 b'<' => {
141 self.bump();
142 Ok(Token {
143 tok: Tok::LAngle,
144 span: self.span(start_line, start_col, 1),
145 })
146 }
147 b'>' => {
148 self.bump();
149 Ok(Token {
150 tok: Tok::RAngle,
151 span: self.span(start_line, start_col, 1),
152 })
153 }
154 b'=' => {
155 self.bump();
156 Ok(Token {
157 tok: Tok::Eq,
158 span: self.span(start_line, start_col, 1),
159 })
160 }
161 b',' => {
162 self.bump();
163 Ok(Token {
164 tok: Tok::Comma,
165 span: self.span(start_line, start_col, 1),
166 })
167 }
168 b'"' => {
169 self.bump();
170 let mut s = String::new();
171 loop {
172 match self.peek_byte() {
173 None => {
174 return Err(Error::new(
175 ErrorKind::BindingsParse("unterminated string literal".to_string()),
176 self.span(start_line, start_col, 1),
177 ));
178 }
179 Some(b'"') => {
180 self.bump();
181 break;
182 }
183 Some(b'\\') => {
184 self.bump();
185 match self.bump() {
186 Some(b'"') => s.push('"'),
187 Some(b'\\') => s.push('\\'),
188 Some(b'n') => s.push('\n'),
189 Some(b't') => s.push('\t'),
190 Some(c) => s.push(c as char),
191 None => {
192 return Err(Error::new(
193 ErrorKind::BindingsParse(
194 "unterminated string escape".to_string(),
195 ),
196 self.span(start_line, start_col, 1),
197 ));
198 }
199 }
200 }
201 Some(c) => {
202 s.push(c as char);
203 self.bump();
204 }
205 }
206 }
207 let len = self.pos - start_pos;
208 Ok(Token {
209 tok: Tok::Str(s),
210 span: self.span(start_line, start_col, len),
211 })
212 }
213 b'0'..=b'9' => {
214 let mut s = String::new();
215 while let Some(c) = self.peek_byte() {
216 if c.is_ascii_alphanumeric() || c == b'x' || c == b'X' {
217 s.push(c as char);
218 self.bump();
219 } else {
220 break;
221 }
222 }
223 let n = if let Some(rest) = s.strip_prefix("0x").or(s.strip_prefix("0X")) {
224 u64::from_str_radix(rest, 16)
225 } else {
226 s.parse::<u64>()
227 };
228 let n = n.map_err(|_| {
229 Error::new(
230 ErrorKind::BindingsParse(format!("invalid number literal '{}'", s)),
231 self.span(start_line, start_col, s.len()),
232 )
233 })?;
234 let len = self.pos - start_pos;
235 Ok(Token {
236 tok: Tok::Num(n),
237 span: self.span(start_line, start_col, len),
238 })
239 }
240 c if is_ident_start(c) => {
241 let mut s = String::new();
242 while let Some(c) = self.peek_byte() {
243 if is_ident_cont(c) {
244 s.push(c as char);
245 self.bump();
246 } else if c == b':' && self.src.get(self.pos + 1) == Some(&b':') {
247 s.push_str("::");
248 self.bump();
249 self.bump();
250 } else if c == b'$' {
251 s.push(c as char);
255 self.bump();
256 } else {
257 break;
258 }
259 }
260 let len = self.pos - start_pos;
261 Ok(Token {
262 tok: Tok::Ident(s),
263 span: self.span(start_line, start_col, len),
264 })
265 }
266 _ => Err(Error::new(
267 ErrorKind::BindingsParse(format!("unexpected character '{}'", b as char)),
268 self.span(start_line, start_col, 1),
269 )),
270 }
271 }
272}
273
274fn is_ident_start(c: u8) -> bool {
275 c.is_ascii_alphabetic() || c == b'_'
276}
277
278fn is_ident_cont(c: u8) -> bool {
279 c.is_ascii_alphanumeric() || c == b'_'
280}
281
282struct Parser<'a> {
287 lex: Lexer<'a>,
288 peeked: Option<Token>,
289 file_path: PathBuf,
290}
291
292pub fn parse(source: &str, file_path: &Path) -> Result<BindingsFile, Vec<Error>> {
294 let filename = file_path
295 .file_name()
296 .and_then(|s| s.to_str())
297 .unwrap_or("<bindings>");
298 let mut p = Parser {
299 lex: Lexer::new(source, filename),
300 peeked: None,
301 file_path: file_path.to_path_buf(),
302 };
303 p.parse_file()
304}
305
306pub fn parse_file(path: &Path) -> Result<BindingsFile, Vec<Error>> {
308 let source = std::fs::read_to_string(path).map_err(|_| {
309 vec![Error::new(
310 ErrorKind::IncludeNotFound(path.display().to_string()),
311 Span::new(&path.display().to_string(), 1, 1, 0),
312 )]
313 })?;
314 parse(&source, path)
315}
316
317pub fn parse_file_with_includes(path: &Path) -> Result<BindingsFile, Vec<Error>> {
320 let mut visited: HashSet<PathBuf> = HashSet::new();
321 parse_file_recursive(path, &mut visited)
322}
323
324fn parse_file_recursive(
325 path: &Path,
326 visited: &mut HashSet<PathBuf>,
327) -> Result<BindingsFile, Vec<Error>> {
328 let canonical = path.canonicalize().map_err(|_| {
329 vec![Error::new(
330 ErrorKind::IncludeNotFound(path.display().to_string()),
331 Span::new(&path.display().to_string(), 1, 1, 0),
332 )]
333 })?;
334 if !visited.insert(canonical.clone()) {
335 return Err(vec![Error::new(
336 ErrorKind::BindingsCircularInclude(path.display().to_string()),
337 Span::new(&path.display().to_string(), 1, 1, 0),
338 )]);
339 }
340 let mut file = parse_file(&canonical)?;
341 file.path = canonical.clone();
342 let base = canonical.parent().unwrap_or(Path::new(".")).to_path_buf();
343 let mut merged_targets: Vec<TargetBinding> = std::mem::take(&mut file.targets);
344 let mut merged_specs: Vec<(PathBuf, Span)> = std::mem::take(&mut file.spec_includes);
345
346 let bindings_inc = std::mem::take(&mut file.bindings_includes);
347 let mut resolved_bindings_inc: Vec<(PathBuf, Span)> = Vec::new();
348 for (rel, span) in bindings_inc {
349 let abs = if rel.is_absolute() {
350 rel
351 } else {
352 base.join(rel)
353 };
354 let inc = parse_file_recursive(&abs, visited)?;
355 merged_targets.extend(inc.targets);
357 merged_specs.extend(inc.spec_includes);
358 resolved_bindings_inc.push((inc.path, span));
359 }
360
361 let mut resolved_specs: Vec<(PathBuf, Span)> = Vec::new();
363 for (rel, span) in merged_specs {
364 let abs = if rel.is_absolute() {
365 rel
366 } else {
367 base.join(rel)
368 };
369 let canon = abs.canonicalize().unwrap_or(abs);
370 resolved_specs.push((canon, span));
371 }
372
373 file.targets = merged_targets;
374 file.spec_includes = resolved_specs;
375 file.bindings_includes = resolved_bindings_inc;
376 Ok(file)
377}
378
379impl<'a> Parser<'a> {
380 fn peek(&mut self) -> Result<&Token, Error> {
381 if self.peeked.is_none() {
382 self.peeked = Some(self.lex.next_token()?);
383 }
384 Ok(self.peeked.as_ref().unwrap())
385 }
386
387 fn peek_clone(&mut self) -> Result<Token, Error> {
391 Ok(self.peek()?.clone())
392 }
393
394 fn next(&mut self) -> Result<Token, Error> {
395 if let Some(t) = self.peeked.take() {
396 return Ok(t);
397 }
398 self.lex.next_token()
399 }
400
401 fn expect_ident(&mut self) -> Result<(String, Span), Error> {
402 let t = self.next()?;
403 match t.tok {
404 Tok::Ident(s) => Ok((s, t.span)),
405 other => Err(Error::new(
406 ErrorKind::BindingsParse(format!("expected identifier, got {:?}", other)),
407 t.span,
408 )),
409 }
410 }
411
412 fn expect_string(&mut self) -> Result<(String, Span), Error> {
413 let t = self.next()?;
414 match t.tok {
415 Tok::Str(s) => Ok((s, t.span)),
416 other => Err(Error::new(
417 ErrorKind::BindingsParse(format!("expected string literal, got {:?}", other)),
418 t.span,
419 )),
420 }
421 }
422
423 fn expect_number(&mut self) -> Result<(u64, Span), Error> {
424 let t = self.next()?;
425 match t.tok {
426 Tok::Num(n) => Ok((n, t.span)),
427 other => Err(Error::new(
428 ErrorKind::BindingsParse(format!("expected number, got {:?}", other)),
429 t.span,
430 )),
431 }
432 }
433
434 fn expect_lbrace(&mut self) -> Result<Span, Error> {
435 let t = self.next()?;
436 match t.tok {
437 Tok::LBrace => Ok(t.span),
438 other => Err(Error::new(
439 ErrorKind::BindingsParse(format!("expected '{{', got {:?}", other)),
440 t.span,
441 )),
442 }
443 }
444
445 fn parse_file(&mut self) -> Result<BindingsFile, Vec<Error>> {
446 let mut errors: Vec<Error> = Vec::new();
447 let mut spec_includes: Vec<(PathBuf, Span)> = Vec::new();
448 let mut bindings_includes: Vec<(PathBuf, Span)> = Vec::new();
449 let mut targets: Vec<TargetBinding> = Vec::new();
450
451 loop {
452 let t = match self.peek() {
453 Ok(t) => t,
454 Err(e) => {
455 errors.push(e);
456 break;
457 }
458 };
459 match &t.tok {
460 Tok::Eof => break,
461 Tok::Ident(name) if name == "include" => {
462 self.next().ok();
463 match self.expect_string() {
464 Ok((s, span)) => {
465 let p = PathBuf::from(&s);
466 if s.ends_with(".bindings.chipi") {
467 bindings_includes.push((p, span));
468 } else if s.ends_with(".chipi") {
469 spec_includes.push((p, span));
470 } else {
471 errors.push(Error::new(
472 ErrorKind::BindingsParse(format!(
473 "include path '{}' must end in .chipi or .bindings.chipi",
474 s
475 )),
476 span,
477 ));
478 }
479 }
480 Err(e) => errors.push(e),
481 }
482 }
483 Tok::Ident(name) if name == "target" => match self.parse_target() {
484 Ok(t) => targets.push(t),
485 Err(e) => errors.push(e),
486 },
487 _ => {
488 let t = self.next().unwrap();
489 errors.push(Error::new(
490 ErrorKind::BindingsParse(format!(
491 "expected 'include' or 'target' at top level, got {:?}",
492 t.tok
493 )),
494 t.span,
495 ));
496 }
497 }
498 }
499
500 if errors.is_empty() {
501 Ok(BindingsFile {
502 path: self.file_path.clone(),
503 spec_includes,
504 bindings_includes,
505 targets,
506 })
507 } else {
508 Err(errors)
509 }
510 }
511
512 fn parse_target(&mut self) -> Result<TargetBinding, Error> {
513 let target_tok = self.next()?;
515 let span = target_tok.span;
516 let (kind_name, kind_span) = self.expect_ident()?;
517 let kind = match kind_name.as_str() {
518 "rust" => TargetKind::Rust,
519 "cpp" | "c++" => TargetKind::Cpp,
520 "ida" => TargetKind::Ida,
521 "binja" => TargetKind::Binja,
522 other => {
523 return Err(Error::new(
524 ErrorKind::UnknownTargetKind(other.to_string()),
525 kind_span,
526 ));
527 }
528 };
529 self.expect_lbrace()?;
530
531 let mut binding = TargetBinding::empty(kind, span);
532
533 loop {
534 let t = self.peek_clone()?;
535 match &t.tok {
536 Tok::RBrace => {
537 self.next()?;
538 break;
539 }
540 Tok::Eof => {
541 return Err(Error::new(
542 ErrorKind::BindingsParse(
543 "unexpected end of file inside target block".to_string(),
544 ),
545 t.span.clone(),
546 ));
547 }
548 Tok::Ident(name) => match (kind, name.as_str()) {
549 (TargetKind::Rust, "decoder") => {
550 let d = self.parse_decoder_block()?;
551 binding.rust_decoders.push(d);
552 }
553 (TargetKind::Rust, "dispatch") => {
554 let d = self.parse_dispatch_block()?;
555 binding.rust_dispatches.push(d);
556 }
557 (TargetKind::Cpp, "decoder") => {
558 let d = self.parse_decoder_block()?;
559 binding.cpp_decoders.push(d);
560 }
561 (TargetKind::Ida, "processor") => {
562 let p = self.parse_processor_block()?;
563 binding.ida_processors.push(p);
564 }
565 (TargetKind::Binja, "architecture") => {
566 let a = self.parse_architecture_block()?;
567 binding.binja_architectures.push(a);
568 }
569 _ => {
570 let t = self.next()?;
571 return Err(Error::new(
572 ErrorKind::BindingsParse(format!(
573 "unexpected '{}' inside target {}",
574 name,
575 kind.name()
576 )),
577 t.span,
578 ));
579 }
580 },
581 other => {
582 let t = self.next()?;
583 return Err(Error::new(
584 ErrorKind::BindingsParse(format!(
585 "unexpected token {:?} inside target block",
586 other
587 )),
588 t.span,
589 ));
590 }
591 }
592 }
593
594 Ok(binding)
595 }
596
597 fn parse_decoder_block(&mut self) -> Result<DecoderBinding, Error> {
598 self.next()?;
600 let (name, span) = self.expect_ident()?;
601 self.expect_lbrace()?;
602
603 let mut output: Option<String> = None;
604 let mut type_map: BTreeMap<String, String> = BTreeMap::new();
605 let mut subdecoders: Vec<DecoderBinding> = Vec::new();
606 let mut cpp_namespace: Option<String> = None;
607 let mut cpp_guard_style: Option<String> = None;
608 let mut cpp_includes: Vec<String> = Vec::new();
609
610 loop {
611 let t = self.peek_clone()?;
612 match &t.tok {
613 Tok::RBrace => {
614 self.next()?;
615 break;
616 }
617 Tok::Eof => {
618 return Err(Error::new(
619 ErrorKind::BindingsParse(
620 "unexpected end of file inside decoder block".to_string(),
621 ),
622 t.span.clone(),
623 ));
624 }
625 Tok::Ident(name) => {
626 let name = name.clone();
627 match name.as_str() {
628 "output" => {
629 self.next()?;
630 let (s, _) = self.expect_string()?;
631 output = Some(s);
632 }
633 "type" => {
634 self.next()?;
635 let (lhs, _) = self.expect_ident()?;
636 let eq = self.next()?;
638 if !matches!(eq.tok, Tok::Eq) {
639 return Err(Error::new(
640 ErrorKind::BindingsParse(
641 "expected '=' in type alias".to_string(),
642 ),
643 eq.span,
644 ));
645 }
646 let (rhs, _) = self.expect_ident()?;
647 type_map.insert(lhs, rhs);
648 }
649 "subdecoder" => {
650 let sd = self.parse_decoder_block()?;
651 subdecoders.push(sd);
652 }
653 "namespace" => {
654 self.next()?;
655 let (s, _) = self.expect_string()?;
656 cpp_namespace = Some(s);
657 }
658 "guard_style" => {
659 self.next()?;
660 let (s, _) = self.expect_ident()?;
661 cpp_guard_style = Some(s);
662 }
663 "includes" => {
664 self.next()?;
665 cpp_includes = self.parse_string_block()?;
666 }
667 other => {
668 let t = self.next()?;
669 return Err(Error::new(
670 ErrorKind::BindingsParse(format!(
671 "unexpected '{}' inside decoder block",
672 other
673 )),
674 t.span,
675 ));
676 }
677 }
678 }
679 _ => {
680 let t = self.next()?;
681 return Err(Error::new(
682 ErrorKind::BindingsParse(format!(
683 "unexpected token {:?} inside decoder block",
684 t.tok
685 )),
686 t.span,
687 ));
688 }
689 }
690 }
691
692 let output = output.ok_or_else(|| {
693 Error::new(
694 ErrorKind::MissingBindingsField {
695 block: format!("decoder {}", name),
696 field: "output".to_string(),
697 },
698 span.clone(),
699 )
700 })?;
701
702 Ok(DecoderBinding {
703 decoder_name: name,
704 span,
705 output,
706 type_map,
707 subdecoders,
708 cpp_namespace,
709 cpp_guard_style,
710 cpp_includes,
711 })
712 }
713
714 fn parse_dispatch_block(&mut self) -> Result<DispatchBinding, Error> {
715 self.next()?;
717 let (name, span) = self.expect_ident()?;
718 self.expect_lbrace()?;
719
720 let mut output: Option<String> = None;
721 let mut context: Option<String> = None;
722 let mut handlers: Option<String> = None;
723 let mut strategy: Option<Dispatch> = None;
724 let mut invalid_handler: Option<String> = None;
725 let mut instruction_type: Option<InstructionTypeBinding> = None;
726 let mut handler_groups: Vec<HandlerBinding> = Vec::new();
727 let mut subdispatches: Vec<DispatchBinding> = Vec::new();
728 let mut handler_consts: Vec<String> = Vec::new();
729
730 loop {
731 let t = self.peek_clone()?;
732 match &t.tok {
733 Tok::RBrace => {
734 self.next()?;
735 break;
736 }
737 Tok::Eof => {
738 return Err(Error::new(
739 ErrorKind::BindingsParse(
740 "unexpected end of file inside dispatch block".to_string(),
741 ),
742 t.span.clone(),
743 ));
744 }
745 Tok::Ident(name) => {
746 let name = name.clone();
747 match name.as_str() {
748 "output" => {
749 self.next()?;
750 let (s, _) = self.expect_string()?;
751 output = Some(s);
752 }
753 "context" => {
754 self.next()?;
755 let (s, _) = self.expect_ident()?;
756 context = Some(s);
757 }
758 "handlers" => {
759 self.next()?;
760 let (s, _) = self.expect_ident()?;
761 handlers = Some(s);
762 }
763 "strategy" => {
764 self.next()?;
765 let (s, span) = self.expect_ident()?;
766 strategy = Some(parse_strategy(&s, &span)?);
767 }
768 "invalid_handler" => {
769 self.next()?;
770 let (s, _) = self.expect_ident()?;
771 invalid_handler = Some(s);
772 }
773 "handler_const" => {
774 self.next()?;
775 let (s, _) = self.expect_ident()?;
776 handler_consts.push(s);
777 }
778 "instruction_type" => {
779 self.next()?;
780 let (path, _) = self.expect_ident()?;
781 let next = self.peek()?;
783 if matches!(next.tok, Tok::LBrace) {
784 self.next()?;
785 let mut inner_out: Option<String> = None;
786 loop {
787 let t = self.peek_clone()?;
788 match &t.tok {
789 Tok::RBrace => {
790 self.next()?;
791 break;
792 }
793 Tok::Ident(n) if n == "output" => {
794 self.next()?;
795 let (s, _) = self.expect_string()?;
796 inner_out = Some(s);
797 }
798 _ => {
799 let t = self.next()?;
800 return Err(Error::new(
801 ErrorKind::BindingsParse(format!(
802 "unexpected token {:?} inside instruction_type block",
803 t.tok
804 )),
805 t.span,
806 ));
807 }
808 }
809 }
810 instruction_type = Some(InstructionTypeBinding {
811 type_path: path,
812 output: inner_out,
813 });
814 } else {
815 instruction_type = Some(InstructionTypeBinding {
816 type_path: path,
817 output: None,
818 });
819 }
820 }
821 "handler" => {
822 let group = self.parse_handler_block()?;
823 handler_groups.push(group);
824 }
825 "subdispatch" => {
826 let sd = self.parse_dispatch_block()?;
827 subdispatches.push(sd);
828 }
829 other => {
830 let t = self.next()?;
831 return Err(Error::new(
832 ErrorKind::BindingsParse(format!(
833 "unexpected '{}' inside dispatch block",
834 other
835 )),
836 t.span,
837 ));
838 }
839 }
840 }
841 _ => {
842 let t = self.next()?;
843 return Err(Error::new(
844 ErrorKind::BindingsParse(format!(
845 "unexpected token {:?} inside dispatch block",
846 t.tok
847 )),
848 t.span,
849 ));
850 }
851 }
852 }
853
854 Ok(DispatchBinding {
855 decoder_name: name,
856 span,
857 output,
858 context,
859 handlers,
860 strategy,
861 invalid_handler,
862 instruction_type,
863 handler_groups,
864 subdispatches,
865 handler_consts,
866 })
867 }
868
869 fn parse_handler_block(&mut self) -> Result<HandlerBinding, Error> {
870 self.next()?;
872 let (handler_name, span) = self.expect_ident()?;
873
874 self.expect_lbrace()?;
875 let mut instructions: Vec<(String, Span)> = Vec::new();
876 loop {
877 let t = self.peek_clone()?;
878 match &t.tok {
879 Tok::RBrace => {
880 self.next()?;
881 break;
882 }
883 Tok::Comma => {
884 self.next()?;
885 }
886 Tok::Ident(name) => {
887 let name = name.clone();
888 let t = self.next()?;
889 instructions.push((name, t.span));
890 }
891 other => {
892 let t = self.next()?;
893 return Err(Error::new(
894 ErrorKind::BindingsParse(format!(
895 "unexpected token {:?} inside handler block",
896 other
897 )),
898 t.span,
899 ));
900 }
901 }
902 }
903
904 Ok(HandlerBinding {
905 handler_name,
906 instructions,
907 span,
908 })
909 }
910
911 fn parse_processor_block(&mut self) -> Result<IdaProcessorBinding, Error> {
912 self.next()?; let (name, span) = self.expect_ident()?;
914 self.expect_lbrace()?;
915
916 let mut output: Option<String> = None;
917 let mut p_name: Option<String> = None;
918 let mut long_name: Option<String> = None;
919 let mut id: Option<u64> = None;
920 let mut address_size: Option<u32> = None;
921 let mut bytes_per_unit: Option<u32> = None;
922 let mut registers: Vec<String> = Vec::new();
923 let mut segment_registers: Vec<(String, Span)> = Vec::new();
924 let mut flow = IdaFlowBinding::default();
925
926 loop {
927 let t = self.peek_clone()?;
928 match &t.tok {
929 Tok::RBrace => {
930 self.next()?;
931 break;
932 }
933 Tok::Eof => {
934 return Err(Error::new(
935 ErrorKind::BindingsParse(
936 "unexpected end of file inside processor block".to_string(),
937 ),
938 t.span.clone(),
939 ));
940 }
941 Tok::Ident(name) => {
942 let name = name.clone();
943 match name.as_str() {
944 "output" => {
945 self.next()?;
946 let (s, _) = self.expect_string()?;
947 output = Some(s);
948 }
949 "name" => {
950 self.next()?;
951 let (s, _) = self.expect_string()?;
952 p_name = Some(s);
953 }
954 "long_name" => {
955 self.next()?;
956 let (s, _) = self.expect_string()?;
957 long_name = Some(s);
958 }
959 "id" => {
960 self.next()?;
961 let (n, _) = self.expect_number()?;
962 id = Some(n);
963 }
964 "address_size" => {
965 self.next()?;
966 let (n, _) = self.expect_number()?;
967 address_size = Some(n as u32);
968 }
969 "bytes_per_unit" => {
970 self.next()?;
971 let (n, _) = self.expect_number()?;
972 bytes_per_unit = Some(n as u32);
973 }
974 "registers" => {
975 self.next()?;
976 registers = self.parse_ident_block()?;
977 }
978 "segment_registers" => {
979 self.next()?;
980 segment_registers = self.parse_ident_block_with_spans()?;
981 }
982 "flow" => {
983 self.next()?;
984 flow = self.parse_flow_block()?;
985 }
986 other => {
987 let t = self.next()?;
988 return Err(Error::new(
989 ErrorKind::BindingsParse(format!(
990 "unexpected '{}' inside processor block",
991 other
992 )),
993 t.span,
994 ));
995 }
996 }
997 }
998 _ => {
999 let t = self.next()?;
1000 return Err(Error::new(
1001 ErrorKind::BindingsParse(format!(
1002 "unexpected token {:?} inside processor block",
1003 t.tok
1004 )),
1005 t.span,
1006 ));
1007 }
1008 }
1009 }
1010
1011 Ok(IdaProcessorBinding {
1012 decoder_name: name,
1013 span,
1014 output,
1015 name: p_name,
1016 long_name,
1017 id,
1018 address_size,
1019 bytes_per_unit,
1020 registers,
1021 segment_registers,
1022 flow,
1023 })
1024 }
1025
1026 fn parse_architecture_block(&mut self) -> Result<BinjaArchitectureBinding, Error> {
1027 self.next()?; let (name, span) = self.expect_ident()?;
1029 self.expect_lbrace()?;
1030
1031 let mut output: Option<String> = None;
1032 let mut a_name: Option<String> = None;
1033 let mut address_size: Option<u32> = None;
1034 let mut default_int_size: Option<u32> = None;
1035 let mut endianness: Option<(String, Span)> = None;
1036 let mut registers: Vec<String> = Vec::new();
1037
1038 loop {
1039 let t = self.peek_clone()?;
1040 match &t.tok {
1041 Tok::RBrace => {
1042 self.next()?;
1043 break;
1044 }
1045 Tok::Eof => {
1046 return Err(Error::new(
1047 ErrorKind::BindingsParse(
1048 "unexpected end of file inside architecture block".to_string(),
1049 ),
1050 t.span.clone(),
1051 ));
1052 }
1053 Tok::Ident(name) => {
1054 let name = name.clone();
1055 match name.as_str() {
1056 "output" => {
1057 self.next()?;
1058 let (s, _) = self.expect_string()?;
1059 output = Some(s);
1060 }
1061 "name" => {
1062 self.next()?;
1063 let (s, _) = self.expect_string()?;
1064 a_name = Some(s);
1065 }
1066 "address_size" => {
1067 self.next()?;
1068 let (n, _) = self.expect_number()?;
1069 address_size = Some(n as u32);
1070 }
1071 "default_int_size" => {
1072 self.next()?;
1073 let (n, _) = self.expect_number()?;
1074 default_int_size = Some(n as u32);
1075 }
1076 "endianness" => {
1077 self.next()?;
1078 let (s, span) = self.expect_ident()?;
1079 endianness = Some((s, span));
1080 }
1081 "registers" => {
1082 self.next()?;
1083 registers = self.parse_ident_block()?;
1084 }
1085 other => {
1086 let t = self.next()?;
1087 return Err(Error::new(
1088 ErrorKind::BindingsParse(format!(
1089 "unexpected '{}' inside architecture block",
1090 other
1091 )),
1092 t.span,
1093 ));
1094 }
1095 }
1096 }
1097 _ => {
1098 let t = self.next()?;
1099 return Err(Error::new(
1100 ErrorKind::BindingsParse(format!(
1101 "unexpected token {:?} inside architecture block",
1102 t.tok
1103 )),
1104 t.span,
1105 ));
1106 }
1107 }
1108 }
1109
1110 Ok(BinjaArchitectureBinding {
1111 decoder_name: name,
1112 span,
1113 output,
1114 name: a_name,
1115 address_size,
1116 default_int_size,
1117 endianness,
1118 registers,
1119 })
1120 }
1121
1122 fn parse_ident_block(&mut self) -> Result<Vec<String>, Error> {
1123 let pairs = self.parse_ident_block_with_spans()?;
1124 Ok(pairs.into_iter().map(|(s, _)| s).collect())
1125 }
1126
1127 fn parse_string_block(&mut self) -> Result<Vec<String>, Error> {
1128 self.expect_lbrace()?;
1129 let mut out = Vec::new();
1130 loop {
1131 let t = self.peek_clone()?;
1132 match &t.tok {
1133 Tok::RBrace => {
1134 self.next()?;
1135 break;
1136 }
1137 Tok::Comma => {
1138 self.next()?;
1139 }
1140 Tok::Str(_) => {
1141 let t = self.next()?;
1142 if let Tok::Str(s) = t.tok {
1143 out.push(s);
1144 }
1145 }
1146 other => {
1147 let t = self.next()?;
1148 return Err(Error::new(
1149 ErrorKind::BindingsParse(format!(
1150 "expected string literal, got {:?}",
1151 other
1152 )),
1153 t.span,
1154 ));
1155 }
1156 }
1157 }
1158 Ok(out)
1159 }
1160
1161 fn parse_ident_block_with_spans(&mut self) -> Result<Vec<(String, Span)>, Error> {
1162 self.expect_lbrace()?;
1163 let mut out = Vec::new();
1164 loop {
1165 let t = self.peek_clone()?;
1166 match &t.tok {
1167 Tok::RBrace => {
1168 self.next()?;
1169 break;
1170 }
1171 Tok::Comma => {
1172 self.next()?;
1173 }
1174 Tok::Ident(_) => {
1175 let t = self.next()?;
1176 if let Tok::Ident(s) = t.tok {
1177 out.push((s, t.span));
1178 }
1179 }
1180 other => {
1181 let t = self.next()?;
1182 return Err(Error::new(
1183 ErrorKind::BindingsParse(format!("expected identifier, got {:?}", other)),
1184 t.span,
1185 ));
1186 }
1187 }
1188 }
1189 Ok(out)
1190 }
1191
1192 fn parse_flow_block(&mut self) -> Result<IdaFlowBinding, Error> {
1193 self.expect_lbrace()?;
1194 let mut flow = IdaFlowBinding::default();
1195 loop {
1196 let t = self.peek_clone()?;
1197 match &t.tok {
1198 Tok::RBrace => {
1199 self.next()?;
1200 break;
1201 }
1202 Tok::Ident(name) => {
1203 let name = name.clone();
1204 match name.as_str() {
1205 "calls" => {
1206 self.next()?;
1207 flow.calls = self.parse_ident_block_with_spans()?;
1208 }
1209 "returns" => {
1210 self.next()?;
1211 flow.returns = self.parse_ident_block_with_spans()?;
1212 }
1213 "stops" => {
1214 self.next()?;
1215 flow.stops = self.parse_ident_block_with_spans()?;
1216 }
1217 other => {
1218 let t = self.next()?;
1219 return Err(Error::new(
1220 ErrorKind::BindingsParse(format!("unknown flow key '{}'", other)),
1221 t.span,
1222 ));
1223 }
1224 }
1225 }
1226 _ => {
1227 let t = self.next()?;
1228 return Err(Error::new(
1229 ErrorKind::BindingsParse(format!(
1230 "unexpected token {:?} inside flow block",
1231 t.tok
1232 )),
1233 t.span,
1234 ));
1235 }
1236 }
1237 }
1238 Ok(flow)
1239 }
1240}
1241
1242fn parse_strategy(s: &str, span: &Span) -> Result<Dispatch, Error> {
1243 match s {
1244 "fn_ptr_lut" => Ok(Dispatch::FnPtrLut),
1245 "jump_table" => Ok(Dispatch::JumpTable),
1246 "flat_lut" => Ok(Dispatch::FlatLut),
1247 "flat_match" => Ok(Dispatch::FlatMatch),
1248 other => Err(Error::new(
1249 ErrorKind::InvalidStrategy(other.to_string()),
1250 span.clone(),
1251 )),
1252 }
1253}