浏览代码

Emit an error if no parses in a `choice!` work

Isaac Woods 5 年之前
父节点
当前提交
33e22cddc2
共有 2 个文件被更改,包括 14 次插入2 次删除
  1. 3 0
      aml_parser/src/lib.rs
  2. 11 2
      aml_parser/src/parser.rs

+ 3 - 0
aml_parser/src/lib.rs

@@ -36,6 +36,9 @@ pub enum AmlError {
     IncompatibleValueConversion,
     UnterminatedStringConstant,
     InvalidStringConstant,
+    /// Error produced when none of the parsers in a `choice!` could parse the next part of the
+    /// stream. Contains the next two bytes to make debugging missing extended opcodes easier.
+    NoParsersCouldParse([u8; 2]),
 }
 
 #[derive(Debug)]

+ 11 - 2
aml_parser/src/parser.rs

@@ -395,13 +395,21 @@ where
     }
 }
 
+pub(crate) fn emit_no_parsers_could_parse<'a, 'c, R>() -> impl Parser<'a, 'c, R>
+where
+    'c: 'a,
+{
+    |input: &'a [u8], context| {
+        Err((input, context, AmlError::NoParsersCouldParse([input[0], input[1]])))
+    }
+}
+
 /// Takes a number of parsers, and tries to apply each one to the input in order. Returns the
 /// result of the first one that succeeds, or fails if all of them fail.
-// TODO: maybe this should emit a custom error at the end? "None of these parsers could parse
-// this?" Or maybe just a specific UnexpectedByte?
 pub macro choice {
     ($first_parser: expr) => {
         $first_parser
+        .or(emit_no_parsers_could_parse())
     },
 
     ($first_parser: expr, $($other_parser: expr),*) => {
@@ -409,6 +417,7 @@ pub macro choice {
         $(
             .or($other_parser)
          )*
+        .or(emit_no_parsers_could_parse())
     }
 }