WIP: element type declarations
This commit is contained in:
parent
94b716753d
commit
435b2af24c
169
src/parser.rs
169
src/parser.rs
|
@ -434,7 +434,7 @@ pub fn int_subset(input: &str) -> IResult<&str, IntSubset> {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MarkupDecl<'s> {
|
enum MarkupDecl<'s> {
|
||||||
ElementDecl(ElementDecl<'s>),
|
Elementdecl(Elementdecl<'s>),
|
||||||
AttlistDecl(AttlistDecl<'s>),
|
AttlistDecl(AttlistDecl<'s>),
|
||||||
EntityDecl(EntityDecl<'s>),
|
EntityDecl(EntityDecl<'s>),
|
||||||
NotationDecl(NotationDecl<'s>),
|
NotationDecl(NotationDecl<'s>),
|
||||||
|
@ -444,8 +444,8 @@ enum MarkupDecl<'s> {
|
||||||
/// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
|
/// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
|
||||||
pub fn markup_decl(input: &str) -> IResult<&str, MarkupDecl> {
|
pub fn markup_decl(input: &str) -> IResult<&str, MarkupDecl> {
|
||||||
alt((
|
alt((
|
||||||
map(element_decl, |element_decl| {
|
map(elementdecl, |elementdecl| {
|
||||||
MarkupDecl::ElementDecl(element_decl)
|
MarkupDecl::Elementdecl(elementdecl)
|
||||||
}),
|
}),
|
||||||
map(attlist_decl, |attlist_decl| {
|
map(attlist_decl, |attlist_decl| {
|
||||||
MarkupDecl::AttlistDecl(attlist_decl)
|
MarkupDecl::AttlistDecl(attlist_decl)
|
||||||
|
@ -613,6 +613,169 @@ pub fn empty_elem_tag(input: &str) -> IResult<&str, EmptyElemTag> {
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Elementdecl<'s> {
|
||||||
|
name: Name<'s>,
|
||||||
|
contentspec: Contentspec<'s>,
|
||||||
|
}
|
||||||
|
/// [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
|
||||||
|
pub fn elementdecl(input: &str) -> IResult<&str, Elementdecl> {
|
||||||
|
map(
|
||||||
|
delimited(
|
||||||
|
pair(tag("<!ELEMENT"), s),
|
||||||
|
separated_pair(name, s, contentspec),
|
||||||
|
pair(opt(s), tag(">")),
|
||||||
|
),
|
||||||
|
|(name, contentspec)| Elementdecl { name, contentspec },
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: casings???
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum Contentspec<'s> {
|
||||||
|
Empty,
|
||||||
|
Any,
|
||||||
|
Mixed(Mixed<'s>),
|
||||||
|
Children(Children<'s>),
|
||||||
|
}
|
||||||
|
/// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
|
||||||
|
pub fn contentspec(input: &str) -> IResult<&str, Contentspec> {
|
||||||
|
alt((
|
||||||
|
value(Contentspec::Empty, tag("EMPTY")),
|
||||||
|
value(Contentspec::Any, tag("ANY")),
|
||||||
|
map(mixed, |mixed| Contentspec::Mixed(mixed)),
|
||||||
|
map(children, |children| Contentspec::Children(children)),
|
||||||
|
))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum Occurence {
|
||||||
|
Once,
|
||||||
|
Optional,
|
||||||
|
Many0,
|
||||||
|
Many1,
|
||||||
|
}
|
||||||
|
/// Occurence ::= ('?' | '*' | '+')?
|
||||||
|
pub fn occurence(input: &str) -> IResult<&str, Occurence> {
|
||||||
|
map(
|
||||||
|
opt(alt((tag("?"), tag("*"), tag("+")))),
|
||||||
|
|occurence| match occurence {
|
||||||
|
Some("?") => Occurence::Optional,
|
||||||
|
Some("*") => Occurence::Many0,
|
||||||
|
Some("+") => Occurence::Many1,
|
||||||
|
_ => Occurence::Once,
|
||||||
|
},
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum ChildrenKind<'s> {
|
||||||
|
Choice(Choice<'s>),
|
||||||
|
Seq(Seq<'s>),
|
||||||
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Children<'s> {
|
||||||
|
kind: ChildrenKind<'s>,
|
||||||
|
occurence: Occurence,
|
||||||
|
}
|
||||||
|
/// [47] children ::= (choice | seq) ('?' | '*' | '+')?
|
||||||
|
pub fn children(input: &str) -> IResult<&str, Children> {
|
||||||
|
map(
|
||||||
|
pair(
|
||||||
|
alt((
|
||||||
|
map(choice, |choice| ChildrenKind::Choice(choice)),
|
||||||
|
map(seq, |seq| ChildrenKind::Seq(seq)),
|
||||||
|
)),
|
||||||
|
occurence,
|
||||||
|
),
|
||||||
|
|(kind, occurence)| Children { kind, occurence },
|
||||||
|
)(input)
|
||||||
|
// alt((
|
||||||
|
// map(pair(choice, occurence), |(choice, occurence)| Children::Choice(choice, occurence)),
|
||||||
|
// map(pair(seq, occurence), |(seq, occurence)| Children::Seq(seq, occurence))
|
||||||
|
// ))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum CpKind<'s> {
|
||||||
|
Name(Name<'s>),
|
||||||
|
Choice(Choice<'s>),
|
||||||
|
Seq(Seq<'s>),
|
||||||
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Cp<'s> {
|
||||||
|
kind: CpKind<'s>,
|
||||||
|
occurence: Occurence,
|
||||||
|
}
|
||||||
|
/// [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
|
||||||
|
pub fn cp(input: &str) -> IResult<&str, Cp> {
|
||||||
|
map(
|
||||||
|
pair(
|
||||||
|
alt((
|
||||||
|
map(name, |name| CpKind::Name(name)),
|
||||||
|
map(choice, |choice| CpKind::Choice(choice)),
|
||||||
|
map(seq, |seq| CpKind::Seq(seq)),
|
||||||
|
)),
|
||||||
|
occurence,
|
||||||
|
),
|
||||||
|
|(kind, occurence)| Cp { kind, occurence },
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Choice<'s>(Vec<Cp<'s>>);
|
||||||
|
/// [49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'
|
||||||
|
pub fn choice(input: &str) -> IResult<&str, Choice> {
|
||||||
|
map(
|
||||||
|
delimited(
|
||||||
|
pair(tag("("), opt(s)),
|
||||||
|
pair(cp, many1(preceded(tuple((opt(s), tag("|"), opt(s))), cp))),
|
||||||
|
pair(opt(s), tag(")")),
|
||||||
|
),
|
||||||
|
|(first, rest)| {
|
||||||
|
let choice = vec![vec![first], rest].concat();
|
||||||
|
Choice(choice)
|
||||||
|
},
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Seq<'s>(Vec<Cp<'s>>);
|
||||||
|
/// [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
|
||||||
|
pub fn seq(input: &str) -> IResult<&str, Seq> {
|
||||||
|
map(
|
||||||
|
delimited(
|
||||||
|
pair(tag("("), opt(s)),
|
||||||
|
pair(cp, many0(preceded(tuple((opt(s), tag(","), opt(s))), cp))),
|
||||||
|
pair(opt(s), tag(")")),
|
||||||
|
),
|
||||||
|
|(first, rest)| {
|
||||||
|
let seq = vec![vec![first], rest].concat();
|
||||||
|
Seq(seq)
|
||||||
|
},
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
// always contains #PCDATA
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Mixed<'s>(Vec<Name<'s>>);
|
||||||
|
/// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'
|
||||||
|
pub fn mixed(input: &str) -> IResult<&str, Mixed> {
|
||||||
|
alt((
|
||||||
|
map(
|
||||||
|
delimited(
|
||||||
|
tuple((tag("("), s, tag("#PCDATA"))),
|
||||||
|
many0(preceded(tuple((opt(s), tag("|"), opt(s))), name)),
|
||||||
|
pair(opt(s), tag(")*")),
|
||||||
|
),
|
||||||
|
|names| Mixed(names),
|
||||||
|
),
|
||||||
|
value(
|
||||||
|
Mixed(Vec::new()),
|
||||||
|
tuple((tag("("), opt(s), tag("#PCDATA"), opt(s), tag(")"))),
|
||||||
|
),
|
||||||
|
))(input)
|
||||||
|
}
|
||||||
|
|
||||||
enum CharRef<'s> {
|
enum CharRef<'s> {
|
||||||
Decimal(&'s str),
|
Decimal(&'s str),
|
||||||
Hexadecimal(&'s str),
|
Hexadecimal(&'s str),
|
||||||
|
|
Loading…
Reference in New Issue