Skip to content

Instantly share code, notes, and snippets.

@pollend
Created March 17, 2022 04:18
Show Gist options
  • Save pollend/dda6eb003e40302cbd43c6d03c7f3faf to your computer and use it in GitHub Desktop.
Save pollend/dda6eb003e40302cbd43c6d03c7f3faf to your computer and use it in GitHub Desktop.
/// 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