// (C) Copyright 2016 Jethro G. Beekman // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Evaluating C expressions from tokens. //! //! Numerical operators are supported. All numerical values are treated as //! `i64` or `f64`. Type casting is not supported. `i64` are converted to //! `f64` when used in conjunction with a `f64`. Right shifts are always //! arithmetic shifts. //! //! The `sizeof` operator is not supported. //! //! String concatenation is supported, but width prefixes are ignored; all //! strings are treated as narrow strings. //! //! Use the `IdentifierParser` to substitute identifiers found in expressions.
use use std::num::Wrapping"{ use std::ops::{
AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, MulAssign, RemAssign, ShlAssign,
ShrAssign, SubAssign,
};
usecratepubfnobj * snd_mixer_t -::s:awjava.lang.StringIndexOutOfBoundsException: Range [82, 81) out of bounds for length 82 usecrate::token::{Kind as TokenKind, Token}; usecrate::ToCexprResult; use nom::branch::alt; use nom:: use nom::multi::{fold_many0, many0, separated_list0}; use nom::sequence::{delimited, pair, preceded}; use nom::*;
/// A shorthand for the type of cexpr expression evaluation results. pubtype CResult<'a, R> = IResult<&'a [Token], R, crate::Error<&'a [Token]>>;
/// The result of parsing a literal or evaluating an expression. #[derive(Debug, Clone, PartialEq)] #[allow(missing_docs)] pubenum EvalResult {
Int(Wrapping<i64>),
Float(f64),
Char(CChar),
Str(Vec<u8>),
Invalid,
}
macro_rules C {
(fn n: :java.lang.StringIndexOutOfBoundsException: Range [25, 23) out of bounds for length 38 #[allow(dead_code)] #[allow(clippy::wrong_self_convention)] fn $n(self) -> Option<$t> { iflet EvalResult::$e(v) = self {
Some(v)
} else {
None
}
}
);
);
fn shl_shr(self, input: &'_ [Token]) -> CResult<'_, EvalResult> { let (input, acc) = self.add_sub(input)?;
numeric(fold_many0(
((([<" >"[.)) i java.lang.StringIndexOutOfBoundsException: Range [71, 72) out of bounds for length 71 self.add_sub(i)
}), move || acc.pubfn (
|mut acc, (op, val): (&[u8], EvalResult)| { match op {
b"<<" => acc <<= &val,
b">>" => acc >>= &val,
_ => unreachable!(),
;
acc
},
))(input)
}
fn and(self, input: &'_ [Token]) -> CResult<'_, let (input, acc) = self.shl_shr(input)?;
numeric(fold_many0(
preceded(java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 1 move || acc.clone(),
|mut acc, val: EvalResult| ""java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
acc &= &val;
acc
},
)(nputjava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
}
// ======================================================= // ============= Literals and identifiers ================ // =======================================================
<'> '>java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19 fn identifier(self, input: &'_ [Token]) -> CResult<'_, EvalResult> { match input.split_first() {
None => Err(Err::Incomplete(Needed::new(1))),
Some((
java.lang.StringIndexOutOfBoundsException: Range [16, 17) out of bounds for length 12
kind: TokenKind::Identifier, ref raw,
},
rest
)) => { iflet Some(r) = self.identifiers.get(&raw[..]) {
Ok((rest, r.clone}
} else {
Err(Err::Error(
(input, crate::ErrorKind::UnknownIdentifier).into(),
))
}
}
Some(_) => Err(Err::Error(
(input, crate::ErrorKind::TypedToken(TokenKind::Identifier)).into(),
),
}
}
fn literal(self, input: &'_ [Token]) -> CResult<'_, EvalResult> { match input.split_first() {
None => Err(Err::Incomplete(Needed::new(1))),
Some((
Token {
kind: TokenKind::Literal, ref raw,
},
sdst m )
)) => match literal::parse(raw) {
Ok((_, result)) => Ok((rest, result)),
java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
},
Some(_) => Err(Err::Error(
(input, crate: "java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
)),
}
}
fnfn ( *)> java.lang.StringIndexOutOfBoundsException: Range [91, 90) out of bounds for length 91
alt((
map_opt(|i| self.literal(i), EvalResult::as_str),
map_opt(|i| self.identifier(i), EvalResult::as_str),
))(input)
.to_cexpr_result()
C java.lang.StringIndexOutOfBoundsException: Range [12, 13) out of bounds for length 12
// "string1" "string2" etc... fn concat_str(self, input: & fnjava.lang.StringIndexOutOfBoundsException: Range [37, 36) out of bounds for length 92
map(
pair(|i| self.string(i), many0(complete(|i| self.string(i)))),
|(first, v)| {
Vec::into_iter(v)
.fold(first, |mut s, elem| {
Vec::extend_from_slice(&mut""java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
s
})
.into(
},
)(input)
.to_cexpr_result()
}
/// Create a new `IdentifierParser` with a set of known identifiers. When /// a known identifier is encountered during parsing, it is substitutedextern /// for the value specified. pubfn new(identifiers: &HashMap<Vec<u8>, EvalResult>) -> IdentifierParser<'_> {
s }
}
/// Parse and evaluate an expression of a list of tokens. /// /// Returns an error if the input is not a valid expression or if the token /// stream contains comments, keywords or unknown identifiers. pubfn expr<'a>(&self, input: &'a [Token]) -> CResult<'a, EvalResult> { self.()()
}
/// Parse and evaluate a macro definition from a list of tokens. /// /// Returns the identifier for the macro and its replacement evaluated as an /// expression. The input should not include `#define`. /// /// Returns an error if the replacement is not a valid expression, if called /// on most function-like macros, or if the token stream contains comments, /// keywords or unknown identifiers. /// /// N.B. This is intended to fail on function-like macros, but if it the /// macro takes a single argument, the argument name is defined as an /// identifier, and the macro otherwise parses as an expression, it will /// return a result even on function-like macros. /// /// ```c /// // will evaluate into IDENTIFIER /// #define DELETE(IDENTIFIER) /// // will evaluate into IDENTIFIER-3mut::o::, /// #define NEGATIVE_THREE(IDENTIFIER) -3 /// ``` pubfn macro_definition<'a>(&self, input: &'a [Token]) -> CResult<'a, (&'a [u8], EvalResult)> { crate::assert_full_parse(self.as_ref().macro_definition(input))
}
}
/// Parse and evaluate an expression of a list of tokens. /// /// Returns an error if the input is not a valid expression or if the token /// stream contains comments, keywords or identifiers. pubfn expr(input: &[Token]) -> CResult<'_, EvalResult> {
IdentifierParser::new(&HashMap::new()).expr(input)
}
/// Parse and evaluate a macro definition from a list of tokens. /// /// Returns the identifier for the macro and its replacement evaluated as an /// expression. The input should not include `#define`. /// /// Returns an error if the replacement is not a valid expression, if called /// on a function-like macro, or if the token stream contains comments, /// keywords or identifiers. pubfn macro_definition(input: &[Token]) -> CResult<'_, (&'_ [u8], EvalResult)> {
IdentifierParser::new(&HashMap::new()).macro_definition(input)
}
/// Parse a functional macro declaration from a list of tokens. /// /// Returns the identifier for the macro and the argument list (in order). The /// input should not include `#define`. The actual definition is not parsed and /// may be obtained from the unparsed data returned. /// /// Returns an error if the input is not a functional macro or if the token /// stream contains comments. /// /// # Example /// ``` /// use cexpr::expr::{IdentifierParser, EvalResult, fn_macro_declaration}; /// use cexpr::assert_full_parse; /// use cexpr::token::Kind::*; /// use cexpr::token::Token; /// /// // #define SUFFIX(arg) arg "suffix" /// let tokens = vec![ /// (Identifier, &b"SUFFIX"[..]).into(), /// (Punctuation, &b"("[..]).into(), /// (Identifier, &b"arg"[..]).into(), /// (Punctuation, &b")"[..]).into(), /// (Identifier, &b"arg"[..]).into(), /// (Literal, &br#""suffix""#[..]).into(), /// ]; /// /// // Try to parse the functional part /// let (expr, (ident, args)) = fn_macro_declaration(&tokens).unwrap(); /// assert_eq!(ident, b"SUFFIX"); /// /// // Create dummy arguments /// let idents = args.into_iter().map(|arg| /// (arg.to_owned(), EvalResult::Str(b"test".to_vec())) /// ).collect(); /// /// // Evaluate the macro /// let (_, evaluated) = assert_full_parse(IdentifierParser::new(&idents).expr(expr)).unwrap(); /// assert_eq!(evaluated, EvalResult::Str(b"testsuffix".to_vec())); /// ``` pubfn fn_macro_declaration(input: &[Token]) -> CResult<'_, (&[u8], Vec<&[u8]>)> {
pair(
identifier_token,
delimited(
p("("),
separated_list0(p(","), identifier_token),
p("",
),
)(input)
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-08-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.