diff --git a/src/parser/declarations/assertion_declarations.rs b/src/parser/declarations/assertion_declarations.rs index 3a98563..0b0d16f 100644 --- a/src/parser/declarations/assertion_declarations.rs +++ b/src/parser/declarations/assertion_declarations.rs @@ -172,7 +172,7 @@ pub struct PropertyPortItem<'a> { pub nodes: ( Vec>, Option<(Local<'a>, Option>)>, - PropertyFormalType<'a>, + Option>, FormalPortIdentifier<'a>, Vec>, Option<(Symbol<'a>, PropertyActualArg<'a>)>, @@ -472,7 +472,7 @@ pub struct SequencePortItem<'a> { pub nodes: ( Vec>, Option<(Local<'a>, Option>)>, - SequenceFormalType<'a>, + Option>, FormalPortIdentifier<'a>, Vec>, Option<(Symbol<'a>, SequenceActualArg<'a>)>, @@ -975,11 +975,11 @@ pub fn property_port_list(s: Span) -> IResult { Ok((s, PropertyPortList { nodes: (a,) })) } -#[parser] +#[parser(Ambiguous)] pub fn property_port_item(s: Span) -> IResult { let (s, a) = many0(attribute_instance)(s)?; let (s, b) = opt(pair(local, opt(property_lvar_port_direction)))(s)?; - let (s, c) = property_formal_type(s)?; + let (s, c) = ambiguous_opt(property_formal_type)(s)?; let (s, d) = formal_port_identifier(s)?; let (s, e) = many0(variable_dimension)(s)?; let (s, f) = opt(pair(symbol("="), property_actual_arg))(s)?; @@ -1448,11 +1448,11 @@ pub fn sequence_port_list(s: Span) -> IResult { Ok((s, SequencePortList { nodes: (a,) })) } -#[parser] +#[parser(Ambiguous)] pub fn sequence_port_item(s: Span) -> IResult { let (s, a) = many0(attribute_instance)(s)?; let (s, b) = opt(pair(local, opt(sequence_lvar_port_direction)))(s)?; - let (s, c) = sequence_formal_type(s)?; + let (s, c) = ambiguous_opt(sequence_formal_type)(s)?; let (s, d) = formal_port_identifier(s)?; let (s, e) = many0(variable_dimension)(s)?; let (s, f) = opt(pair(symbol("="), sequence_actual_arg))(s)?; diff --git a/src/parser/declarations/covergroup_declarations.rs b/src/parser/declarations/covergroup_declarations.rs index 0736eb7..00df2f8 100644 --- a/src/parser/declarations/covergroup_declarations.rs +++ b/src/parser/declarations/covergroup_declarations.rs @@ -715,10 +715,10 @@ pub fn hierarchical_identifier_or_class_scope( ))(s) } -#[parser] +#[parser(Ambiguous)] pub fn cover_point(s: Span) -> IResult { let (s, a) = opt(triple( - opt(data_type_or_implicit), + ambiguous_opt(data_type_or_implicit), cover_point_identifier, symbol(":"), ))(s)?; diff --git a/src/parser/declarations/function_declarations.rs b/src/parser/declarations/function_declarations.rs index 8ce24dd..1be3968 100644 --- a/src/parser/declarations/function_declarations.rs +++ b/src/parser/declarations/function_declarations.rs @@ -32,7 +32,7 @@ pub enum FunctionBodyDeclaration<'a> { #[derive(Debug, Node)] pub struct FunctionBodyDeclarationWithoutPort<'a> { pub nodes: ( - FunctionDataTypeOrImplicit<'a>, + Option>, Option>, FunctionIdentifier<'a>, Symbol<'a>, @@ -46,7 +46,7 @@ pub struct FunctionBodyDeclarationWithoutPort<'a> { #[derive(Debug, Node)] pub struct FunctionBodyDeclarationWithPort<'a> { pub nodes: ( - FunctionDataTypeOrImplicit<'a>, + Option>, Option>, FunctionIdentifier<'a>, Paren<'a, Option>>, @@ -187,9 +187,9 @@ pub fn function_body_declaration(s: Span) -> IResult IResult { - let (s, a) = function_data_type_or_implicit(s)?; + let (s, a) = ambiguous_opt(function_data_type_or_implicit)(s)?; let (s, b) = opt(interface_identifier_or_class_scope)(s)?; let (s, c) = function_identifier(s)?; let (s, d) = symbol(";")(s)?; @@ -205,9 +205,9 @@ pub fn function_body_declaration_without_port(s: Span) -> IResult IResult { - let (s, a) = function_data_type_or_implicit(s)?; + let (s, a) = ambiguous_opt(function_data_type_or_implicit)(s)?; let (s, b) = opt(interface_identifier_or_class_scope)(s)?; let (s, c) = function_identifier(s)?; let (s, d) = paren(opt(tf_port_list))(s)?; diff --git a/src/parser/declarations/let_declarations.rs b/src/parser/declarations/let_declarations.rs index f16703e..b36f3bb 100644 --- a/src/parser/declarations/let_declarations.rs +++ b/src/parser/declarations/let_declarations.rs @@ -34,7 +34,7 @@ pub struct LetPortList<'a> { pub struct LetPortItem<'a> { pub nodes: ( Vec>, - LetFormalType<'a>, + Option>, FormalPortIdentifier<'a>, Vec>, Option<(Symbol<'a>, Expression<'a>)>, @@ -124,10 +124,10 @@ pub fn let_port_list(s: Span) -> IResult { Ok((s, LetPortList { nodes: (a,) })) } -#[parser] +#[parser(Ambiguous)] pub fn let_port_item(s: Span) -> IResult { let (s, a) = many0(attribute_instance)(s)?; - let (s, b) = let_formal_type(s)?; + let (s, b) = ambiguous_opt(let_formal_type)(s)?; let (s, c) = formal_port_identifier(s)?; let (s, d) = many0(variable_dimension)(s)?; let (s, e) = opt(pair(symbol("="), expression))(s)?; diff --git a/src/parser/declarations/module_parameter_declarations.rs b/src/parser/declarations/module_parameter_declarations.rs index a48d9ab..79464cc 100644 --- a/src/parser/declarations/module_parameter_declarations.rs +++ b/src/parser/declarations/module_parameter_declarations.rs @@ -16,7 +16,7 @@ pub enum LocalParameterDeclaration<'a> { pub struct LocalParameterDeclarationParam<'a> { pub nodes: ( Symbol<'a>, - DataTypeOrImplicit<'a>, + Option>, ListOfParamAssignments<'a>, ), } @@ -36,7 +36,7 @@ pub enum ParameterDeclaration<'a> { pub struct ParameterDeclarationParam<'a> { pub nodes: ( Symbol<'a>, - DataTypeOrImplicit<'a>, + Option>, ListOfParamAssignments<'a>, ), } @@ -66,10 +66,10 @@ pub fn local_parameter_declaration(s: Span) -> IResult IResult { let (s, a) = symbol("localparam")(s)?; - let (s, b) = data_type_or_implicit(s)?; + let (s, b) = ambiguous_opt(data_type_or_implicit)(s)?; let (s, c) = list_of_param_assignments(s)?; Ok(( s, @@ -93,10 +93,10 @@ pub fn parameter_declaration(s: Span) -> IResult { alt((parameter_declaration_param, parameter_declaration_type))(s) } -#[parser] +#[parser(Ambiguous)] pub fn parameter_declaration_param(s: Span) -> IResult { let (s, a) = symbol("parameter")(s)?; - let (s, b) = data_type_or_implicit(s)?; + let (s, b) = ambiguous_opt(data_type_or_implicit)(s)?; let (s, c) = list_of_param_assignments(s)?; Ok(( s, diff --git a/src/parser/declarations/net_and_variable_types.rs b/src/parser/declarations/net_and_variable_types.rs index 09f26df..53cf946 100644 --- a/src/parser/declarations/net_and_variable_types.rs +++ b/src/parser/declarations/net_and_variable_types.rs @@ -533,12 +533,12 @@ pub fn net_type(s: Span) -> IResult { alt(( map(symbol("supply0"), |x| NetType::Supply0(x)), map(symbol("supply1"), |x| NetType::Supply1(x)), - map(symbol("tri"), |x| NetType::Tri(x)), map(symbol("triand"), |x| NetType::Triand(x)), map(symbol("trior"), |x| NetType::Trior(x)), map(symbol("trireg"), |x| NetType::Trireg(x)), map(symbol("tri0"), |x| NetType::Tri0(x)), map(symbol("tri1"), |x| NetType::Tri1(x)), + map(symbol("tri"), |x| NetType::Tri(x)), map(symbol("uwire"), |x| NetType::Uwire(x)), map(symbol("wire"), |x| NetType::Wire(x)), map(symbol("wand"), |x| NetType::Wand(x)), diff --git a/src/parser/declarations/port_declarations.rs b/src/parser/declarations/port_declarations.rs index 525e0bb..c842863 100644 --- a/src/parser/declarations/port_declarations.rs +++ b/src/parser/declarations/port_declarations.rs @@ -9,7 +9,11 @@ use nom::IResult; #[derive(Debug, Node)] pub struct InoutDeclaration<'a> { - pub nodes: (Symbol<'a>, NetPortType<'a>, ListOfPortIdentifiers<'a>), + pub nodes: ( + Symbol<'a>, + Option>, + ListOfPortIdentifiers<'a>, + ), } #[derive(Debug, Node)] @@ -20,7 +24,11 @@ pub enum InputDeclaration<'a> { #[derive(Debug, Node)] pub struct InputDeclarationNet<'a> { - pub nodes: (Symbol<'a>, NetPortType<'a>, ListOfPortIdentifiers<'a>), + pub nodes: ( + Symbol<'a>, + Option>, + ListOfPortIdentifiers<'a>, + ), } #[derive(Debug, Node)] @@ -40,7 +48,11 @@ pub enum OutputDeclaration<'a> { #[derive(Debug, Node)] pub struct OutputDeclarationNet<'a> { - pub nodes: (Symbol<'a>, NetPortType<'a>, ListOfPortIdentifiers<'a>), + pub nodes: ( + Symbol<'a>, + Option>, + ListOfPortIdentifiers<'a>, + ), } #[derive(Debug, Node)] @@ -72,10 +84,10 @@ pub struct RefDeclaration<'a> { // ----------------------------------------------------------------------------- -#[parser] +#[parser(Ambiguous)] pub fn inout_declaration(s: Span) -> IResult { let (s, a) = symbol("inout")(s)?; - let (s, b) = net_port_type(s)?; + let (s, b) = ambiguous_opt(net_port_type)(s)?; let (s, c) = list_of_port_identifiers(s)?; Ok((s, InoutDeclaration { nodes: (a, b, c) })) } @@ -85,10 +97,10 @@ pub fn input_declaration(s: Span) -> IResult { alt((input_declaration_net, input_declaration_variable))(s) } -#[parser] +#[parser(Ambiguous)] pub fn input_declaration_net(s: Span) -> IResult { let (s, a) = symbol("input")(s)?; - let (s, b) = net_port_type(s)?; + let (s, b) = ambiguous_opt(net_port_type)(s)?; let (s, c) = list_of_port_identifiers(s)?; Ok(( s, @@ -112,10 +124,10 @@ pub fn output_declaration(s: Span) -> IResult { alt((output_declaration_net, output_declaration_variable))(s) } -#[parser] +#[parser(Ambiguous)] pub fn output_declaration_net(s: Span) -> IResult { let (s, a) = symbol("output")(s)?; - let (s, b) = net_port_type(s)?; + let (s, b) = ambiguous_opt(net_port_type)(s)?; let (s, c) = list_of_port_identifiers(s)?; Ok(( s, @@ -149,3 +161,18 @@ pub fn ref_declaration(s: Span) -> IResult { let (s, c) = list_of_variable_identifiers(s)?; Ok((s, RefDeclaration { nodes: (a, b, c) })) } + +// ----------------------------------------------------------------------------- + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_inout_declaration() { + parser_test!(inout_declaration, "inout a", Ok((_, _))); + parser_test!(inout_declaration, "inout [7:0] a", Ok((_, _))); + parser_test!(inout_declaration, "inout signed [7:0] a", Ok((_, _))); + parser_test!(inout_declaration, "inout var a", Ok((_, _))); + } +} diff --git a/src/parser/declarations/task_declarations.rs b/src/parser/declarations/task_declarations.rs index 7841cbe..ff774f5 100644 --- a/src/parser/declarations/task_declarations.rs +++ b/src/parser/declarations/task_declarations.rs @@ -63,7 +63,7 @@ pub struct TfPortItem<'a> { Vec>, Option>, Option>, - DataTypeOrImplicit<'a>, + Option>, Option<( PortIdentifier<'a>, Vec>, @@ -84,7 +84,7 @@ pub struct TfPortDeclaration<'a> { Vec>, TfPortDirection<'a>, Option>, - DataTypeOrImplicit<'a>, + Option>, ListOfTfVariableIdentifiers<'a>, Symbol<'a>, ), @@ -170,12 +170,12 @@ pub fn tf_port_list(s: Span) -> IResult { Ok((s, TfPortList { nodes: (a,) })) } -#[parser] +#[parser(Ambiguous)] pub fn tf_port_item(s: Span) -> IResult { let (s, a) = many0(attribute_instance)(s)?; let (s, b) = opt(tf_port_direction)(s)?; let (s, c) = opt(var)(s)?; - let (s, d) = data_type_or_implicit(s)?; + let (s, d) = ambiguous_opt(data_type_or_implicit)(s)?; let (s, e) = opt(triple( port_identifier, many0(variable_dimension), @@ -199,12 +199,12 @@ pub fn tf_port_direction(s: Span) -> IResult { ))(s) } -#[parser] +#[parser(Ambiguous)] pub fn tf_port_declaration(s: Span) -> IResult { let (s, a) = many0(attribute_instance)(s)?; let (s, b) = tf_port_direction(s)?; let (s, c) = opt(var)(s)?; - let (s, d) = data_type_or_implicit(s)?; + let (s, d) = ambiguous_opt(data_type_or_implicit)(s)?; let (s, e) = list_of_tf_variable_identifiers(s)?; let (s, f) = symbol(";")(s)?; Ok(( diff --git a/src/parser/declarations/type_declarations.rs b/src/parser/declarations/type_declarations.rs index 104b069..4607585 100644 --- a/src/parser/declarations/type_declarations.rs +++ b/src/parser/declarations/type_declarations.rs @@ -22,7 +22,7 @@ pub struct DataDeclarationVariable<'a> { Option>, Option>, Option>, - DataTypeOrImplicit<'a>, + Option>, ListOfVariableDeclAssignments<'a>, Symbol<'a>, ), @@ -96,7 +96,7 @@ pub struct NetDeclarationNetType<'a> { NetType<'a>, Option>, Option>, - DataTypeOrImplicit<'a>, + Option>, Option>, ListOfNetDeclAssignments<'a>, Symbol<'a>, @@ -242,12 +242,12 @@ pub fn data_declaration(s: Span) -> IResult { ))(s) } -#[parser] +#[parser(Ambiguous)] pub fn data_declaration_variable(s: Span) -> IResult { let (s, a) = opt(r#const)(s)?; let (s, b) = opt(var)(s)?; let (s, c) = opt(lifetime)(s)?; - let (s, d) = data_type_or_implicit(s)?; + let (s, d) = ambiguous_opt(data_type_or_implicit)(s)?; let (s, e) = list_of_variable_decl_assignments(s)?; let (s, f) = symbol(";")(s)?; Ok(( @@ -340,18 +340,18 @@ pub fn genvar_declaration(s: Span) -> IResult { #[parser] pub fn net_declaration(s: Span) -> IResult { alt(( + net_declaration_interconnect, net_declaration_net_type, net_declaration_net_type_identifier, - net_declaration_interconnect, ))(s) } -#[parser] +#[parser(Ambiguous)] pub fn net_declaration_net_type(s: Span) -> IResult { let (s, a) = net_type(s)?; let (s, b) = opt(strength)(s)?; let (s, c) = opt(vector_scalar)(s)?; - let (s, d) = data_type_or_implicit(s)?; + let (s, d) = ambiguous_opt(data_type_or_implicit)(s)?; let (s, e) = opt(delay3)(s)?; let (s, f) = list_of_net_decl_assignments(s)?; let (s, g) = symbol(";")(s)?; @@ -531,3 +531,75 @@ pub fn lifetime(s: Span) -> IResult { map(symbol("automatic"), |x| Lifetime::Automatic(x)), ))(s) } + +// ----------------------------------------------------------------------------- + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_net_type_declaration() { + parser_test!( + net_type_declaration, + "nettype T wT;", + Ok((_, NetTypeDeclaration::DataType(_))) + ); + parser_test!( + net_type_declaration, + "nettype T wTsum with Tsum;", + Ok((_, NetTypeDeclaration::DataType(_))) + ); + parser_test!( + net_type_declaration, + "nettype MyBaseT::T narrowTsum with MyBaseT::Tsum;", + Ok((_, NetTypeDeclaration::DataType(_))) + ); + } + + #[test] + fn test_net_declaration() { + parser_test!( + net_declaration, + "trireg (large) logic #(0,0,0) cap1;", + Ok((_, NetDeclaration::NetType(_))) + ); + parser_test!( + net_declaration, + "wire addressT w1;", + Ok((_, NetDeclaration::NetType(_))) + ); + parser_test!( + net_declaration, + "wire struct packed { logic ecc; logic [7:0] data; } memsig;", + Ok((_, NetDeclaration::NetType(_))) + ); + parser_test!( + net_declaration, + "wire w;", + Ok((_, NetDeclaration::NetType(_))) + ); + parser_test!( + net_declaration, + "wire [15:0] w;", + Ok((_, NetDeclaration::NetType(_))) + ); + parser_test!( + net_declaration, + "interconnect w1;", + Ok((_, NetDeclaration::Interconnect(_))) + ); + parser_test!( + net_declaration, + "interconnect [3:0] w2;", + Ok((_, NetDeclaration::Interconnect(_))) + ); + parser_test!( + net_declaration, + "interconnect [3:0] w3 [1:0];", + Ok((_, NetDeclaration::Interconnect(_))) + ); + parser_test!(net_declaration, "interconnect logic [3:0] w4;", Err(_)); + parser_test!(net_declaration, "interconnect #(1,2,3) w5;", Err(_)); + } +} diff --git a/src/parser/expressions/expression_leftside_values.rs b/src/parser/expressions/expression_leftside_values.rs index 5c9859a..9d86e0a 100644 --- a/src/parser/expressions/expression_leftside_values.rs +++ b/src/parser/expressions/expression_leftside_values.rs @@ -156,41 +156,6 @@ pub fn nonrange_variable_lvalue(s: Span) -> IResult { - Expr(Box>), - Term(ExprTerm<'a>), -} - -#[derive(Debug, Node)] -pub struct ExprExpr<'a> { - pub nodes: (Expr<'a>, Symbol<'a>, Expr<'a>), -} - -#[derive(Debug, Node)] -pub struct ExprTerm<'a> { - pub nodes: (Identifier<'a>,), -} - -#[parser] -pub fn expr(s: Span) -> IResult { - alt((expr_expr, expr_term))(s) -} - -#[parser(MaybeRecursive)] -pub fn expr_expr(s: Span) -> IResult { - let (s, a) = expr(s)?; - let (s, b) = symbol("+")(s)?; - let (s, c) = expr(s)?; - Ok((s, Expr::Expr(Box::new(ExprExpr { nodes: (a, b, c) })))) -} - -#[parser] -pub fn expr_term(s: Span) -> IResult { - let (s, a) = identifier(s)?; - Ok((s, Expr::Term(ExprTerm { nodes: (a,) }))) -} - // ----------------------------------------------------------------------------- #[cfg(test)] @@ -219,10 +184,4 @@ mod tests { //parser_test!(nonrange_variable_lvalue, "A[][2][3]", Ok((_, _))); //parser_test!(nonrange_variable_lvalue, "A[][]", Ok((_, _))); } - - #[test] - fn test_expr() { - parser_test!(expr, "A", Ok((_, _))); - parser_test!(expr, "A+B", Ok((_, _))); - } } diff --git a/src/parser/utils.rs b/src/parser/utils.rs index dd9bc2e..e959ee2 100644 --- a/src/parser/utils.rs +++ b/src/parser/utils.rs @@ -188,6 +188,13 @@ where } } +pub fn none<'a, O, F>(_f: F) -> impl Fn(Span<'a>) -> IResult, Option> +where + F: Fn(Span<'a>) -> IResult, O>, +{ + move |s: Span<'a>| Ok((s, None)) +} + // ----------------------------------------------------------------------------- #[parser] diff --git a/sv-parser-derive/Cargo.toml b/sv-parser-derive/Cargo.toml index f0d1460..b4d8b85 100644 --- a/sv-parser-derive/Cargo.toml +++ b/sv-parser-derive/Cargo.toml @@ -10,5 +10,5 @@ edition = "2018" proc-macro = true [dependencies] -syn = { version = "0.15.18", features = ["full", "fold", "parsing"] } +syn = { version = "0.15.18", features = ["full", "fold", "parsing", "extra-traits"] } quote = "0.6.9" diff --git a/sv-parser-derive/src/lib.rs b/sv-parser-derive/src/lib.rs index db25bdc..9bd42cc 100644 --- a/sv-parser-derive/src/lib.rs +++ b/sv-parser-derive/src/lib.rs @@ -4,6 +4,7 @@ extern crate proc_macro; use crate::proc_macro::TokenStream; use quote::quote; +use std::str::FromStr; use syn::Data::{Enum, Struct}; use syn::{ self, parse_macro_input, AttributeArgs, DeriveInput, Expr, ItemFn, Meta, NestedMeta, Stmt, @@ -121,20 +122,75 @@ pub fn parser(attr: TokenStream, item: TokenStream) -> TokenStream { } fn impl_parser(attr: &AttributeArgs, item: &ItemFn) -> TokenStream { - let (maybe_recursive,) = impl_parser_attribute(attr); + let (maybe_recursive, ambiguous) = impl_parser_attribute(attr); + + let trace = impl_parser_trace(&item); + let trace = parse_macro_input!(trace as Stmt); + + let check_recursive_flag = impl_parser_check_recursive_flag(&item); + let check_recursive_flag = parse_macro_input!(check_recursive_flag as Stmt); + + let set_recursive_flag = impl_parser_set_recursive_flag(&item); + let set_recursive_flag = parse_macro_input!(set_recursive_flag as Stmt); + + let body = if ambiguous { + impl_parser_body_ambiguous(&item) + } else { + impl_parser_body(&item) + }; + let body = parse_macro_input!(body as Stmt); + + let clear_recursive_flags = impl_parser_clear_recursive_flags(&item); + let clear_recursive_flags = parse_macro_input!(clear_recursive_flags as Expr); + let clear_recursive_flags = Stmt::Expr(clear_recursive_flags); - let ident = &item.ident; let mut item = item.clone(); - let tracer = quote! { + item.block.stmts.clear(); + item.block.stmts.push(trace); + if maybe_recursive { + item.block.stmts.push(check_recursive_flag); + item.block.stmts.push(set_recursive_flag); + } + item.block.stmts.push(body); + item.block.stmts.push(clear_recursive_flags); + + let gen = quote! { + #item + }; + gen.into() +} + +fn impl_parser_attribute(attr: &AttributeArgs) -> (bool, bool) { + let mut maybe_recursive = false; + let mut ambiguous = false; + + for a in attr { + match a { + NestedMeta::Meta(Meta::Word(x)) if x == "MaybeRecursive" => maybe_recursive = true, + NestedMeta::Meta(Meta::Word(x)) if x == "Ambiguous" => ambiguous = true, + _ => panic!(), + } + } + + (maybe_recursive, ambiguous) +} + +fn impl_parser_trace(item: &ItemFn) -> TokenStream { + let ident = &item.ident; + + let gen = quote! { if cfg!(feature = "trace") { println!("{:<64} : {:<4},{:>032x} : {}", stringify!(#ident), s.offset, s.extra[0], s.fragment); } }; - let tracer: TokenStream = tracer.into(); - let tracer = parse_macro_input!(tracer as Stmt); + gen.into() +} - let checker = quote! { +fn impl_parser_check_recursive_flag(item: &ItemFn) -> TokenStream { + let ident = &item.ident; + + let gen = quote! { if thread_context::PARSER_INDEX.with(|p| { if let Some(i) = p.borrow_mut().get(stringify!(#ident)) { return check_recursive_flag(s, i); @@ -148,10 +204,13 @@ fn impl_parser(attr: &AttributeArgs, item: &ItemFn) -> TokenStream { return Err(nom::Err::Error(nom::error::make_error(s, nom::error::ErrorKind::Fix))); } }; - let checker: TokenStream = checker.into(); - let checker = parse_macro_input!(checker as Stmt); + gen.into() +} - let before = quote! { +fn impl_parser_set_recursive_flag(item: &ItemFn) -> TokenStream { + let ident = &item.ident; + + let gen = quote! { let s = thread_context::PARSER_INDEX.with(|p| { if let Some(i) = p.borrow_mut().get(stringify!(#ident)) { set_recursive_flag(s, i, true) @@ -163,53 +222,80 @@ fn impl_parser(attr: &AttributeArgs, item: &ItemFn) -> TokenStream { } }); }; - let before: TokenStream = before.into(); - let before = parse_macro_input!(before as Stmt); + gen.into() +} - let mut body = quote! {}; +fn impl_parser_body(item: &ItemFn) -> TokenStream { + let mut gen = quote! {}; for s in &item.block.stmts { - body = quote! { - #body + gen = quote! { + #gen #s }; } - let body = quote! { - let (s, ret) = { #body }?; - }; - let body: TokenStream = body.into(); - let body = parse_macro_input!(body as Stmt); - - let after = quote! { - Ok((clear_recursive_flags(s), ret)) - }; - let after: TokenStream = after.into(); - let after = parse_macro_input!(after as Expr); - let after = Stmt::Expr(after); - - item.block.stmts.clear(); - item.block.stmts.push(tracer); - if maybe_recursive { - item.block.stmts.push(checker); - item.block.stmts.push(before); - } - item.block.stmts.push(body); - item.block.stmts.push(after); - let gen = quote! { - #item + let (s, ret) = { #gen }?; }; gen.into() } -fn impl_parser_attribute(attr: &AttributeArgs) -> (bool,) { - let mut maybe_recursive = false; +fn impl_parser_body_ambiguous(item: &ItemFn) -> TokenStream { + let mut token = quote! {}; + for s in &item.block.stmts { + token = quote! { + #token + #s + }; + } + let mut token = token.to_string(); - for a in attr { - match a { - NestedMeta::Meta(Meta::Word(x)) if x == "MaybeRecursive" => maybe_recursive = true, - _ => panic!(), + let ambiguous_cnt: Vec<&str> = token.matches("ambiguous").collect(); + let ambiguous_cnt = ambiguous_cnt.len(); + + let mut replace_parsers = Vec::new(); + for i in 0..ambiguous_cnt { + let pos = token.find("ambiguous").unwrap(); + let (head, rest) = token.split_at(pos); + if rest.starts_with("ambiguous_opt") { + let rest = rest.replacen("ambiguous_opt", &format!("amb_temporary{}", i), 1); + token = format!("{}{}", head, rest); + replace_parsers.push(("opt", "none")); } } - (maybe_recursive,) + let mut gen = quote! {}; + for i in 0..2_u32.pow(ambiguous_cnt as u32) { + let mut token = token.clone(); + for j in 0..ambiguous_cnt { + let (p0, p1) = replace_parsers[j]; + let repl = if ((i >> j) & 1) == 0 { p0 } else { p1 }; + token = token.replace(&format!("amb_temporary{}", j), repl); + } + let token = format!("{{ {} }}", token); + let token = TokenStream::from_str(&token).unwrap(); + let token = parse_macro_input!(token as Stmt); + gen = quote! { + #gen + |s| #token, + }; + } + + let gen = quote! { + alt(( + #gen + ))(s) + }; + + let gen = quote! { + let (s, ret) = { #gen }?; + }; + + gen.into() +} + +fn impl_parser_clear_recursive_flags(_item: &ItemFn) -> TokenStream { + let gen = quote! { + Ok((clear_recursive_flags(s), ret)) + }; + gen.into() }