Created
March 17, 2022 04:18
-
-
Save pollend/dda6eb003e40302cbd43c6d03c7f3faf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// parser combinators are constructed from the bottom up: | |
/// first we write parsers for the smallest elements (here a space character), | |
/// then we'll combine them in larger parsers | |
fn sp<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> { | |
let chars = " \t\r\n"; | |
// nom combinators like `take_while` return a function. That function is the | |
// parser,to which we can pass the input | |
take_while(move |c| chars.contains(c))(i) | |
} | |
fn parse_fundamental_type<'a, E: ParseError<&'a str> + ContextError<&'a str>>( | |
i: &'a str, | |
) -> IResult<&'a str, FundamentalType, E> { | |
#[derive(Clone)] | |
enum SymbolType { | |
SignedType, | |
UnsignedType, | |
ShortType, | |
LongType, | |
IntType, | |
} | |
(context("fundamental_type",map_opt( | |
many1(alt(( | |
value(SymbolType::UnsignedType, preceded(sp, tag("unsigned"))), | |
value(SymbolType::SignedType, preceded(sp, tag("signed"))), | |
value(SymbolType::ShortType, preceded(sp, tag("short"))), | |
value(SymbolType::IntType, preceded(sp, tag("int"))), | |
value(SymbolType::LongType, preceded(sp, tag("long"))), | |
))), | |
|items| { | |
let signed_count = items.iter().filter(|x| match x { | |
SymbolType::SignedType => true, | |
_ => false | |
}).count(); | |
let unsigned_count = items | |
.iter() | |
.filter(|x| match x { | |
SymbolType::UnsignedType => true, | |
_ => false | |
}) | |
.count(); | |
let short_count = items.iter().filter(|x| match x { | |
SymbolType::ShortType => true, | |
_ => false | |
}).count(); | |
let int_count = items.iter().filter(|x| match x { | |
SymbolType::IntType => true, | |
_ => false | |
}).count(); | |
let long_count = items.iter().filter(|x| match x { | |
SymbolType::LongType => true, | |
_ => false | |
}).count(); | |
let is_unsigned = if unsigned_count == 1 { | |
true | |
} else if (signed_count == 0 || signed_count == 1) && unsigned_count == 0 { | |
false | |
} else { | |
return None | |
}; | |
if long_count == 2 && int_count <= 1 && short_count == 0 { | |
return Some(if is_unsigned { | |
FundamentalType::UnsignedLongLongInt | |
} else { | |
FundamentalType::SignedLongLongInt | |
}) | |
} | |
if long_count == 1 && int_count <= 1 && short_count == 0 { | |
return Some(if is_unsigned { | |
FundamentalType::UnsignedLongInt | |
} else { | |
FundamentalType::SignedLongInt | |
}) | |
} | |
if short_count == 1 && int_count <= 1 && long_count == 0{ | |
return Some(if is_unsigned { | |
FundamentalType::UnsignedShortInt | |
} else { | |
FundamentalType::SignedShortInt | |
}) | |
} | |
if int_count <= 1 { | |
return Some((if is_unsigned { | |
FundamentalType::UnsignedInt | |
} else { | |
FundamentalType::SignedInt | |
})) | |
} | |
return None | |
}, | |
)))(i) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment