quil_rs/parser/mod.rs
1// Copyright 2021 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.
14use nom::IResult;
15
16pub(crate) use expression::parse_expression;
17pub(crate) use instruction::parse_instructions;
18pub(crate) use lexer::lex;
19
20mod command;
21mod gate;
22mod macros;
23
24pub(crate) mod common;
25mod error;
26mod expression;
27pub(crate) mod instruction;
28mod lexer;
29pub(crate) mod pragma_extern;
30mod token;
31
32pub(crate) use error::{ErrorInput, InternalParseError};
33pub use error::{ParseError, ParserErrorKind};
34pub use lexer::{Command, DataType, LexError, Modifier};
35pub use token::{KeywordToken, Token, TokenWithLocation};
36
37pub(crate) type ParserInput<'a> = &'a [TokenWithLocation<'a>];
38type InternalParserResult<'a, R, E = InternalParseError<'a>> = IResult<ParserInput<'a>, R, E>;
39
40/// Pops the first token off of the `input` and returns it and the remaining input.
41///
42/// This also converts the first item from [`TokenWithLocation`] to [`Token`], which makes match
43/// statements more straightforward.
44pub(crate) fn split_first_token(input: ParserInput<'_>) -> Option<(&Token, ParserInput<'_>)> {
45 input
46 .split_first()
47 .map(|(first, rest)| (first.as_token(), rest))
48}
49
50/// Returns the first token of the input as [`Token`] instead of [`TokenWithLocation`].
51pub(crate) fn first_token(input: ParserInput<'_>) -> Option<&Token> {
52 input.first().map(TokenWithLocation::as_token)
53}
54
55/// Extracts the actual error from [`nom::Err`].
56///
57/// Instead of using this with [`Result::map_err`], use [`nom::Finish::finish`].
58///
59/// # Panics
60///
61/// Will panic if the error is [`nom::Err::Incomplete`]. This only happens for streaming parsers,
62/// which we do not use as of 2022-09-14.
63pub(crate) fn extract_nom_err<E>(err: nom::Err<E>) -> E {
64 // If this ever panics, switch to returning an Option
65 match err {
66 nom::Err::Incomplete(_) => {
67 unreachable!("can't be incomplete if all parsers are complete variants")
68 }
69 nom::Err::Error(inner) => inner,
70 nom::Err::Failure(inner) => inner,
71 }
72}