Add ambiguous
This commit is contained in:
parent
a6c0a54f3c
commit
ecb89f691f
@ -172,7 +172,7 @@ pub struct PropertyPortItem<'a> {
|
||||
pub nodes: (
|
||||
Vec<AttributeInstance<'a>>,
|
||||
Option<(Local<'a>, Option<PropertyLvarPortDirection<'a>>)>,
|
||||
PropertyFormalType<'a>,
|
||||
Option<PropertyFormalType<'a>>,
|
||||
FormalPortIdentifier<'a>,
|
||||
Vec<VariableDimension<'a>>,
|
||||
Option<(Symbol<'a>, PropertyActualArg<'a>)>,
|
||||
@ -472,7 +472,7 @@ pub struct SequencePortItem<'a> {
|
||||
pub nodes: (
|
||||
Vec<AttributeInstance<'a>>,
|
||||
Option<(Local<'a>, Option<SequenceLvarPortDirection<'a>>)>,
|
||||
SequenceFormalType<'a>,
|
||||
Option<SequenceFormalType<'a>>,
|
||||
FormalPortIdentifier<'a>,
|
||||
Vec<VariableDimension<'a>>,
|
||||
Option<(Symbol<'a>, SequenceActualArg<'a>)>,
|
||||
@ -975,11 +975,11 @@ pub fn property_port_list(s: Span) -> IResult<Span, PropertyPortList> {
|
||||
Ok((s, PropertyPortList { nodes: (a,) }))
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn property_port_item(s: Span) -> IResult<Span, PropertyPortItem> {
|
||||
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<Span, SequencePortList> {
|
||||
Ok((s, SequencePortList { nodes: (a,) }))
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn sequence_port_item(s: Span) -> IResult<Span, SequencePortItem> {
|
||||
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)?;
|
||||
|
@ -715,10 +715,10 @@ pub fn hierarchical_identifier_or_class_scope(
|
||||
))(s)
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn cover_point(s: Span) -> IResult<Span, CoverPoint> {
|
||||
let (s, a) = opt(triple(
|
||||
opt(data_type_or_implicit),
|
||||
ambiguous_opt(data_type_or_implicit),
|
||||
cover_point_identifier,
|
||||
symbol(":"),
|
||||
))(s)?;
|
||||
|
@ -32,7 +32,7 @@ pub enum FunctionBodyDeclaration<'a> {
|
||||
#[derive(Debug, Node)]
|
||||
pub struct FunctionBodyDeclarationWithoutPort<'a> {
|
||||
pub nodes: (
|
||||
FunctionDataTypeOrImplicit<'a>,
|
||||
Option<FunctionDataTypeOrImplicit<'a>>,
|
||||
Option<InterfaceIdentifierOrClassScope<'a>>,
|
||||
FunctionIdentifier<'a>,
|
||||
Symbol<'a>,
|
||||
@ -46,7 +46,7 @@ pub struct FunctionBodyDeclarationWithoutPort<'a> {
|
||||
#[derive(Debug, Node)]
|
||||
pub struct FunctionBodyDeclarationWithPort<'a> {
|
||||
pub nodes: (
|
||||
FunctionDataTypeOrImplicit<'a>,
|
||||
Option<FunctionDataTypeOrImplicit<'a>>,
|
||||
Option<InterfaceIdentifierOrClassScope<'a>>,
|
||||
FunctionIdentifier<'a>,
|
||||
Paren<'a, Option<TfPortList<'a>>>,
|
||||
@ -187,9 +187,9 @@ pub fn function_body_declaration(s: Span) -> IResult<Span, FunctionBodyDeclarati
|
||||
))(s)
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn function_body_declaration_without_port(s: Span) -> IResult<Span, FunctionBodyDeclaration> {
|
||||
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<Span, Function
|
||||
))
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn function_body_declaration_with_port(s: Span) -> IResult<Span, FunctionBodyDeclaration> {
|
||||
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)?;
|
||||
|
@ -34,7 +34,7 @@ pub struct LetPortList<'a> {
|
||||
pub struct LetPortItem<'a> {
|
||||
pub nodes: (
|
||||
Vec<AttributeInstance<'a>>,
|
||||
LetFormalType<'a>,
|
||||
Option<LetFormalType<'a>>,
|
||||
FormalPortIdentifier<'a>,
|
||||
Vec<VariableDimension<'a>>,
|
||||
Option<(Symbol<'a>, Expression<'a>)>,
|
||||
@ -124,10 +124,10 @@ pub fn let_port_list(s: Span) -> IResult<Span, LetPortList> {
|
||||
Ok((s, LetPortList { nodes: (a,) }))
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn let_port_item(s: Span) -> IResult<Span, LetPortItem> {
|
||||
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)?;
|
||||
|
@ -16,7 +16,7 @@ pub enum LocalParameterDeclaration<'a> {
|
||||
pub struct LocalParameterDeclarationParam<'a> {
|
||||
pub nodes: (
|
||||
Symbol<'a>,
|
||||
DataTypeOrImplicit<'a>,
|
||||
Option<DataTypeOrImplicit<'a>>,
|
||||
ListOfParamAssignments<'a>,
|
||||
),
|
||||
}
|
||||
@ -36,7 +36,7 @@ pub enum ParameterDeclaration<'a> {
|
||||
pub struct ParameterDeclarationParam<'a> {
|
||||
pub nodes: (
|
||||
Symbol<'a>,
|
||||
DataTypeOrImplicit<'a>,
|
||||
Option<DataTypeOrImplicit<'a>>,
|
||||
ListOfParamAssignments<'a>,
|
||||
),
|
||||
}
|
||||
@ -66,10 +66,10 @@ pub fn local_parameter_declaration(s: Span) -> IResult<Span, LocalParameterDecla
|
||||
))(s)
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn local_parameter_declaration_param(s: Span) -> IResult<Span, LocalParameterDeclaration> {
|
||||
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<Span, ParameterDeclaration> {
|
||||
alt((parameter_declaration_param, parameter_declaration_type))(s)
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn parameter_declaration_param(s: Span) -> IResult<Span, ParameterDeclaration> {
|
||||
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,
|
||||
|
@ -533,12 +533,12 @@ pub fn net_type(s: Span) -> IResult<Span, NetType> {
|
||||
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)),
|
||||
|
@ -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<NetPortType<'a>>,
|
||||
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<NetPortType<'a>>,
|
||||
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<NetPortType<'a>>,
|
||||
ListOfPortIdentifiers<'a>,
|
||||
),
|
||||
}
|
||||
|
||||
#[derive(Debug, Node)]
|
||||
@ -72,10 +84,10 @@ pub struct RefDeclaration<'a> {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn inout_declaration(s: Span) -> IResult<Span, InoutDeclaration> {
|
||||
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<Span, InputDeclaration> {
|
||||
alt((input_declaration_net, input_declaration_variable))(s)
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn input_declaration_net(s: Span) -> IResult<Span, InputDeclaration> {
|
||||
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<Span, OutputDeclaration> {
|
||||
alt((output_declaration_net, output_declaration_variable))(s)
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn output_declaration_net(s: Span) -> IResult<Span, OutputDeclaration> {
|
||||
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<Span, RefDeclaration> {
|
||||
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((_, _)));
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ pub struct TfPortItem<'a> {
|
||||
Vec<AttributeInstance<'a>>,
|
||||
Option<TfPortDirection<'a>>,
|
||||
Option<Var<'a>>,
|
||||
DataTypeOrImplicit<'a>,
|
||||
Option<DataTypeOrImplicit<'a>>,
|
||||
Option<(
|
||||
PortIdentifier<'a>,
|
||||
Vec<VariableDimension<'a>>,
|
||||
@ -84,7 +84,7 @@ pub struct TfPortDeclaration<'a> {
|
||||
Vec<AttributeInstance<'a>>,
|
||||
TfPortDirection<'a>,
|
||||
Option<Var<'a>>,
|
||||
DataTypeOrImplicit<'a>,
|
||||
Option<DataTypeOrImplicit<'a>>,
|
||||
ListOfTfVariableIdentifiers<'a>,
|
||||
Symbol<'a>,
|
||||
),
|
||||
@ -170,12 +170,12 @@ pub fn tf_port_list(s: Span) -> IResult<Span, TfPortList> {
|
||||
Ok((s, TfPortList { nodes: (a,) }))
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn tf_port_item(s: Span) -> IResult<Span, TfPortItem> {
|
||||
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<Span, TfPortDirection> {
|
||||
))(s)
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn tf_port_declaration(s: Span) -> IResult<Span, TfPortDeclaration> {
|
||||
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((
|
||||
|
@ -22,7 +22,7 @@ pub struct DataDeclarationVariable<'a> {
|
||||
Option<Const<'a>>,
|
||||
Option<Var<'a>>,
|
||||
Option<Lifetime<'a>>,
|
||||
DataTypeOrImplicit<'a>,
|
||||
Option<DataTypeOrImplicit<'a>>,
|
||||
ListOfVariableDeclAssignments<'a>,
|
||||
Symbol<'a>,
|
||||
),
|
||||
@ -96,7 +96,7 @@ pub struct NetDeclarationNetType<'a> {
|
||||
NetType<'a>,
|
||||
Option<Strength<'a>>,
|
||||
Option<VectorScalar<'a>>,
|
||||
DataTypeOrImplicit<'a>,
|
||||
Option<DataTypeOrImplicit<'a>>,
|
||||
Option<Delay3<'a>>,
|
||||
ListOfNetDeclAssignments<'a>,
|
||||
Symbol<'a>,
|
||||
@ -242,12 +242,12 @@ pub fn data_declaration(s: Span) -> IResult<Span, DataDeclaration> {
|
||||
))(s)
|
||||
}
|
||||
|
||||
#[parser]
|
||||
#[parser(Ambiguous)]
|
||||
pub fn data_declaration_variable(s: Span) -> IResult<Span, DataDeclaration> {
|
||||
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<Span, GenvarDeclaration> {
|
||||
#[parser]
|
||||
pub fn net_declaration(s: Span) -> IResult<Span, NetDeclaration> {
|
||||
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<Span, NetDeclaration> {
|
||||
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<Span, Lifetime> {
|
||||
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(_));
|
||||
}
|
||||
}
|
||||
|
@ -156,41 +156,6 @@ pub fn nonrange_variable_lvalue(s: Span) -> IResult<Span, NonrangeVariableLvalue
|
||||
Ok((s, NonrangeVariableLvalue { nodes: (a, b, c) }))
|
||||
}
|
||||
|
||||
#[derive(Debug, Node)]
|
||||
pub enum Expr<'a> {
|
||||
Expr(Box<ExprExpr<'a>>),
|
||||
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<Span, Expr> {
|
||||
alt((expr_expr, expr_term))(s)
|
||||
}
|
||||
|
||||
#[parser(MaybeRecursive)]
|
||||
pub fn expr_expr(s: Span) -> IResult<Span, Expr> {
|
||||
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<Span, Expr> {
|
||||
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((_, _)));
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +188,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn none<'a, O, F>(_f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Option<O>>
|
||||
where
|
||||
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
|
||||
{
|
||||
move |s: Span<'a>| Ok((s, None))
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#[parser]
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user