generator: Upgrade nom to 0.7 where parser macros have been removed (#610)

This commit is contained in:
Michael Pollind 2022-05-10 13:58:47 -07:00 committed by GitHub
parent 94e750d66e
commit c4f1c053ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 75 deletions

View file

@ -8,7 +8,7 @@ edition = "2018"
bindgen = "0.58" bindgen = "0.58"
heck = "0.3" heck = "0.3"
itertools = "0.10" itertools = "0.10"
nom = "6.0" nom = "7.1"
once_cell = "1.7" once_cell = "1.7"
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"

View file

@ -3,19 +3,26 @@
use heck::{CamelCase, ShoutySnakeCase, SnakeCase}; use heck::{CamelCase, ShoutySnakeCase, SnakeCase};
use itertools::Itertools; use itertools::Itertools;
use nom::sequence::pair;
use nom::{ use nom::{
alt, char, branch::alt,
character::complete::{digit1, hex_digit1, multispace1}, bytes::streaming::tag,
complete, delimited, do_parse, many1, map, named, none_of, one_of, opt, pair, preceded, tag, character::complete::{char, digit1, hex_digit1, multispace1, none_of, one_of},
terminated, value, combinator::{complete, map, opt, value},
error::{ParseError, VerboseError},
multi::many1,
sequence::{delimited, preceded, terminated},
IResult, Parser,
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use proc_macro2::{Delimiter, Group, Literal, Span, TokenStream, TokenTree}; use proc_macro2::{Delimiter, Group, Literal, Span, TokenStream, TokenTree};
use quote::*; use quote::*;
use regex::Regex; use regex::Regex;
use std::collections::{BTreeMap, HashMap, HashSet}; use std::{
use std::fmt::Display; collections::{BTreeMap, HashMap, HashSet},
use std::path::Path; fmt::Display,
path::Path,
};
use syn::Ident; use syn::Ident;
macro_rules! get_variant { macro_rules! get_variant {
@ -63,83 +70,90 @@ impl quote::ToTokens for CType {
} }
} }
named!(ctype<&str, CType>, fn parse_ctype<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, CType, E> {
alt!( (alt((
value!(CType::U64, complete!(tag!("ULL"))) | value(CType::U64, complete(tag("ULL"))),
value!(CType::U32, complete!(tag!("U"))) value(CType::U32, complete(tag("U"))),
) )))(i)
); }
named!(cexpr<&str, (CType, String)>, fn parse_cexpr<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (CType, String), E> {
alt!( (alt((
map!(cfloat, |f| (CType::Float, format!("{:.2}", f))) | map(parse_cfloat, |f| (CType::Float, format!("{:.2}", f))),
inverse_number | parse_inverse_number,
decimal_number | parse_decimal_number,
hexadecimal_number parse_hexadecimal_number,
) )))(i)
); }
named!(decimal_number<&str, (CType, String)>, fn parse_cfloat<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, f32, E> {
do_parse!( (terminated(nom::number::complete::float, one_of("fF")))(i)
num: digit1 >> }
typ: ctype >>
((typ, num.to_string()))
)
);
named!(hexadecimal_number<&str, (CType, String)>, fn parse_inverse_number<'a, E: ParseError<&'a str>>(
preceded!( i: &'a str,
alt!(tag!("0x") | tag!("0X")), ) -> IResult<&'a str, (CType, String), E> {
map!( (map(
pair!(hex_digit1, ctype), delimited(
|(num, typ)| (typ, format!("0x{}{}", num.to_ascii_lowercase(), typ.to_string()) char('('),
) pair(
) preceded(char('~'), parse_decimal_number),
) opt(preceded(char('-'), digit1)),
);
named!(inverse_number<&str, (CType, String)>,
map!(
delimited!(
tag!("("),
pair!(
preceded!(tag!("~"), decimal_number),
opt!(preceded!(tag!("-"), digit1))
), ),
tag!(")") char(')'),
), ),
|((ctyp, num), minus_num)| { |((ctyp, num), minus_num)| {
let expr = if let Some(minus) = minus_num { let expr = if let Some(minus) = minus_num {
format!("!{}-{}", num, minus) format!("!{}-{}", num, minus)
} } else {
else{
format!("!{}", num) format!("!{}", num)
}; };
(ctyp, expr) (ctyp, expr)
} },
) ))(i)
); }
named!(cfloat<&str, f32>,
terminated!(nom::number::complete::float, one_of!("fF"))
);
// Like a C string, but does not support quote escaping and expects at least one character. // Like a C string, but does not support quote escaping and expects at least one character.
// If needed, use https://github.com/Geal/nom/blob/8e09f0c3029d32421b5b69fb798cef6855d0c8df/tests/json.rs#L61-L81 // If needed, use https://github.com/Geal/nom/blob/8e09f0c3029d32421b5b69fb798cef6855d0c8df/tests/json.rs#L61-L81
named!(c_include_string<&str, String>, fn parse_c_include_string<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, String, E> {
delimited!( (delimited(
char!('"'), char('"'),
map!( map(many1(none_of("\"")), |c| {
many1!(none_of!("\"")), c.iter().map(char::to_string).join("")
|chars| chars.iter().map(char::to_string).join("") }),
), char('"'),
char!('"') ))(i)
) }
);
named!(c_include<&str, String>, fn parse_c_include<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, String, E> {
preceded!(tag!("#include"), preceded!(multispace1, c_include_string)) (preceded(
); tag("#include"),
preceded(multispace1, parse_c_include_string),
))(i)
}
fn parse_decimal_number<'a, E: ParseError<&'a str>>(
i: &'a str,
) -> IResult<&'a str, (CType, String), E> {
(map(
pair(digit1.map(str::to_string), parse_ctype),
|(dig, ctype)| (ctype, dig),
))(i)
}
fn parse_hexadecimal_number<'a, E: ParseError<&'a str>>(
i: &'a str,
) -> IResult<&'a str, (CType, String), E> {
(preceded(
alt((tag("0x"), tag("0X"))),
map(pair(hex_digit1, parse_ctype), |(num, typ)| {
(
typ,
format!("0x{}{}", num.to_ascii_lowercase(), typ.to_string()),
)
}),
))(i)
}
fn khronos_link<S: Display + ?Sized>(name: &S) -> Literal { fn khronos_link<S: Display + ?Sized>(name: &S) -> Literal {
Literal::string(&format!( Literal::string(&format!(
@ -265,7 +279,8 @@ impl quote::ToTokens for Constant {
} }
Constant::Text(ref text) => text.to_tokens(tokens), Constant::Text(ref text) => text.to_tokens(tokens),
Constant::CExpr(ref expr) => { Constant::CExpr(ref expr) => {
let (_, (_, rexpr)) = cexpr(expr).expect("Unable to parse cexpr"); let (_, (_, rexpr)) =
parse_cexpr::<VerboseError<&str>>(expr).expect("Unable to parse cexpr");
tokens.extend(rexpr.parse::<TokenStream>()); tokens.extend(rexpr.parse::<TokenStream>());
} }
Constant::BitPos(pos) => { Constant::BitPos(pos) => {
@ -318,7 +333,8 @@ impl Constant {
match self { match self {
Constant::Number(_) | Constant::Hex(_) => CType::USize, Constant::Number(_) | Constant::Hex(_) => CType::USize,
Constant::CExpr(expr) => { Constant::CExpr(expr) => {
let (_, (ty, _)) = cexpr(expr).expect("Unable to parse cexpr"); let (_, (ty, _)) =
parse_cexpr::<VerboseError<&str>>(expr).expect("Unable to parse cexpr");
ty ty
} }
_ => unimplemented!(), _ => unimplemented!(),
@ -549,12 +565,12 @@ fn name_to_tokens(type_name: &str) -> Ident {
/// Parses and rewrites a C literal into Rust /// Parses and rewrites a C literal into Rust
/// ///
/// If no special pattern is recognized the original literal is returned. /// If no special pattern is recognized the original literal is returned.
/// Any new conversions need to be added to the [`cexpr()`] [`nom`] parser. /// Any new conversions need to be added to the [`parse_cexpr()`] [`nom`] parser.
/// ///
/// Examples: /// Examples:
/// - `0x3FFU` -> `0x3ffu32` /// - `0x3FFU` -> `0x3ffu32`
fn convert_c_literal(lit: Literal) -> Literal { fn convert_c_literal(lit: Literal) -> Literal {
if let Ok((_, (_, rexpr))) = cexpr(&lit.to_string()) { if let Ok((_, (_, rexpr))) = parse_cexpr::<VerboseError<&str>>(&lit.to_string()) {
// lit::SynInt uses the same `.parse` method to create hexadecimal // lit::SynInt uses the same `.parse` method to create hexadecimal
// literals because there is no `Literal` constructor for it. // literals because there is no `Literal` constructor for it.
let mut stream = rexpr.parse::<TokenStream>().unwrap().into_iter(); let mut stream = rexpr.parse::<TokenStream>().unwrap().into_iter();
@ -2291,7 +2307,7 @@ pub fn extract_native_types(registry: &vk_parse::Registry) -> (Vec<(String, Stri
name name
); );
let (rem, path) = c_include(&code.code) let (rem, path) = parse_c_include::<VerboseError<&str>>(&code.code)
.expect("Failed to parse `#include` from `category=\"include\"` directive"); .expect("Failed to parse `#include` from `category=\"include\"` directive");
assert!(rem.is_empty()); assert!(rem.is_empty());
header_includes.push((name, path)); header_includes.push((name, path));