xml/reader/parser/
inside_declaration.rs

1
2use common::XmlVersion;
3
4use reader::events::XmlEvent;
5use reader::lexer::Token;
6
7use super::{
8    Result, PullParser, State, DeclarationSubstate, QualifiedNameTarget,
9    DEFAULT_VERSION, DEFAULT_ENCODING
10};
11
12impl PullParser {
13    // TODO: remove redundancy via macros or extra methods
14    pub fn inside_declaration(&mut self, t: Token, s: DeclarationSubstate) -> Option<Result> {
15        macro_rules! unexpected_token(
16            ($this:expr; $t:expr) => (Some($this.error(format!("Unexpected token inside XML declaration: {}", $t))));
17            ($t:expr) => (unexpected_token!(self; $t));
18        );
19
20        #[inline]
21        fn emit_start_document(this: &mut PullParser) -> Option<Result> {
22            this.parsed_declaration = true;
23            let version = this.data.take_version();
24            let encoding = this.data.take_encoding();
25            let standalone = this.data.take_standalone();
26            this.into_state_emit(State::OutsideTag, Ok(XmlEvent::StartDocument {
27                version: version.unwrap_or(DEFAULT_VERSION),
28                encoding: encoding.unwrap_or(DEFAULT_ENCODING.into()),
29                standalone: standalone
30            }))
31        }
32
33        match s {
34            DeclarationSubstate::BeforeVersion => match t {
35                Token::Whitespace(_) => None,  // continue
36                Token::Character('v') => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideVersion)),
37                _ => unexpected_token!(t)
38            },
39
40            DeclarationSubstate::InsideVersion => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| {
41                match &name.local_name[..] {
42                    "ersion" if name.namespace.is_none() =>
43                        this.into_state_continue(State::InsideDeclaration(
44                            if token == Token::EqualsSign {
45                                DeclarationSubstate::InsideVersionValue
46                            } else {
47                                DeclarationSubstate::AfterVersion
48                            }
49                        )),
50                    _ => unexpected_token!(this; name)
51                }
52            }),
53
54            DeclarationSubstate::AfterVersion => match t {
55                Token::Whitespace(_) => None,
56                Token::EqualsSign => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideVersionValue)),
57                _ => unexpected_token!(t)
58            },
59
60            DeclarationSubstate::InsideVersionValue => self.read_attribute_value(t, |this, value| {
61                this.data.version = match &value[..] {
62                    "1.0" => Some(XmlVersion::Version10),
63                    "1.1" => Some(XmlVersion::Version11),
64                    _     => None
65                };
66                if this.data.version.is_some() {
67                    this.into_state_continue(State::InsideDeclaration(DeclarationSubstate::AfterVersionValue))
68                } else {
69                    Some(self_error!(this; "Unexpected XML version value: {}", value))
70                }
71            }),
72
73            DeclarationSubstate::AfterVersionValue => match t {
74                Token::Whitespace(_) => None,  // skip whitespace
75                Token::Character('e') => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideEncoding)),
76                Token::Character('s') => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideStandaloneDecl)),
77                Token::ProcessingInstructionEnd => emit_start_document(self),
78                _ => unexpected_token!(t)
79            },
80
81            DeclarationSubstate::InsideEncoding => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| {
82                match &name.local_name[..] {
83                    "ncoding" if name.namespace.is_none() =>
84                        this.into_state_continue(State::InsideDeclaration(
85                            if token == Token::EqualsSign { DeclarationSubstate::InsideEncodingValue } else { DeclarationSubstate::AfterEncoding }
86                        )),
87                    _ => unexpected_token!(this; name)
88                }
89            }),
90
91            DeclarationSubstate::AfterEncoding => match t {
92                Token::Whitespace(_) => None,
93                Token::EqualsSign => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideEncodingValue)),
94                _ => unexpected_token!(t)
95            },
96
97            DeclarationSubstate::InsideEncodingValue => self.read_attribute_value(t, |this, value| {
98                this.data.encoding = Some(value);
99                this.into_state_continue(State::InsideDeclaration(DeclarationSubstate::BeforeStandaloneDecl))
100            }),
101
102            DeclarationSubstate::BeforeStandaloneDecl => match t {
103                Token::Whitespace(_) => None,  // skip whitespace
104                Token::Character('s') => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideStandaloneDecl)),
105                Token::ProcessingInstructionEnd => emit_start_document(self),
106                _ => unexpected_token!(t)
107            },
108
109            DeclarationSubstate::InsideStandaloneDecl => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| {
110                match &name.local_name[..] {
111                    "tandalone" if name.namespace.is_none() =>
112                        this.into_state_continue(State::InsideDeclaration(
113                            if token == Token::EqualsSign {
114                                DeclarationSubstate::InsideStandaloneDeclValue
115                            } else {
116                                DeclarationSubstate::AfterStandaloneDecl
117                            }
118                        )),
119                    _ => unexpected_token!(this; name)
120                }
121            }),
122
123            DeclarationSubstate::AfterStandaloneDecl => match t {
124                Token::Whitespace(_) => None,
125                Token::EqualsSign => self.into_state_continue(State::InsideDeclaration(DeclarationSubstate::InsideStandaloneDeclValue)),
126                _ => unexpected_token!(t)
127            },
128
129            DeclarationSubstate::InsideStandaloneDeclValue => self.read_attribute_value(t, |this, value| {
130                let standalone = match &value[..] {
131                    "yes" => Some(true),
132                    "no"  => Some(false),
133                    _     => None
134                };
135                if standalone.is_some() {
136                    this.data.standalone = standalone;
137                    this.into_state_continue(State::InsideDeclaration(DeclarationSubstate::AfterStandaloneDeclValue))
138                } else {
139                    Some(self_error!(this; "Invalid standalone declaration value: {}", value))
140                }
141            }),
142
143            DeclarationSubstate::AfterStandaloneDeclValue => match t {
144                Token::Whitespace(_) => None,  // skip whitespace
145                Token::ProcessingInstructionEnd => emit_start_document(self),
146                _ => unexpected_token!(t)
147            }
148        }
149    }
150
151}