Fix an indented syntax parsing bug.

This commit is contained in:
Natalie Weizenbaum 2016-10-30 13:06:23 -07:00
parent 5ad9540e39
commit e28b399c0b
3 changed files with 29 additions and 23 deletions

View File

@ -38,6 +38,10 @@ class SassParser extends StylesheetParser {
SassParser(String contents, {url, bool color: false}) SassParser(String contents, {url, bool color: false})
: super(contents, url: url, color: color); : super(contents, url: url, color: color);
void expectStatementSeparator() {
if (!atEndOfStatement()) scanner.expectChar($lf);
}
bool atEndOfStatement() { bool atEndOfStatement() {
var next = scanner.peekChar(); var next = scanner.peekChar();
return next == null || isNewline(next); return next == null || isNewline(next);

View File

@ -16,6 +16,14 @@ class ScssParser extends StylesheetParser {
ScssParser(String contents, {url, bool color: false}) ScssParser(String contents, {url, bool color: false})
: super(contents, url: url, color: color); : super(contents, url: url, color: color);
void expectStatementSeparator() {
whitespaceWithoutComments();
if (scanner.isDone) return;
var next = scanner.peekChar();
if (next == $semicolon || next == $rbrace) return;
scanner.expectChar($semicolon);
}
bool atEndOfStatement() { bool atEndOfStatement() {
var next = scanner.peekChar(); var next = scanner.peekChar();
return next == null || return next == null ||

View File

@ -111,7 +111,7 @@ abstract class StylesheetParser extends Parser {
whitespace(); whitespace();
} }
_expectStatementSeparator(); expectStatementSeparator();
return new VariableDeclaration(name, expression, scanner.spanFrom(start), return new VariableDeclaration(name, expression, scanner.spanFrom(start),
guarded: guarded, global: global); guarded: guarded, global: global);
@ -162,7 +162,7 @@ abstract class StylesheetParser extends Parser {
var declarationOrBuffer = _declarationOrBuffer(); var declarationOrBuffer = _declarationOrBuffer();
if (declarationOrBuffer is Declaration) { if (declarationOrBuffer is Declaration) {
_expectStatementSeparator(); expectStatementSeparator();
return declarationOrBuffer; return declarationOrBuffer;
} }
@ -300,7 +300,7 @@ abstract class StylesheetParser extends Parser {
var value = _declarationExpression(); var value = _declarationExpression();
var children = var children =
lookingAtChildren() ? this.children(_declarationChild) : null; lookingAtChildren() ? this.children(_declarationChild) : null;
if (children == null) _expectStatementSeparator(); if (children == null) expectStatementSeparator();
return new Declaration(name, scanner.spanFrom(start), return new Declaration(name, scanner.spanFrom(start),
value: value, children: children); value: value, children: children);
} }
@ -486,7 +486,7 @@ abstract class StylesheetParser extends Parser {
/// [start] should point before the `@`. /// [start] should point before the `@`.
DebugRule _debugRule(LineScannerState start) { DebugRule _debugRule(LineScannerState start) {
var expression = _expression(); var expression = _expression();
_expectStatementSeparator(); expectStatementSeparator();
return new DebugRule(expression, scanner.spanFrom(start)); return new DebugRule(expression, scanner.spanFrom(start));
} }
@ -521,7 +521,7 @@ abstract class StylesheetParser extends Parser {
/// [start] should point before the `@`. /// [start] should point before the `@`.
ErrorRule _errorRule(LineScannerState start) { ErrorRule _errorRule(LineScannerState start) {
var expression = _expression(); var expression = _expression();
_expectStatementSeparator(); expectStatementSeparator();
return new ErrorRule(expression, scanner.spanFrom(start)); return new ErrorRule(expression, scanner.spanFrom(start));
} }
@ -532,7 +532,7 @@ abstract class StylesheetParser extends Parser {
var value = _almostAnyValue(); var value = _almostAnyValue();
var optional = scanner.scanChar($exclamation); var optional = scanner.scanChar($exclamation);
if (optional) expectIdentifier("optional"); if (optional) expectIdentifier("optional");
_expectStatementSeparator(); expectStatementSeparator();
return new ExtendRule(value, scanner.spanFrom(start), optional: optional); return new ExtendRule(value, scanner.spanFrom(start), optional: optional);
} }
@ -634,7 +634,7 @@ abstract class StylesheetParser extends Parser {
imports.add(_importArgument()); imports.add(_importArgument());
whitespace(); whitespace();
} while (scanner.scanChar($comma)); } while (scanner.scanChar($comma));
_expectStatementSeparator(); expectStatementSeparator();
return new ImportRule(imports, scanner.spanFrom(start)); return new ImportRule(imports, scanner.spanFrom(start));
} }
@ -731,7 +731,7 @@ abstract class StylesheetParser extends Parser {
children = this.children(_ruleChild); children = this.children(_ruleChild);
_inContentBlock = false; _inContentBlock = false;
} else { } else {
_expectStatementSeparator(); expectStatementSeparator();
} }
return new IncludeRule(name, arguments, scanner.spanFrom(start), return new IncludeRule(name, arguments, scanner.spanFrom(start),
@ -781,7 +781,7 @@ abstract class StylesheetParser extends Parser {
/// [start] should point before the `@`. /// [start] should point before the `@`.
ReturnRule _returnRule(LineScannerState start) { ReturnRule _returnRule(LineScannerState start) {
var expression = _expression(); var expression = _expression();
_expectStatementSeparator(); expectStatementSeparator();
return new ReturnRule(expression, scanner.spanFrom(start)); return new ReturnRule(expression, scanner.spanFrom(start));
} }
@ -800,7 +800,7 @@ abstract class StylesheetParser extends Parser {
/// [start] should point before the `@`. /// [start] should point before the `@`.
WarnRule _warnRule(LineScannerState start) { WarnRule _warnRule(LineScannerState start) {
var expression = _expression(); var expression = _expression();
_expectStatementSeparator(); expectStatementSeparator();
return new WarnRule(expression, scanner.spanFrom(start)); return new WarnRule(expression, scanner.spanFrom(start));
} }
@ -826,7 +826,7 @@ abstract class StylesheetParser extends Parser {
if (next != $exclamation && !atEndOfStatement()) value = _almostAnyValue(); if (next != $exclamation && !atEndOfStatement()) value = _almostAnyValue();
var children = lookingAtChildren() ? this.children(_ruleChild) : null; var children = lookingAtChildren() ? this.children(_ruleChild) : null;
if (children == null) _expectStatementSeparator(); if (children == null) expectStatementSeparator();
return new AtRule(name, scanner.spanFrom(start), return new AtRule(name, scanner.spanFrom(start),
value: value, children: children); value: value, children: children);
@ -2378,18 +2378,6 @@ abstract class StylesheetParser extends Parser {
// ## Utilities // ## Utilities
/// Asserts that the scanner is positioned immediately before a statement
/// separator, or at the end of a list of statements.
///
/// This consumes whitespace, but nothing else, including comments.
void _expectStatementSeparator() {
whitespaceWithoutComments();
if (scanner.isDone) return;
var next = scanner.peekChar();
if (next == $semicolon || next == $rbrace) return;
scanner.expect(';');
}
// ## Abstract Methods // ## Abstract Methods
/// Whether this is parsing the indented syntax. /// Whether this is parsing the indented syntax.
@ -2401,6 +2389,12 @@ abstract class StylesheetParser extends Parser {
/// [scanElse]. /// [scanElse].
int get currentIndentation; int get currentIndentation;
/// Asserts that the scanner is positioned before a statement separator, or at
/// the end of a list of statements.
///
/// This consumes whitespace, but nothing else, including comments.
void expectStatementSeparator();
/// Whether the scanner is positioned at the end of a statement. /// Whether the scanner is positioned at the end of a statement.
bool atEndOfStatement(); bool atEndOfStatement();