quil_rs/program/error/result.rs
1// Copyright 2022 Rigetti Computing
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::parser::{ErrorInput, ParseError};
16use crate::program::error::LeftoverError;
17use crate::program::ParseProgramError;
18use nom::Finish;
19
20use super::SyntaxError;
21
22/// If parsing was successful but there is leftover input, returns a [`SyntaxError::Leftover`] containing the output.
23///
24/// See also [`LeftoverError`].
25pub fn disallow_leftover<I, O, E>(result: nom::IResult<I, O, ParseError>) -> Result<O, E>
26where
27 I: ErrorInput,
28 E: From<SyntaxError<O>>,
29{
30 match result.finish() {
31 Ok((leftover, parsed)) => {
32 if leftover.is_empty() {
33 Ok(parsed)
34 } else {
35 Err(E::from(SyntaxError::from(LeftoverError::new(
36 leftover, parsed,
37 ))))
38 }
39 }
40 Err(err) => Err(E::from(SyntaxError::from(err))),
41 }
42}
43
44/// Map the parsed output into another value.
45///
46/// This should be preferred over [`Result::map`], as this will map both the `Ok` case and when
47/// there is a [`LeftoverError`].
48pub fn map_parsed<O, O2>(
49 result: Result<O, ParseProgramError<O>>,
50 map: impl Fn(O) -> O2,
51) -> Result<O2, ParseProgramError<O2>> {
52 match result {
53 Ok(parsed) => Ok(map(parsed)),
54 Err(err) => Err(err.map_parsed(map)),
55 }
56}
57
58/// If this `result` is `Err(ProgramParsingError::Leftover)`, converts it to `Ok(_)` with the parsed
59/// output.
60pub fn recover<O>(result: Result<O, ParseProgramError<O>>) -> Result<O, ParseProgramError<O>> {
61 match result {
62 Ok(parsed) => Ok(parsed),
63 Err(ParseProgramError::Syntax(err)) => err.recover().map_err(ParseProgramError::from),
64 Err(err) => Err(err),
65 }
66}