Skip to content

Commit a4b7587

Browse files
committed
Add SourceLocation to syntax errors.
1 parent 8d4343b commit a4b7587

File tree

3 files changed

+74
-48
lines changed

3 files changed

+74
-48
lines changed

ast.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ pub enum Rule {
105105
AtRule(AtRule),
106106
}
107107

108+
#[deriving(Eq)]
109+
pub struct SyntaxError {
110+
location: SourceLocation,
111+
reason: ErrorReason,
112+
}
113+
108114
#[deriving(Eq)]
109115
pub enum ErrorReason {
110116
ErrEmptyInput, // Parsing a single "thing", found only whitespace.
@@ -115,8 +121,10 @@ pub enum ErrorReason {
115121
// This is meant to be extended
116122
}
117123

118-
impl ToStr for ErrorReason {
119-
fn to_str(&self) -> ~str { fmt!("%?", self) }
124+
impl ToStr for SyntaxError {
125+
fn to_str(&self) -> ~str {
126+
fmt!("%u:%u %?", self.location.line, self.location.column, self.reason)
127+
}
120128
}
121129

122130

parser.rs

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ use ast::*;
2121

2222

2323
/// Parse top-level of a CSS stylesheet.
24-
/// Return a Iterator<Result<Rule, ErrorReason>>
24+
/// Return a Iterator<Result<Rule, SyntaxError>>
2525
#[inline]
2626
pub fn parse_stylesheet_rules<T: Iterator<Node>>(iter: T) -> StylesheetParser<T> {
2727
StylesheetParser(iter)
2828
}
2929

3030

3131
/// Parse a non-top level list of rules eg. the content of an @media rule.
32-
/// Return a Iterator<Result<Rule, ErrorReason>>
32+
/// Return a Iterator<Result<Rule, SyntaxError>>
3333
#[inline]
3434
pub fn parse_rule_list<T: Iterator<Node>>(iter: T) -> RuleListParser<T> {
3535
RuleListParser(iter)
@@ -38,7 +38,7 @@ pub fn parse_rule_list<T: Iterator<Node>>(iter: T) -> RuleListParser<T> {
3838

3939
/// Parse a list of declarations and at-rules,
4040
/// like @page in CSS 2.1, all declaration lists in level 3
41-
/// Return a Iterator<Result<DeclarationListItem, ErrorReason>>
41+
/// Return a Iterator<Result<DeclarationListItem, SyntaxError>>
4242
#[inline]
4343
pub fn parse_declaration_list<T: Iterator<Node>>(iter: T) -> DeclarationListParser<T> {
4444
DeclarationListParser(iter)
@@ -47,27 +47,33 @@ pub fn parse_declaration_list<T: Iterator<Node>>(iter: T) -> DeclarationListPars
4747

4848
/// Parse a single rule.
4949
/// Used eg. for CSSRuleList.insertRule()
50-
pub fn parse_one_rule<T: Iterator<Node>>(iter: T) -> Result<Rule, ErrorReason> {
50+
pub fn parse_one_rule<T: Iterator<Node>>(iter: T) -> Result<Rule, SyntaxError> {
5151
let mut parser = RuleListParser(iter);
5252
match parser.next() {
53-
None => Err(ErrEmptyInput),
53+
None => error(START_LOCATION, ErrEmptyInput),
5454
Some(result) => {
55-
if result.is_err() || next_non_whitespace(&mut *parser).is_none() { result }
56-
else { Err(ErrExtraInput) }
55+
if result.is_err() { result }
56+
else { match next_non_whitespace(&mut *parser) {
57+
None => result,
58+
Some((_component_value, location)) => error(location, ErrExtraInput),
59+
}}
5760
}
5861
}
5962
}
6063

6164

6265
/// Parse a single declaration (not an at-rule)
6366
/// Used eg. in @supports
64-
pub fn parse_one_declaration<T: Iterator<Node>>(mut iter: T) -> Result<Declaration, ErrorReason> {
67+
pub fn parse_one_declaration<T: Iterator<Node>>(mut iter: T) -> Result<Declaration, SyntaxError> {
6568
match next_non_whitespace(&mut iter) {
66-
None => Err(ErrEmptyInput),
69+
None => error(START_LOCATION, ErrEmptyInput),
6770
Some((component_value, location)) => {
6871
let result = parse_declaration(&mut iter, component_value, location);
69-
if result.is_err() || next_non_whitespace(&mut iter).is_none() { result }
70-
else { Err(ErrExtraInput) }
72+
if result.is_err() { result }
73+
else { match next_non_whitespace(&mut iter) {
74+
None => result,
75+
Some((_component_value, location)) => error(location, ErrExtraInput),
76+
}}
7177
}
7278
}
7379
}
@@ -76,12 +82,14 @@ pub fn parse_one_declaration<T: Iterator<Node>>(mut iter: T) -> Result<Declarati
7682
/// Parse a single component value.
7783
/// Used eg. in attr(foo, color)
7884
pub fn parse_one_component_value<T: Iterator<Node>>(mut iter: T)
79-
-> Result<ComponentValue, ErrorReason> {
85+
-> Result<ComponentValue, SyntaxError> {
8086
match next_non_whitespace(&mut iter) {
81-
None => Err(ErrEmptyInput),
87+
None => error(START_LOCATION, ErrEmptyInput),
8288
Some((component_value, _location)) => {
83-
if next_non_whitespace(&mut iter).is_none() { Ok(component_value) }
84-
else { Err(ErrExtraInput) }
89+
match next_non_whitespace(&mut iter) {
90+
None => Ok(component_value),
91+
Some((_component_value, location)) => error(location, ErrExtraInput),
92+
}
8593
}
8694
}
8795
}
@@ -106,16 +114,16 @@ macro_rules! for_iter(
106114
)
107115

108116

109-
impl<T: Iterator<Node>> Iterator<Result<Rule, ErrorReason>> for StylesheetParser<T> {
110-
fn next(&mut self) -> Option<Result<Rule, ErrorReason>> {
117+
impl<T: Iterator<Node>> Iterator<Result<Rule, SyntaxError>> for StylesheetParser<T> {
118+
fn next(&mut self) -> Option<Result<Rule, SyntaxError>> {
111119
let iter = &mut **self;
112120
for_iter!(iter, (component_value, location), {
113121
match component_value {
114122
WhiteSpace | CDO | CDC => (),
115123
AtKeyword(name) => return Some(Ok(AtRule(parse_at_rule(iter, name, location)))),
116124
_ => return Some(match parse_qualified_rule(iter, component_value, location) {
117125
Ok(rule) => Ok(QualifiedRule(rule)),
118-
Err(reason) => Err(reason),
126+
Err(e) => Err(e),
119127
}),
120128
}
121129
})
@@ -124,16 +132,16 @@ impl<T: Iterator<Node>> Iterator<Result<Rule, ErrorReason>> for StylesheetParser
124132
}
125133

126134

127-
impl<T: Iterator<Node>> Iterator<Result<Rule, ErrorReason>> for RuleListParser<T> {
128-
fn next(&mut self) -> Option<Result<Rule, ErrorReason>> {
135+
impl<T: Iterator<Node>> Iterator<Result<Rule, SyntaxError>> for RuleListParser<T> {
136+
fn next(&mut self) -> Option<Result<Rule, SyntaxError>> {
129137
let iter = &mut **self;
130138
for_iter!(iter, (component_value, location), {
131139
match component_value {
132140
WhiteSpace => (),
133141
AtKeyword(name) => return Some(Ok(AtRule(parse_at_rule(iter, name, location)))),
134142
_ => return Some(match parse_qualified_rule(iter, component_value, location) {
135143
Ok(rule) => Ok(QualifiedRule(rule)),
136-
Err(reason) => Err(reason),
144+
Err(e) => Err(e),
137145
}),
138146
}
139147
})
@@ -142,9 +150,9 @@ impl<T: Iterator<Node>> Iterator<Result<Rule, ErrorReason>> for RuleListParser<T
142150
}
143151

144152

145-
impl<T: Iterator<Node>> Iterator<Result<DeclarationListItem, ErrorReason>>
153+
impl<T: Iterator<Node>> Iterator<Result<DeclarationListItem, SyntaxError>>
146154
for DeclarationListParser<T> {
147-
fn next(&mut self) -> Option<Result<DeclarationListItem, ErrorReason>> {
155+
fn next(&mut self) -> Option<Result<DeclarationListItem, SyntaxError>> {
148156
let iter = &mut **self;
149157
for_iter!(iter, (component_value, location), {
150158
match component_value {
@@ -153,10 +161,10 @@ for DeclarationListParser<T> {
153161
=> return Some(Ok(Decl_AtRule(parse_at_rule(iter, name, location)))),
154162
_ => return Some(match parse_declaration(iter, component_value, location) {
155163
Ok(declaration) => Ok(Declaration(declaration)),
156-
Err(reason) => {
164+
Err(e) => {
157165
// Find the end of the declaration
158166
for (v, _) in *iter { if v == Semicolon { break } }
159-
Err(reason)
167+
Err(e)
160168
}
161169
}),
162170
}
@@ -183,7 +191,7 @@ fn parse_at_rule<T: Iterator<Node>>(iter: &mut T, name: ~str, location: SourceLo
183191

184192
fn parse_qualified_rule<T: Iterator<Node>>(iter: &mut T, first: ComponentValue,
185193
location: SourceLocation)
186-
-> Result<QualifiedRule, ErrorReason> {
194+
-> Result<QualifiedRule, SyntaxError> {
187195
match first {
188196
CurlyBracketBlock(content)
189197
=> return Ok(QualifiedRule { location: location, prelude: ~[], block: content }),
@@ -197,20 +205,20 @@ fn parse_qualified_rule<T: Iterator<Node>>(iter: &mut T, first: ComponentValue,
197205
component_value => prelude.push(component_value),
198206
}
199207
})
200-
Err(ErrMissingQualifiedRuleBlock)
208+
error(location, ErrMissingQualifiedRuleBlock)
201209
}
202210

203211

204212
fn parse_declaration<T: Iterator<Node>>(iter: &mut T, first: ComponentValue,
205213
location: SourceLocation)
206-
-> Result<Declaration, ErrorReason> {
214+
-> Result<Declaration, SyntaxError> {
207215
let name = match first {
208216
Ident(name) => name,
209-
_ => return Err(ErrInvalidDeclarationSyntax)
217+
_ => return error(location, ErrInvalidDeclarationSyntax)
210218
};
211219
match next_non_whitespace(iter) {
212220
Some((Colon, _)) => (),
213-
_ => return Err(ErrInvalidDeclarationSyntax),
221+
_ => return error(location, ErrInvalidDeclarationSyntax),
214222
}
215223
let mut value = ~[];
216224
let mut important = false;
@@ -221,7 +229,7 @@ fn parse_declaration<T: Iterator<Node>>(iter: &mut T, first: ComponentValue,
221229
important = true;
222230
break
223231
} else {
224-
return Err(ErrInvalidBangImportantSyntax)
232+
return error(location, ErrInvalidBangImportantSyntax)
225233
},
226234
component_value => value.push(component_value),
227235
}
@@ -252,3 +260,13 @@ fn next_non_whitespace<T: Iterator<Node>>(iter: &mut T) -> Option<Node> {
252260
}
253261
None
254262
}
263+
264+
265+
#[inline]
266+
fn error<T>(location: SourceLocation, reason: ErrorReason) -> Result<T, SyntaxError> {
267+
Err(SyntaxError{location: location, reason: reason})
268+
}
269+
270+
271+
// When parsing one thing on an empty input
272+
static START_LOCATION: SourceLocation = SourceLocation{ line: 1, column: 1 };

tests.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ fn color3_keywords() {
164164
}
165165
166166
167-
impl ToJson for Result<Rule, ErrorReason> {
167+
impl ToJson for Result<Rule, SyntaxError> {
168168
fn to_json(&self) -> json::Json {
169169
match *self {
170170
Ok(ref a) => a.to_json(),
@@ -174,7 +174,7 @@ impl ToJson for Result<Rule, ErrorReason> {
174174
}
175175
176176
177-
impl ToJson for Result<DeclarationListItem, ErrorReason> {
177+
impl ToJson for Result<DeclarationListItem, SyntaxError> {
178178
fn to_json(&self) -> json::Json {
179179
match *self {
180180
Ok(ref a) => a.to_json(),
@@ -184,7 +184,7 @@ impl ToJson for Result<DeclarationListItem, ErrorReason> {
184184
}
185185
186186
187-
impl ToJson for Result<Declaration, ErrorReason> {
187+
impl ToJson for Result<Declaration, SyntaxError> {
188188
fn to_json(&self) -> json::Json {
189189
match *self {
190190
Ok(ref a) => a.to_json(),
@@ -194,7 +194,7 @@ impl ToJson for Result<Declaration, ErrorReason> {
194194
}
195195
196196
197-
impl ToJson for Result<ComponentValue, ErrorReason> {
197+
impl ToJson for Result<ComponentValue, SyntaxError> {
198198
fn to_json(&self) -> json::Json {
199199
match *self {
200200
Ok(ref a) => a.to_json(),
@@ -204,23 +204,23 @@ impl ToJson for Result<ComponentValue, ErrorReason> {
204204
}
205205
206206
207-
impl ToJson for Color {
207+
impl ToJson for SyntaxError {
208208
fn to_json(&self) -> json::Json {
209-
match *self {
210-
RGBA(r, g, b, a) => (~[r, g, b, a]).to_json(),
211-
CurrentColor => json::String(~"currentColor"),
212-
}
209+
json::List(~[json::String(~"error"), json::String(match self.reason {
210+
ErrEmptyInput => ~"empty",
211+
ErrExtraInput => ~"extra-input",
212+
_ => ~"invalid",
213+
})])
213214
}
214215
}
215216
216217
217-
impl ToJson for ErrorReason {
218+
impl ToJson for Color {
218219
fn to_json(&self) -> json::Json {
219-
json::List(~[json::String(~"error"), json::String(match *self {
220-
ErrEmptyInput => ~"empty",
221-
ErrExtraInput => ~"extra-input",
222-
_ => ~"invalid",
223-
})])
220+
match *self {
221+
RGBA(r, g, b, a) => (~[r, g, b, a]).to_json(),
222+
CurrentColor => json::String(~"currentColor"),
223+
}
224224
}
225225
}
226226

0 commit comments

Comments
 (0)