xref: /third_party/rust/crates/rust-cexpr/src/lib.rs (revision 67c3a3e4)
167c3a3e4Sopenharmony_ci// (C) Copyright 2016 Jethro G. Beekman
267c3a3e4Sopenharmony_ci//
367c3a3e4Sopenharmony_ci// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
467c3a3e4Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
567c3a3e4Sopenharmony_ci// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
667c3a3e4Sopenharmony_ci// option. This file may not be copied, modified, or distributed
767c3a3e4Sopenharmony_ci// except according to those terms.
867c3a3e4Sopenharmony_ci//! A C expression parser and evaluator.
967c3a3e4Sopenharmony_ci//!
1067c3a3e4Sopenharmony_ci//! This crate provides methods for parsing and evaluating simple C expressions. In general, the
1167c3a3e4Sopenharmony_ci//! crate can handle most arithmetic expressions that would appear in macros or the definition of
1267c3a3e4Sopenharmony_ci//! constants, as well as string and character constants.
1367c3a3e4Sopenharmony_ci//!
1467c3a3e4Sopenharmony_ci//! The main entry point for is [`token::parse`], which parses a byte string and returns its
1567c3a3e4Sopenharmony_ci//! evaluated value.
1667c3a3e4Sopenharmony_ci#![warn(rust_2018_idioms)]
1767c3a3e4Sopenharmony_ci#![warn(missing_docs)]
1867c3a3e4Sopenharmony_ci#![allow(deprecated)]
1967c3a3e4Sopenharmony_ci
2067c3a3e4Sopenharmony_cipub mod nom {
2167c3a3e4Sopenharmony_ci    //! nom's result types, re-exported.
2267c3a3e4Sopenharmony_ci    pub use nom::{error::ErrorKind, error::Error, Err, IResult, Needed};
2367c3a3e4Sopenharmony_ci}
2467c3a3e4Sopenharmony_cipub mod expr;
2567c3a3e4Sopenharmony_cipub mod literal;
2667c3a3e4Sopenharmony_cipub mod token;
2767c3a3e4Sopenharmony_ci
2867c3a3e4Sopenharmony_ci/// Parsing errors specific to C parsing
2967c3a3e4Sopenharmony_ci#[derive(Debug)]
3067c3a3e4Sopenharmony_cipub enum ErrorKind {
3167c3a3e4Sopenharmony_ci    /// Expected the specified token
3267c3a3e4Sopenharmony_ci    ExactToken(token::Kind, &'static [u8]),
3367c3a3e4Sopenharmony_ci    /// Expected one of the specified tokens
3467c3a3e4Sopenharmony_ci    ExactTokens(token::Kind, &'static [&'static str]),
3567c3a3e4Sopenharmony_ci    /// Expected a token of the specified kind
3667c3a3e4Sopenharmony_ci    TypedToken(token::Kind),
3767c3a3e4Sopenharmony_ci    /// An unknown identifier was encountered
3867c3a3e4Sopenharmony_ci    UnknownIdentifier,
3967c3a3e4Sopenharmony_ci    /// An invalid literal was encountered.
4067c3a3e4Sopenharmony_ci    ///
4167c3a3e4Sopenharmony_ci    /// When encountered, this generally means a bug exists in the data that
4267c3a3e4Sopenharmony_ci    /// was passed in or the parsing logic.
4367c3a3e4Sopenharmony_ci    InvalidLiteral,
4467c3a3e4Sopenharmony_ci    /// A full parse was requested, but data was left over after parsing finished.
4567c3a3e4Sopenharmony_ci    Partial,
4667c3a3e4Sopenharmony_ci    /// An error occurred in an underlying nom parser.
4767c3a3e4Sopenharmony_ci    Parser(nom::ErrorKind),
4867c3a3e4Sopenharmony_ci}
4967c3a3e4Sopenharmony_ci
5067c3a3e4Sopenharmony_ciimpl From<nom::ErrorKind> for ErrorKind {
5167c3a3e4Sopenharmony_ci    fn from(k: nom::ErrorKind) -> Self {
5267c3a3e4Sopenharmony_ci        ErrorKind::Parser(k)
5367c3a3e4Sopenharmony_ci    }
5467c3a3e4Sopenharmony_ci}
5567c3a3e4Sopenharmony_ci
5667c3a3e4Sopenharmony_ciimpl From<u32> for ErrorKind {
5767c3a3e4Sopenharmony_ci    fn from(_: u32) -> Self {
5867c3a3e4Sopenharmony_ci        ErrorKind::InvalidLiteral
5967c3a3e4Sopenharmony_ci    }
6067c3a3e4Sopenharmony_ci}
6167c3a3e4Sopenharmony_ci
6267c3a3e4Sopenharmony_ci/// Parsing errors specific to C parsing.
6367c3a3e4Sopenharmony_ci///
6467c3a3e4Sopenharmony_ci/// This is a superset of `(I, nom::ErrorKind)` that includes the additional errors specified by
6567c3a3e4Sopenharmony_ci/// [`ErrorKind`].
6667c3a3e4Sopenharmony_ci#[derive(Debug)]
6767c3a3e4Sopenharmony_cipub struct Error<I> {
6867c3a3e4Sopenharmony_ci    /// The remainder of the input stream at the time of the error.
6967c3a3e4Sopenharmony_ci    pub input: I,
7067c3a3e4Sopenharmony_ci    /// The error that occurred.
7167c3a3e4Sopenharmony_ci    pub error: ErrorKind,
7267c3a3e4Sopenharmony_ci}
7367c3a3e4Sopenharmony_ci
7467c3a3e4Sopenharmony_ciimpl<I> From<(I, nom::ErrorKind)> for Error<I> {
7567c3a3e4Sopenharmony_ci    fn from(e: (I, nom::ErrorKind)) -> Self {
7667c3a3e4Sopenharmony_ci        Self::from((e.0, ErrorKind::from(e.1)))
7767c3a3e4Sopenharmony_ci    }
7867c3a3e4Sopenharmony_ci}
7967c3a3e4Sopenharmony_ci
8067c3a3e4Sopenharmony_ciimpl<I> From<(I, ErrorKind)> for Error<I> {
8167c3a3e4Sopenharmony_ci    fn from(e: (I, ErrorKind)) -> Self {
8267c3a3e4Sopenharmony_ci        Self {
8367c3a3e4Sopenharmony_ci            input: e.0,
8467c3a3e4Sopenharmony_ci            error: e.1,
8567c3a3e4Sopenharmony_ci        }
8667c3a3e4Sopenharmony_ci    }
8767c3a3e4Sopenharmony_ci}
8867c3a3e4Sopenharmony_ci
8967c3a3e4Sopenharmony_ciimpl<I> From<::nom::error::Error<I>> for Error<I> {
9067c3a3e4Sopenharmony_ci    fn from(e: ::nom::error::Error<I>) -> Self {
9167c3a3e4Sopenharmony_ci        Self {
9267c3a3e4Sopenharmony_ci            input: e.input,
9367c3a3e4Sopenharmony_ci            error: e.code.into(),
9467c3a3e4Sopenharmony_ci        }
9567c3a3e4Sopenharmony_ci    }
9667c3a3e4Sopenharmony_ci}
9767c3a3e4Sopenharmony_ci
9867c3a3e4Sopenharmony_ciimpl<I> ::nom::error::ParseError<I> for Error<I> {
9967c3a3e4Sopenharmony_ci    fn from_error_kind(input: I, kind: nom::ErrorKind) -> Self {
10067c3a3e4Sopenharmony_ci        Self {
10167c3a3e4Sopenharmony_ci            input,
10267c3a3e4Sopenharmony_ci            error: kind.into(),
10367c3a3e4Sopenharmony_ci        }
10467c3a3e4Sopenharmony_ci    }
10567c3a3e4Sopenharmony_ci
10667c3a3e4Sopenharmony_ci    fn append(_: I, _: nom::ErrorKind, other: Self) -> Self {
10767c3a3e4Sopenharmony_ci        other
10867c3a3e4Sopenharmony_ci    }
10967c3a3e4Sopenharmony_ci}
11067c3a3e4Sopenharmony_ci
11167c3a3e4Sopenharmony_ci// in lieu of https://github.com/Geal/nom/issues/1010
11267c3a3e4Sopenharmony_citrait ToCexprResult<I, O> {
11367c3a3e4Sopenharmony_ci    fn to_cexpr_result(self) -> nom::IResult<I, O, Error<I>>;
11467c3a3e4Sopenharmony_ci}
11567c3a3e4Sopenharmony_ciimpl<I, O, E> ToCexprResult<I, O> for nom::IResult<I, O, E>
11667c3a3e4Sopenharmony_ciwhere
11767c3a3e4Sopenharmony_ci    Error<I>: From<E>,
11867c3a3e4Sopenharmony_ci{
11967c3a3e4Sopenharmony_ci    fn to_cexpr_result(self) -> nom::IResult<I, O, Error<I>> {
12067c3a3e4Sopenharmony_ci        match self {
12167c3a3e4Sopenharmony_ci            Ok(v) => Ok(v),
12267c3a3e4Sopenharmony_ci            Err(nom::Err::Incomplete(n)) => Err(nom::Err::Incomplete(n)),
12367c3a3e4Sopenharmony_ci            Err(nom::Err::Error(e)) => Err(nom::Err::Error(e.into())),
12467c3a3e4Sopenharmony_ci            Err(nom::Err::Failure(e)) => Err(nom::Err::Failure(e.into())),
12567c3a3e4Sopenharmony_ci        }
12667c3a3e4Sopenharmony_ci    }
12767c3a3e4Sopenharmony_ci}
12867c3a3e4Sopenharmony_ci
12967c3a3e4Sopenharmony_ci/// If the input result indicates a succesful parse, but there is data left,
13067c3a3e4Sopenharmony_ci/// return an `Error::Partial` instead.
13167c3a3e4Sopenharmony_cipub fn assert_full_parse<'i, I: 'i, O, E>(
13267c3a3e4Sopenharmony_ci    result: nom::IResult<&'i [I], O, E>,
13367c3a3e4Sopenharmony_ci) -> nom::IResult<&'i [I], O, Error<&'i [I]>>
13467c3a3e4Sopenharmony_ciwhere
13567c3a3e4Sopenharmony_ci    Error<&'i [I]>: From<E>,
13667c3a3e4Sopenharmony_ci{
13767c3a3e4Sopenharmony_ci    match result.to_cexpr_result() {
13867c3a3e4Sopenharmony_ci        Ok((rem, output)) => {
13967c3a3e4Sopenharmony_ci            if rem.is_empty() {
14067c3a3e4Sopenharmony_ci                Ok((rem, output))
14167c3a3e4Sopenharmony_ci            } else {
14267c3a3e4Sopenharmony_ci                Err(nom::Err::Error((rem, ErrorKind::Partial).into()))
14367c3a3e4Sopenharmony_ci            }
14467c3a3e4Sopenharmony_ci        }
14567c3a3e4Sopenharmony_ci        Err(nom::Err::Incomplete(n)) => Err(nom::Err::Incomplete(n)),
14667c3a3e4Sopenharmony_ci        Err(nom::Err::Failure(e)) => Err(nom::Err::Failure(e)),
14767c3a3e4Sopenharmony_ci        Err(nom::Err::Error(e)) => Err(nom::Err::Error(e)),
14867c3a3e4Sopenharmony_ci    }
14967c3a3e4Sopenharmony_ci}
150