-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for casts in macros #4
Comments
I agree, this would be great. The current state of the parser is about at my limit of understanding of parser-combinators. I think something like this would work but it'd be nice if someone could chime in on this: --- expr.rs
+++ expr.rs
@@ -258,9 +258,16 @@
($i:expr, $f:expr ) => (map_opt!($i,call!($f),EvalResult::as_numeric));
);
+struct TypeCast { /* ... */ }
+
impl<'a> PRef<'a> {
+ method!(cast<PRef<'a>,&[Token],TypeCast,::Error>, mut self,
+ delimited!(p!("("),call_m!(self.identifier),p!(")"))
+ );
+
method!(unary<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
alt!(
+ pair!(call_m!(self.cast),call_m!(self.numeric_expr)) |
delimited!(p!("("),call_m!(self.numeric_expr),p!(")")) |
numeric!(call_m!(self.literal)) |
numeric!(call_m!(self.identifier)) | Also whether this has the correct precedence, etc. (I know this needs some more fudging with the return types). |
I will not be able to help much here, all my attempts at trying nom have resulted in miserable fails 😕 |
I tried to take a look, but I'm in over my head. method!(cast<PRef<'a>,&[Token],TypeCast,::Error>, mut self,
delimited!(p!("("),call_m!(self.identifier),p!(")"))
); Has a type error, because method!(unary<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
alt!(
pair!(call_m!(self.cast),call_m!(self.numeric_expr)) |
delimited!(p!("("),call_m!(self.numeric_expr),p!(")")) |
numeric!(call_m!(self.literal)) |
numeric!(call_m!(self.identifier)) |
map_opt!(pair!(alt!( p!("+") | p!("-") | p!("~") ),call_m!(self.unary)),unary_op)
)
); because I tried to figure out how the code works by following the methods used, but I gave up... It's to complex for me :/ |
this unpleasant issue still exists. |
@jethrogb I'm new to nom and trying to implement this feature. Is my approach viable? diff --git a/src/expr.rs b/src/expr.rs
index ccfac83..40e46e9 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -65,7 +65,7 @@ impl EvalResult {
result_opt!(fn as_float: Float -> f64);
result_opt!(fn as_char: Char -> CChar);
result_opt!(fn as_str: Str -> Vec<u8>);
-
+
fn as_numeric(self) -> Option<EvalResult> {
match self {
EvalResult::Int(_) | EvalResult::Float(_) => Some(self),
@@ -130,6 +130,10 @@ macro_rules! p (
($i:expr, $c:expr) => (exact_token!($i,Punctuation,$c.as_bytes()))
);
+macro_rules! k (
+ ($i:expr, $c:expr) => (exact_token!($i,Keyword,$c.as_bytes()))
+);
+
macro_rules! one_of_punctuation (
($i:expr, $c:expr) => ({
if $i.is_empty() {
@@ -298,9 +302,29 @@ macro_rules! numeric (
($i:expr, $f:expr ) => (map_opt!($i,call!($f),EvalResult::as_numeric));
);
+enum TypeCast {
+ Int(u32), // bits of the type to cast
+ Float(u32)
+}
+
impl<'a> PRef<'a> {
+ method!(cast<PRef<'a>,&[Token],TypeCast,::Error>, mut self,
+ delimited!(p!("("), alt!(
+ do_parse!(opt!(k!("unsigned")) >> k!("int") >> (TypeCast::Int(32))) |
+ do_parse!(opt!(k!("unsigned")) >> k!("char") >> (TypeCast::Int(8))) |
+ do_parse!(opt!(k!("unsigned")) >> k!("long") >> (TypeCast::Int(32)))
+ ) ,p!(")"))
+ );
+
method!(unary<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
alt!(
+ map!(pair!(call_m!(self.cast), call_m!(self.numeric_expr)), |r| {
+ match r {
+ (TypeCast::Int(w), EvalResult::Float(f)) => EvalResult::Int(Wrapping(f as i64)),
+ (TypeCast::Int(w), EvalResult::Int(Wrapping(i))) => EvalResult::Int(Wrapping(i % 2i64.pow(w))),
+ (_, v) => v
+ }
+ }) |
delimited!(p!("("),call_m!(self.numeric_expr),p!(")")) |
numeric!(call_m!(self.literal)) |
numeric!(call_m!(self.identifier)) | |
That looks like it's going in the right direction. My main concerns are:
|
Thanks for the reply. The precedence is wrong in fact. For example: #define Float_236p3 (int)233.3 + 3.3 // Int_236 if we are using the patch posted previously We should not expect a map!(pair!(call_m!(self.cast), call_m!(self.unary)), |(c, r)| r.cast(c) ) | Also, |
rust-lang/rust-bindgen#316
Some macro defined constants are written like this:
But currently, they are just ignored. It would be great to support casts.
The text was updated successfully, but these errors were encountered: