1// (C) Copyright 2016 Jethro G. Beekman 2// 3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 6// option. This file may not be copied, modified, or distributed 7// except according to those terms. 8//! A C expression parser and evaluator. 9//! 10//! This crate provides methods for parsing and evaluating simple C expressions. In general, the 11//! crate can handle most arithmetic expressions that would appear in macros or the definition of 12//! constants, as well as string and character constants. 13//! 14//! The main entry point for is [`token::parse`], which parses a byte string and returns its 15//! evaluated value. 16#![warn(rust_2018_idioms)] 17#![warn(missing_docs)] 18#![allow(deprecated)] 19 20pub mod nom { 21 //! nom's result types, re-exported. 22 pub use nom::{error::ErrorKind, error::Error, Err, IResult, Needed}; 23} 24pub mod expr; 25pub mod literal; 26pub mod token; 27 28/// Parsing errors specific to C parsing 29#[derive(Debug)] 30pub enum ErrorKind { 31 /// Expected the specified token 32 ExactToken(token::Kind, &'static [u8]), 33 /// Expected one of the specified tokens 34 ExactTokens(token::Kind, &'static [&'static str]), 35 /// Expected a token of the specified kind 36 TypedToken(token::Kind), 37 /// An unknown identifier was encountered 38 UnknownIdentifier, 39 /// An invalid literal was encountered. 40 /// 41 /// When encountered, this generally means a bug exists in the data that 42 /// was passed in or the parsing logic. 43 InvalidLiteral, 44 /// A full parse was requested, but data was left over after parsing finished. 45 Partial, 46 /// An error occurred in an underlying nom parser. 47 Parser(nom::ErrorKind), 48} 49 50impl From<nom::ErrorKind> for ErrorKind { 51 fn from(k: nom::ErrorKind) -> Self { 52 ErrorKind::Parser(k) 53 } 54} 55 56impl From<u32> for ErrorKind { 57 fn from(_: u32) -> Self { 58 ErrorKind::InvalidLiteral 59 } 60} 61 62/// Parsing errors specific to C parsing. 63/// 64/// This is a superset of `(I, nom::ErrorKind)` that includes the additional errors specified by 65/// [`ErrorKind`]. 66#[derive(Debug)] 67pub struct Error<I> { 68 /// The remainder of the input stream at the time of the error. 69 pub input: I, 70 /// The error that occurred. 71 pub error: ErrorKind, 72} 73 74impl<I> From<(I, nom::ErrorKind)> for Error<I> { 75 fn from(e: (I, nom::ErrorKind)) -> Self { 76 Self::from((e.0, ErrorKind::from(e.1))) 77 } 78} 79 80impl<I> From<(I, ErrorKind)> for Error<I> { 81 fn from(e: (I, ErrorKind)) -> Self { 82 Self { 83 input: e.0, 84 error: e.1, 85 } 86 } 87} 88 89impl<I> From<::nom::error::Error<I>> for Error<I> { 90 fn from(e: ::nom::error::Error<I>) -> Self { 91 Self { 92 input: e.input, 93 error: e.code.into(), 94 } 95 } 96} 97 98impl<I> ::nom::error::ParseError<I> for Error<I> { 99 fn from_error_kind(input: I, kind: nom::ErrorKind) -> Self { 100 Self { 101 input, 102 error: kind.into(), 103 } 104 } 105 106 fn append(_: I, _: nom::ErrorKind, other: Self) -> Self { 107 other 108 } 109} 110 111// in lieu of https://github.com/Geal/nom/issues/1010 112trait ToCexprResult<I, O> { 113 fn to_cexpr_result(self) -> nom::IResult<I, O, Error<I>>; 114} 115impl<I, O, E> ToCexprResult<I, O> for nom::IResult<I, O, E> 116where 117 Error<I>: From<E>, 118{ 119 fn to_cexpr_result(self) -> nom::IResult<I, O, Error<I>> { 120 match self { 121 Ok(v) => Ok(v), 122 Err(nom::Err::Incomplete(n)) => Err(nom::Err::Incomplete(n)), 123 Err(nom::Err::Error(e)) => Err(nom::Err::Error(e.into())), 124 Err(nom::Err::Failure(e)) => Err(nom::Err::Failure(e.into())), 125 } 126 } 127} 128 129/// If the input result indicates a succesful parse, but there is data left, 130/// return an `Error::Partial` instead. 131pub fn assert_full_parse<'i, I: 'i, O, E>( 132 result: nom::IResult<&'i [I], O, E>, 133) -> nom::IResult<&'i [I], O, Error<&'i [I]>> 134where 135 Error<&'i [I]>: From<E>, 136{ 137 match result.to_cexpr_result() { 138 Ok((rem, output)) => { 139 if rem.is_empty() { 140 Ok((rem, output)) 141 } else { 142 Err(nom::Err::Error((rem, ErrorKind::Partial).into())) 143 } 144 } 145 Err(nom::Err::Incomplete(n)) => Err(nom::Err::Incomplete(n)), 146 Err(nom::Err::Failure(e)) => Err(nom::Err::Failure(e)), 147 Err(nom::Err::Error(e)) => Err(nom::Err::Error(e)), 148 } 149} 150