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
729 loop {
730 let t = self.peek_clone()?;
731 match &t.tok {
732 Tok::RBrace => {
733 self.next()?;
734 break;
735 }
736 Tok::Eof => {
737 return Err(Error::new(
738 ErrorKind::BindingsParse(
739 "unexpected end of file inside dispatch block".to_string(),
740 ),
741 t.span.clone(),
742 ));
743 }
744 Tok::Ident(name) => {
745 let name = name.clone();
746 match name.as_str() {
747 "output" => {
748 self.next()?;
749 let (s, _) = self.expect_string()?;
750 output = Some(s);
751 }
752 "context" => {
753 self.next()?;
754 let (s, _) = self.expect_ident()?;
755 context = Some(s);
756 }
757 "handlers" => {
758 self.next()?;
759 let (s, _) = self.expect_ident()?;
760 handlers = Some(s);
761 }
762 "strategy" => {
763 self.next()?;
764 let (s, span) = self.expect_ident()?;
765 strategy = Some(parse_strategy(&s, &span)?);
766 }
767 "invalid_handler" => {
768 self.next()?;
769 let (s, _) = self.expect_ident()?;
770 invalid_handler = Some(s);
771 }
772 "instruction_type" => {
773 self.next()?;
774 let (path, _) = self.expect_ident()?;
775 let next = self.peek()?;
777 if matches!(next.tok, Tok::LBrace) {
778 self.next()?;
779 let mut inner_out: Option<String> = None;
780 loop {
781 let t = self.peek_clone()?;
782 match &t.tok {
783 Tok::RBrace => {
784 self.next()?;
785 break;
786 }
787 Tok::Ident(n) if n == "output" => {
788 self.next()?;
789 let (s, _) = self.expect_string()?;
790 inner_out = Some(s);
791 }
792 _ => {
793 let t = self.next()?;
794 return Err(Error::new(
795 ErrorKind::BindingsParse(format!(
796 "unexpected token {:?} inside instruction_type block",
797 t.tok
798 )),
799 t.span,
800 ));
801 }
802 }
803 }
804 instruction_type = Some(InstructionTypeBinding {
805 type_path: path,
806 output: inner_out,
807 });
808 } else {
809 instruction_type = Some(InstructionTypeBinding {
810 type_path: path,
811 output: None,
812 });
813 }
814 }
815 "handler" => {
816 let group = self.parse_handler_block()?;
817 handler_groups.push(group);
818 }
819 "subdispatch" => {
820 let sd = self.parse_dispatch_block()?;
821 subdispatches.push(sd);
822 }
823 other => {
824 let t = self.next()?;
825 return Err(Error::new(
826 ErrorKind::BindingsParse(format!(
827 "unexpected '{}' inside dispatch block",
828 other
829 )),
830 t.span,
831 ));
832 }
833 }
834 }
835 _ => {
836 let t = self.next()?;
837 return Err(Error::new(
838 ErrorKind::BindingsParse(format!(
839 "unexpected token {:?} inside dispatch block",
840 t.tok
841 )),
842 t.span,
843 ));
844 }
845 }
846 }
847
848 Ok(DispatchBinding {
849 decoder_name: name,
850 span,
851 output,
852 context,
853 handlers,
854 strategy,
855 invalid_handler,
856 instruction_type,
857 handler_groups,
858 subdispatches,
859 })
860 }
861
862 fn parse_handler_block(&mut self) -> Result<HandlerBinding, Error> {
863 self.next()?;
865 let (handler_name, span) = self.expect_ident()?;
866
867 let mut generic_params: Vec<String> = Vec::new();
869 let next = self.peek()?;
870 if matches!(next.tok, Tok::LAngle) {
871 self.next()?;
872 loop {
873 let t = self.peek_clone()?;
874 match &t.tok {
875 Tok::RAngle => {
876 self.next()?;
877 break;
878 }
879 Tok::Ident(_) => {
880 let mut parts: Vec<String> = Vec::new();
883 loop {
884 let t = self.peek_clone()?;
885 match &t.tok {
886 Tok::Ident(s) => {
887 let s = s.clone();
888 self.next()?;
889 parts.push(s);
890 }
891 Tok::Comma => {
892 self.next()?;
893 break;
894 }
895 Tok::RAngle => break,
896 other => {
897 let t = self.next()?;
898 return Err(Error::new(
899 ErrorKind::BindingsParse(format!(
900 "unexpected token {:?} in generic params",
901 other
902 )),
903 t.span,
904 ));
905 }
906 }
907 }
908 if !parts.is_empty() {
909 generic_params.push(parts.join(" "));
910 }
911 }
912 _ => {
913 let t = self.next()?;
914 return Err(Error::new(
915 ErrorKind::BindingsParse(format!(
916 "unexpected token {:?} in generic params",
917 t.tok
918 )),
919 t.span,
920 ));
921 }
922 }
923 }
924 }
925
926 self.expect_lbrace()?;
927 let mut instructions: Vec<(String, Span)> = Vec::new();
928 loop {
929 let t = self.peek_clone()?;
930 match &t.tok {
931 Tok::RBrace => {
932 self.next()?;
933 break;
934 }
935 Tok::Comma => {
936 self.next()?;
937 }
938 Tok::Ident(name) => {
939 let name = name.clone();
940 let t = self.next()?;
941 instructions.push((name, t.span));
942 }
943 other => {
944 let t = self.next()?;
945 return Err(Error::new(
946 ErrorKind::BindingsParse(format!(
947 "unexpected token {:?} inside handler block",
948 other
949 )),
950 t.span,
951 ));
952 }
953 }
954 }
955
956 Ok(HandlerBinding {
957 handler_name,
958 generic_params,
959 instructions,
960 span,
961 })
962 }
963
964 fn parse_processor_block(&mut self) -> Result<IdaProcessorBinding, Error> {
965 self.next()?; let (name, span) = self.expect_ident()?;
967 self.expect_lbrace()?;
968
969 let mut output: Option<String> = None;
970 let mut p_name: Option<String> = None;
971 let mut long_name: Option<String> = None;
972 let mut id: Option<u64> = None;
973 let mut address_size: Option<u32> = None;
974 let mut bytes_per_unit: Option<u32> = None;
975 let mut registers: Vec<String> = Vec::new();
976 let mut segment_registers: Vec<(String, Span)> = Vec::new();
977 let mut flow = IdaFlowBinding::default();
978
979 loop {
980 let t = self.peek_clone()?;
981 match &t.tok {
982 Tok::RBrace => {
983 self.next()?;
984 break;
985 }
986 Tok::Eof => {
987 return Err(Error::new(
988 ErrorKind::BindingsParse(
989 "unexpected end of file inside processor block".to_string(),
990 ),
991 t.span.clone(),
992 ));
993 }
994 Tok::Ident(name) => {
995 let name = name.clone();
996 match name.as_str() {
997 "output" => {
998 self.next()?;
999 let (s, _) = self.expect_string()?;
1000 output = Some(s);
1001 }
1002 "name" => {
1003 self.next()?;
1004 let (s, _) = self.expect_string()?;
1005 p_name = Some(s);
1006 }
1007 "long_name" => {
1008 self.next()?;
1009 let (s, _) = self.expect_string()?;
1010 long_name = Some(s);
1011 }
1012 "id" => {
1013 self.next()?;
1014 let (n, _) = self.expect_number()?;
1015 id = Some(n);
1016 }
1017 "address_size" => {
1018 self.next()?;
1019 let (n, _) = self.expect_number()?;
1020 address_size = Some(n as u32);
1021 }
1022 "bytes_per_unit" => {
1023 self.next()?;
1024 let (n, _) = self.expect_number()?;
1025 bytes_per_unit = Some(n as u32);
1026 }
1027 "registers" => {
1028 self.next()?;
1029 registers = self.parse_ident_block()?;
1030 }
1031 "segment_registers" => {
1032 self.next()?;
1033 segment_registers = self.parse_ident_block_with_spans()?;
1034 }
1035 "flow" => {
1036 self.next()?;
1037 flow = self.parse_flow_block()?;
1038 }
1039 other => {
1040 let t = self.next()?;
1041 return Err(Error::new(
1042 ErrorKind::BindingsParse(format!(
1043 "unexpected '{}' inside processor block",
1044 other
1045 )),
1046 t.span,
1047 ));
1048 }
1049 }
1050 }
1051 _ => {
1052 let t = self.next()?;
1053 return Err(Error::new(
1054 ErrorKind::BindingsParse(format!(
1055 "unexpected token {:?} inside processor block",
1056 t.tok
1057 )),
1058 t.span,
1059 ));
1060 }
1061 }
1062 }
1063
1064 Ok(IdaProcessorBinding {
1065 decoder_name: name,
1066 span,
1067 output,
1068 name: p_name,
1069 long_name,
1070 id,
1071 address_size,
1072 bytes_per_unit,
1073 registers,
1074 segment_registers,
1075 flow,
1076 })
1077 }
1078
1079 fn parse_architecture_block(&mut self) -> Result<BinjaArchitectureBinding, Error> {
1080 self.next()?; let (name, span) = self.expect_ident()?;
1082 self.expect_lbrace()?;
1083
1084 let mut output: Option<String> = None;
1085 let mut a_name: Option<String> = None;
1086 let mut address_size: Option<u32> = None;
1087 let mut default_int_size: Option<u32> = None;
1088 let mut endianness: Option<(String, Span)> = None;
1089 let mut registers: Vec<String> = Vec::new();
1090
1091 loop {
1092 let t = self.peek_clone()?;
1093 match &t.tok {
1094 Tok::RBrace => {
1095 self.next()?;
1096 break;
1097 }
1098 Tok::Eof => {
1099 return Err(Error::new(
1100 ErrorKind::BindingsParse(
1101 "unexpected end of file inside architecture block".to_string(),
1102 ),
1103 t.span.clone(),
1104 ));
1105 }
1106 Tok::Ident(name) => {
1107 let name = name.clone();
1108 match name.as_str() {
1109 "output" => {
1110 self.next()?;
1111 let (s, _) = self.expect_string()?;
1112 output = Some(s);
1113 }
1114 "name" => {
1115 self.next()?;
1116 let (s, _) = self.expect_string()?;
1117 a_name = Some(s);
1118 }
1119 "address_size" => {
1120 self.next()?;
1121 let (n, _) = self.expect_number()?;
1122 address_size = Some(n as u32);
1123 }
1124 "default_int_size" => {
1125 self.next()?;
1126 let (n, _) = self.expect_number()?;
1127 default_int_size = Some(n as u32);
1128 }
1129 "endianness" => {
1130 self.next()?;
1131 let (s, span) = self.expect_ident()?;
1132 endianness = Some((s, span));
1133 }
1134 "registers" => {
1135 self.next()?;
1136 registers = self.parse_ident_block()?;
1137 }
1138 other => {
1139 let t = self.next()?;
1140 return Err(Error::new(
1141 ErrorKind::BindingsParse(format!(
1142 "unexpected '{}' inside architecture block",
1143 other
1144 )),
1145 t.span,
1146 ));
1147 }
1148 }
1149 }
1150 _ => {
1151 let t = self.next()?;
1152 return Err(Error::new(
1153 ErrorKind::BindingsParse(format!(
1154 "unexpected token {:?} inside architecture block",
1155 t.tok
1156 )),
1157 t.span,
1158 ));
1159 }
1160 }
1161 }
1162
1163 Ok(BinjaArchitectureBinding {
1164 decoder_name: name,
1165 span,
1166 output,
1167 name: a_name,
1168 address_size,
1169 default_int_size,
1170 endianness,
1171 registers,
1172 })
1173 }
1174
1175 fn parse_ident_block(&mut self) -> Result<Vec<String>, Error> {
1176 let pairs = self.parse_ident_block_with_spans()?;
1177 Ok(pairs.into_iter().map(|(s, _)| s).collect())
1178 }
1179
1180 fn parse_string_block(&mut self) -> Result<Vec<String>, Error> {
1181 self.expect_lbrace()?;
1182 let mut out = Vec::new();
1183 loop {
1184 let t = self.peek_clone()?;
1185 match &t.tok {
1186 Tok::RBrace => {
1187 self.next()?;
1188 break;
1189 }
1190 Tok::Comma => {
1191 self.next()?;
1192 }
1193 Tok::Str(_) => {
1194 let t = self.next()?;
1195 if let Tok::Str(s) = t.tok {
1196 out.push(s);
1197 }
1198 }
1199 other => {
1200 let t = self.next()?;
1201 return Err(Error::new(
1202 ErrorKind::BindingsParse(format!(
1203 "expected string literal, got {:?}",
1204 other
1205 )),
1206 t.span,
1207 ));
1208 }
1209 }
1210 }
1211 Ok(out)
1212 }
1213
1214 fn parse_ident_block_with_spans(&mut self) -> Result<Vec<(String, Span)>, Error> {
1215 self.expect_lbrace()?;
1216 let mut out = Vec::new();
1217 loop {
1218 let t = self.peek_clone()?;
1219 match &t.tok {
1220 Tok::RBrace => {
1221 self.next()?;
1222 break;
1223 }
1224 Tok::Comma => {
1225 self.next()?;
1226 }
1227 Tok::Ident(_) => {
1228 let t = self.next()?;
1229 if let Tok::Ident(s) = t.tok {
1230 out.push((s, t.span));
1231 }
1232 }
1233 other => {
1234 let t = self.next()?;
1235 return Err(Error::new(
1236 ErrorKind::BindingsParse(format!("expected identifier, got {:?}", other)),
1237 t.span,
1238 ));
1239 }
1240 }
1241 }
1242 Ok(out)
1243 }
1244
1245 fn parse_flow_block(&mut self) -> Result<IdaFlowBinding, Error> {
1246 self.expect_lbrace()?;
1247 let mut flow = IdaFlowBinding::default();
1248 loop {
1249 let t = self.peek_clone()?;
1250 match &t.tok {
1251 Tok::RBrace => {
1252 self.next()?;
1253 break;
1254 }
1255 Tok::Ident(name) => {
1256 let name = name.clone();
1257 match name.as_str() {
1258 "calls" => {
1259 self.next()?;
1260 flow.calls = self.parse_ident_block_with_spans()?;
1261 }
1262 "returns" => {
1263 self.next()?;
1264 flow.returns = self.parse_ident_block_with_spans()?;
1265 }
1266 "stops" => {
1267 self.next()?;
1268 flow.stops = self.parse_ident_block_with_spans()?;
1269 }
1270 other => {
1271 let t = self.next()?;
1272 return Err(Error::new(
1273 ErrorKind::BindingsParse(format!("unknown flow key '{}'", other)),
1274 t.span,
1275 ));
1276 }
1277 }
1278 }
1279 _ => {
1280 let t = self.next()?;
1281 return Err(Error::new(
1282 ErrorKind::BindingsParse(format!(
1283 "unexpected token {:?} inside flow block",
1284 t.tok
1285 )),
1286 t.span,
1287 ));
1288 }
1289 }
1290 }
1291 Ok(flow)
1292 }
1293}
1294
1295fn parse_strategy(s: &str, span: &Span) -> Result<Dispatch, Error> {
1296 match s {
1297 "fn_ptr_lut" => Ok(Dispatch::FnPtrLut),
1298 "jump_table" => Ok(Dispatch::JumpTable),
1299 "flat_lut" => Ok(Dispatch::FlatLut),
1300 "flat_match" => Ok(Dispatch::FlatMatch),
1301 other => Err(Error::new(
1302 ErrorKind::InvalidStrategy(other.to_string()),
1303 span.clone(),
1304 )),
1305 }
1306}