Skip to content

Commit

Permalink
refactor a ton of redundant code by using macros
Browse files Browse the repository at this point in the history
  • Loading branch information
ohanar committed Jul 26, 2018
1 parent f10a29e commit 2612807
Show file tree
Hide file tree
Showing 12 changed files with 1,193 additions and 1,795 deletions.
113 changes: 51 additions & 62 deletions src/argument.rs
@@ -1,84 +1,73 @@
use types::*;
use Parse;
use common::*;
use attribute::*;
use attribute::ExtendedAttributeList;
use common::{Default, Identifier, Punctuated};
use types::{AttributedType, Type};

/// Parses a list of argument. Ex: `double v1, double v2, double v3, optional double alpha`
pub type ArgumentList = Punctuated<Argument, term!(,)>;

/// Parses an argument. Ex: `double v1|double... v1s`
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub enum Argument {
Single(SingleArgument),
Variadic(VariadicArgument)
}

impl Parse for Argument {
named!(parse -> Self, alt!(
weedle!(SingleArgument) => {|inner| Argument::Single(inner)} |
weedle!(VariadicArgument) => {|inner| Argument::Variadic(inner)}
));
}

/// Parses `[attributes]? optional? attributedtype identifier ( = default )?`
///
/// Note: `= default` is only allowed if `optional` is present
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub struct SingleArgument {
pub attributes: Option<ExtendedAttributeList>,
pub optional: Option<term!(optional)>,
pub type_: AttributedType,
pub identifier: Identifier,
pub default: Option<Default>
}

impl Parse for SingleArgument {
named!(parse -> Self, do_parse!(
attributes: weedle!(Option<ExtendedAttributeList>) >>
optional: weedle!(Option<term!(optional)>) >>
type_: weedle!(AttributedType) >>
identifier: weedle!(Identifier) >>
default: opt_flat!(cond_reduce!(optional.is_some(), weedle!(Option<Default>))) >>
(SingleArgument { attributes, optional, type_, identifier, default })
));
}

/// Parses `[attributes]? type... identifier`
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub struct VariadicArgument {
pub attributes: Option<ExtendedAttributeList>,
pub type_: Type,
pub ellipsis: term!(...),
pub identifier: Identifier
}

impl Parse for VariadicArgument {
named!(parse -> Self, do_parse!(
attributes: weedle!(Option<ExtendedAttributeList>) >>
type_: weedle!(Type) >>
ellipsis: weedle!(term!(...)) >>
identifier: weedle!(Identifier) >>
(VariadicArgument { attributes, type_, ellipsis, identifier })
));
ast_types! {
/// Parses an argument. Ex: `double v1|double... v1s`
enum Argument {
/// Parses `[attributes]? optional? attributedtype identifier ( = default )?`
///
/// Note: `= default` is only allowed if `optional` is present
Single(struct SingleArgument {
attributes: Option<ExtendedAttributeList>,
optional: Option<term!(optional)>,
type_: AttributedType,
identifier: Identifier,
default: Option<Default> = map!(cond!(optional.is_some(), weedle!(Option<Default>)), |default| default.unwrap_or(None)),
}),
/// Parses `[attributes]? type... identifier`
Variadic(struct VariadicArgument {
attributes: Option<ExtendedAttributeList>,
type_: Type,
ellipsis: term!(...),
identifier: Identifier,
}),
}
}

#[cfg(test)]
mod test {
use super::*;
use literal::{DecLit, DefaultValue, IntegerLit};
use Parse;

test!(should_parse_single_argument { "optional short a" =>
test!(should_parse_single_argument { "short a" =>
"";
SingleArgument;
attributes.is_none();
optional.is_some();
identifier.name == "a";
optional.is_none();
identifier.0 == "a";
default.is_none();
});

test!(should_parse_variadic_argument { "short... a" =>
"";
VariadicArgument;
attributes.is_none();
identifier.name == "a";
identifier.0 == "a";
});

test!(should_parse_optional_single_argument { "optional short a" =>
"";
SingleArgument;
attributes.is_none();
optional.is_some();
identifier.0 == "a";
default.is_none();
});

test!(should_parse_optional_single_argument_with_default { "optional short a = 5" =>
"";
SingleArgument;
attributes.is_none();
optional.is_some();
identifier.0 == "a";
default == Some(Default {
assign: term!(=),
value: DefaultValue::Integer(IntegerLit::Dec(DecLit("5".to_string()))),
});
});
}
165 changes: 49 additions & 116 deletions src/attribute.rs
@@ -1,156 +1,89 @@
use Parse;
use common::*;
use argument::*;
use argument::ArgumentList;
use common::{Braced, Bracketed, Identifier, Punctuated};

/// Parses a list of attributes. Ex: `[ attribute1, attribute2 ]`
pub type ExtendedAttributeList = Bracketed<Punctuated<ExtendedAttribute, term!(,)>>;

/// Parses on of the forms of attribute
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub enum ExtendedAttribute {
ArgList(ExtendedAttributeArgList),
NamedArgList(ExtendedAttributeNamedArgList),
IdentList(ExtendedAttributeIdentList),
Ident(ExtendedAttributeIdent),
NoArgs(ExtendedAttributeNoArgs),
}

impl Parse for ExtendedAttribute {
named!(parse -> Self, alt!(
weedle!(ExtendedAttributeArgList) => {|inner| ExtendedAttribute::ArgList(inner)} |
weedle!(ExtendedAttributeNamedArgList) => {|inner| ExtendedAttribute::NamedArgList(inner)} |
weedle!(ExtendedAttributeIdentList) => {|inner| ExtendedAttribute::IdentList(inner)} |
weedle!(ExtendedAttributeIdent) => {|inner| ExtendedAttribute::Ident(inner)} |
weedle!(ExtendedAttributeNoArgs) => {|inner| ExtendedAttribute::NoArgs(inner)}
));
}

/// Parses a named argument list. Ex: `NamedConstructor=Image((DOMString src))`
///
/// (( )) means ( ) chars
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub struct ExtendedAttributeNamedArgList {
pub lhs_identifier: Identifier,
pub assign: term!(=),
pub rhs_identifier: Identifier,
pub args: Braced<ArgumentList>,
}

impl Parse for ExtendedAttributeNamedArgList {
named!(parse -> Self, do_parse!(
lhs_identifier: weedle!(Identifier) >>
assign: weedle!(term!(=)) >>
rhs_identifier: weedle!(Identifier) >>
args: weedle!(Braced<ArgumentList>) >>
(ExtendedAttributeNamedArgList { lhs_identifier, assign, rhs_identifier, args })
));
}

/// Parses an identifier list. Ex: `Exposed=((Window,Worker))`
///
/// (( )) means ( ) chars
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub struct ExtendedAttributeIdentList {
pub identifier: Identifier,
pub assign: term!(=),
pub list: Braced<IdentifierList>
}

impl Parse for ExtendedAttributeIdentList {
named!(parse -> Self, do_parse!(
identifier: weedle!(Identifier) >>
assign: weedle!(term!(=)) >>
list: weedle!(Braced<IdentifierList>) >>
(ExtendedAttributeIdentList { identifier, assign, list })
));
}

/// Matches comma separated identifier list
pub type IdentifierList = Punctuated<Identifier, term!(,)>;

/// Parses an attribute with an identifier. Ex: `PutForwards=name`
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub struct ExtendedAttributeIdent {
pub lhs_identifier: Identifier,
pub assign: term!(=),
pub rhs_identifier: Identifier
}

impl Parse for ExtendedAttributeIdent {
named!(parse -> Self, do_parse!(
lhs_identifier: weedle!(Identifier) >>
assign: weedle!(term!(=)) >>
rhs_identifier: weedle!(Identifier) >>
(ExtendedAttributeIdent { lhs_identifier, assign, rhs_identifier })
));
}

/// Parses an argument list. Ex: `Constructor((double x, double y))`
///
/// (( )) means ( ) chars
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub struct ExtendedAttributeArgList {
pub identifier: Identifier,
pub args: Braced<ArgumentList>
}

impl Parse for ExtendedAttributeArgList {
named!(parse -> Self, do_parse!(
identifier: weedle!(Identifier) >>
args: weedle!(Braced<ArgumentList>) >>
(ExtendedAttributeArgList { identifier, args })
));
}

/// Parses a plain attribute. Ex: `Replaceable`
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
pub struct ExtendedAttributeNoArgs {
pub identifier: Identifier
}

impl Parse for ExtendedAttributeNoArgs {
named!(parse -> Self, do_parse!(
identifier: weedle!(Identifier) >>
(ExtendedAttributeNoArgs { identifier })
));
ast_types! {
/// Parses on of the forms of attribute
enum ExtendedAttribute {
/// Parses an argument list. Ex: `Constructor((double x, double y))`
///
/// (( )) means ( ) chars
ArgList(struct ExtendedAttributeArgList {
identifier: Identifier,
args: Braced<ArgumentList>,
}),
/// Parses a named argument list. Ex: `NamedConstructor=Image((DOMString src))`
///
/// (( )) means ( ) chars
NamedArgList(struct ExtendedAttributeNamedArgList {
lhs_identifier: Identifier,
assign: term!(=),
rhs_identifier: Identifier,
args: Braced<ArgumentList>,

}),
/// Parses an identifier list. Ex: `Exposed=((Window,Worker))`
///
/// (( )) means ( ) chars
IdentList(struct ExtendedAttributeIdentList {
identifier: Identifier,
assign: term!(=),
list: Braced<IdentifierList>,
}),
/// Parses an attribute with an identifier. Ex: `PutForwards=name`
Ident(struct ExtendedAttributeIdent {
lhs_identifier: Identifier,
assign: term!(=),
rhs_identifier: Identifier,
}),
/// Parses a plain attribute. Ex: `Replaceable`
NoArgs(struct ExtendedAttributeNoArgs(
Identifier,
)),
}
}

#[cfg(test)]
mod test {
use super::*;
use Parse;

test!(should_parse_attribute_no_args { "Replaceable" =>
"";
ExtendedAttributeNoArgs;
identifier.name == "Replaceable";
ExtendedAttributeNoArgs => ExtendedAttributeNoArgs(Identifier("Replaceable".to_string()))
});

test!(should_parse_attribute_arg_list { "Constructor(double x, double y)" =>
"";
ExtendedAttributeArgList;
identifier.name == "Constructor";
identifier.0 == "Constructor";
args.body.list.len() == 2;
});

test!(should_parse_attribute_ident { "PutForwards=name" =>
"";
ExtendedAttributeIdent;
lhs_identifier.name == "PutForwards";
rhs_identifier.name == "name";
lhs_identifier.0 == "PutForwards";
rhs_identifier.0 == "name";
});

test!(should_parse_ident_list { "Exposed=(Window,Worker)" =>
"";
ExtendedAttributeIdentList;
identifier.name == "Exposed";
identifier.0 == "Exposed";
list.body.list.len() == 2;
});

test!(should_parse_named_arg_list { "NamedConstructor=Image(DOMString src)" =>
"";
ExtendedAttributeNamedArgList;
lhs_identifier.name == "NamedConstructor";
rhs_identifier.name == "Image";
lhs_identifier.0 == "NamedConstructor";
rhs_identifier.0 == "Image";
args.body.list.len() == 1;
});
}

0 comments on commit 2612807

Please sign in to comment.