InterpolationExpression -> Interpolation

This commit is contained in:
Natalie Weizenbaum 2016-08-26 22:43:10 -07:00 committed by Natalie Weizenbaum
parent 860f761c27
commit 0498e8a95c
15 changed files with 60 additions and 66 deletions

View File

@ -5,13 +5,12 @@
import 'package:source_span/source_span.dart';
import '../../visitor/interface/statement.dart';
import 'expression/interpolation.dart';
import 'statement.dart';
class AtRule implements Statement {
final String name;
final InterpolationExpression value;
final Interpolation value;
final List<Statement> children;

View File

@ -6,11 +6,10 @@ import 'package:source_span/source_span.dart';
import '../../visitor/interface/statement.dart';
import 'expression.dart';
import 'expression/interpolation.dart';
import 'statement.dart';
class Declaration implements Statement {
final InterpolationExpression name;
final Interpolation name;
final Expression value;

View File

@ -9,7 +9,6 @@ export 'expression/boolean.dart';
export 'expression/color.dart';
export 'expression/function.dart';
export 'expression/identifier.dart';
export 'expression/interpolation.dart';
export 'expression/list.dart';
export 'expression/map.dart';
export 'expression/number.dart';

View File

@ -10,7 +10,7 @@ import '../expression.dart';
import '../statement.dart';
class FunctionExpression implements Expression {
final InterpolationExpression name;
final Interpolation name;
final ArgumentInvocation arguments;

View File

@ -6,10 +6,10 @@ import 'package:source_span/source_span.dart';
import '../../../visitor/interface/expression.dart';
import '../expression.dart';
import 'interpolation.dart';
import '../statement.dart';
class IdentifierExpression implements Expression {
final InterpolationExpression text;
final Interpolation text;
FileSpan get span => text.span;

View File

@ -9,7 +9,7 @@ import '../../../interpolation_buffer.dart';
import '../../../util/character.dart';
import '../../../visitor/interface/expression.dart';
import '../expression.dart';
import 'interpolation.dart';
import '../statement.dart';
class StringExpression implements Expression {
/// Interpolation that, when evaluated, produces the semantic content of the
@ -17,7 +17,7 @@ class StringExpression implements Expression {
///
/// Unlike [asInterpolation], escapes are resolved and quotes are not
/// included.
final InterpolationExpression text;
final Interpolation text;
FileSpan get span => text.span;
@ -29,11 +29,11 @@ class StringExpression implements Expression {
/// Interpolation that, when evaluated, produces the syntax of the string.
///
/// Unlike [text], his doesn't resolve escapes and does include quotes.
InterpolationExpression asInterpolation({bool static: false, int quote}) {
Interpolation asInterpolation({bool static: false, int quote}) {
quote ??= _bestQuote();
var buffer = new InterpolationBuffer()..writeCharCode(quote);
for (var value in text.contents) {
if (value is InterpolationExpression) {
if (value is Interpolation) {
buffer.addInterpolation(value);
} else if (value is String) {
for (var i = 0; i < value.length; i++) {

View File

@ -5,11 +5,10 @@
import 'package:source_span/source_span.dart';
import '../../visitor/interface/statement.dart';
import 'expression.dart';
import 'statement.dart';
class ExtendRule implements Statement {
final InterpolationExpression selector;
final Interpolation selector;
final FileSpan span;

View File

@ -4,10 +4,10 @@
import 'package:source_span/source_span.dart';
import '../../../visitor/interface/expression.dart';
import '../expression.dart';
import 'expression.dart';
import 'node.dart';
class InterpolationExpression implements Expression {
class Interpolation implements SassNode {
final List contents;
final FileSpan span;
@ -24,7 +24,7 @@ class InterpolationExpression implements Expression {
/// Returns the plain text before the interpolation, or the empty string.
String get initialPlain => contents.first is String ? contents.first : '';
InterpolationExpression(Iterable/*(String|Expression)*/ contents, {this.span})
Interpolation(Iterable/*(String|Expression)*/ contents, {this.span})
: contents = new List.unmodifiable(contents) {
for (var i = 0; i < this.contents.length; i++) {
if (this.contents[i] is! String && this.contents[i] is! Expression) {
@ -40,9 +40,6 @@ class InterpolationExpression implements Expression {
}
}
/*=T*/ accept/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
visitor.visitInterpolationExpression(this);
String toString() =>
contents.map((value) => value is String ? value : "#{$value}").join();
}

View File

@ -6,15 +6,15 @@ import 'package:source_span/source_span.dart';
import '../../utils.dart';
import '../node.dart';
import 'expression.dart';
import 'node.dart';
import 'statement.dart';
class MediaQuery implements SassNode {
final InterpolationExpression modifier;
final Interpolation modifier;
final InterpolationExpression type;
final Interpolation type;
final List<InterpolationExpression> features;
final List<Interpolation> features;
FileSpan get span {
var components = <AstNode>[];
@ -25,12 +25,12 @@ class MediaQuery implements SassNode {
}
MediaQuery(this.type, {this.modifier,
Iterable<InterpolationExpression> features})
Iterable<Interpolation> features})
: features = features == null
? const []
: new List.unmodifiable(features);
MediaQuery.condition(Iterable<InterpolationExpression> features,
MediaQuery.condition(Iterable<Interpolation> features,
{this.modifier, this.type})
: features = new List.unmodifiable(features);

View File

@ -13,6 +13,7 @@ export 'comment.dart';
export 'declaration.dart';
export 'extend_rule.dart';
export 'function_declaration.dart';
export 'interpolation.dart';
export 'media_query.dart';
export 'media_rule.dart';
export 'return.dart';

View File

@ -5,11 +5,10 @@
import 'package:source_span/source_span.dart';
import '../../visitor/interface/statement.dart';
import 'expression/interpolation.dart';
import 'statement.dart';
class StyleRule implements Statement {
final InterpolationExpression selector;
final Interpolation selector;
final List<Statement> children;

View File

@ -5,6 +5,7 @@
import 'package:source_span/source_span.dart';
import 'ast/sass/expression.dart';
import 'ast/sass/statement.dart';
class InterpolationBuffer implements StringSink {
final _text = new StringBuffer();
@ -29,7 +30,7 @@ class InterpolationBuffer implements StringSink {
_contents.add(expression);
}
void addInterpolation(InterpolationExpression expression) {
void addInterpolation(Interpolation expression) {
if (expression.contents.isEmpty) return;
var toAdd = expression.contents;
@ -50,10 +51,10 @@ class InterpolationBuffer implements StringSink {
_text.clear();
}
InterpolationExpression interpolation([FileSpan span]) {
Interpolation interpolation([FileSpan span]) {
var contents = _contents.toList();
if (_text.isNotEmpty) contents.add(_text.toString());
return new InterpolationExpression(contents, span: span);
return new Interpolation(contents, span: span);
}
String toString() => "${_contents.join('')}$_text";

View File

@ -132,7 +132,7 @@ class Parser {
span: _scanner.spanFrom(start));
}
InterpolationExpression value;
Interpolation value;
var next = _scanner.peekChar();
if (next != $exclamation && next != $semicolon && next != $lbrace &&
next != $rbrace && next != null) {
@ -213,7 +213,7 @@ class Parser {
Expression _declarationExpression() {
if (_scanner.peekChar() == $lbrace) {
return new StringExpression(
new InterpolationExpression([], span: _scanner.emptySpan));
new Interpolation([], span: _scanner.emptySpan));
}
return _expression();
@ -762,7 +762,7 @@ class Parser {
return new SassColor.rgb(red, green, blue);
}
bool _isHexColor(InterpolationExpression interpolation) {
bool _isHexColor(Interpolation interpolation) {
var plain = interpolation.asPlain;
if (plain == null) return false;
if (plain.length != 3 && plain.length != 6) return false;
@ -791,7 +791,7 @@ class Parser {
///
/// This respects string boundaries and supports interpolation. Once this
/// interpolation is evaluated, it's expected to be re-parsed.
InterpolationExpression _almostAnyValue() {
Interpolation _almostAnyValue() {
var start = _scanner.state;
var buffer = new InterpolationBuffer();
@ -951,7 +951,7 @@ class Parser {
buffer.interpolation(_scanner.spanFrom(start)));
}
InterpolationExpression _interpolatedIdentifier() {
Interpolation _interpolatedIdentifier() {
var start = _scanner.state;
var buffer = new InterpolationBuffer();
@ -1312,8 +1312,8 @@ class Parser {
}
MediaQuery _mediaQuery() {
InterpolationExpression modifier;
InterpolationExpression type;
Interpolation modifier;
Interpolation type;
if (_scanner.peekChar() != $lparen) {
var identifier1 = _interpolatedIdentifier();
_ignoreComments();
@ -1345,7 +1345,7 @@ class Parser {
// We've consumed either `IDENTIFIER "and"` or
// `IDENTIFIER IDENTIFIER "and"`.
var features = <InterpolationExpression>[];
var features = <Interpolation>[];
do {
_ignoreComments();
features.add(_mediaExpression());
@ -1358,10 +1358,10 @@ class Parser {
}
}
InterpolationExpression _mediaExpression() {
Interpolation _mediaExpression() {
if (_scanner.peekChar() == $hash) {
var interpolation = _singleInterpolation();
return new InterpolationExpression([interpolation],
return new Interpolation([interpolation],
span: interpolation.span);
}

View File

@ -3,6 +3,7 @@
// https://opensource.org/licenses/MIT.
import '../../ast/sass/expression.dart';
import '../../ast/sass/statement.dart';
abstract class ExpressionVisitor<T> {
T visitVariableExpression(VariableExpression node) => null;
@ -16,7 +17,7 @@ abstract class ExpressionVisitor<T> {
}
T visitIdentifierExpression(IdentifierExpression node) {
visitInterpolationExpression(node.text);
_visitInterpolation(node.text);
return null;
}
@ -48,14 +49,13 @@ abstract class ExpressionVisitor<T> {
}
T visitStringExpression(StringExpression node) {
visitInterpolationExpression(node.text);
_visitInterpolation(node.text);
return null;
}
T visitInterpolationExpression(InterpolationExpression node) {
void _visitInterpolation(Interpolation node) {
for (var value in node.contents) {
if (value is Expression) value.accept(this);
}
return null;
}
}

View File

@ -65,7 +65,7 @@ class PerformVisitor extends StatementVisitor
}
void visitDeclaration(Declaration node) {
var name = _performInterpolation(node.name);
var name = _interpolationToValue(node.name);
if (_declarationName != null) {
name = new CssValue("$_declarationName-${name.value}", span: name.span);
}
@ -87,7 +87,7 @@ class PerformVisitor extends StatementVisitor
}
void visitExtendRule(ExtendRule node) {
var targetText = _performInterpolation(node.selector);
var targetText = _interpolationToValue(node.selector);
// TODO: recontextualize parse errors.
// TODO: disallow parent selectors.
@ -98,7 +98,7 @@ class PerformVisitor extends StatementVisitor
void visitAtRule(AtRule node) {
var value = node.value == null
? null
: _performInterpolation(node.value, trim: true);
: _interpolationToValue(node.value, trim: true);
if (node.children == null) {
_parent.addChild(new CssAtRule(node.name, value: value, span: node.span));
@ -165,14 +165,14 @@ class PerformVisitor extends StatementVisitor
CssMediaQuery _visitMediaQuery(MediaQuery query) {
var modifier = query.modifier == null
? null
: _performInterpolation(query.modifier);
: _interpolationToValue(query.modifier);
var type = query.type == null
? null
: _performInterpolation(query.type);
: _interpolationToValue(query.type);
var features = query.features
.map((feature) => _performInterpolation(feature));
.map((feature) => _interpolationToValue(feature));
if (type == null) return new CssMediaQuery.condition(features);
return new CssMediaQuery(type, modifier: modifier, features: features);
@ -181,7 +181,7 @@ class PerformVisitor extends StatementVisitor
Value visitReturn(Return node) => node.expression.accept(this);
void visitStyleRule(StyleRule node) {
var selectorText = _performInterpolation(node.selector, trim: true);
var selectorText = _interpolationToValue(node.selector, trim: true);
var parsedSelector = new Parser(selectorText.value).parseSelector();
// TOOD: catch errors and point them to node.selector
@ -227,7 +227,7 @@ class PerformVisitor extends StatementVisitor
}
SassIdentifier visitIdentifierExpression(IdentifierExpression node) =>
new SassIdentifier(visitInterpolationExpression(node.text).text);
new SassIdentifier(_performInterpolation(node.text));
SassBoolean visitBooleanExpression(BooleanExpression node) =>
new SassBoolean(node.value);
@ -237,13 +237,6 @@ class PerformVisitor extends StatementVisitor
SassColor visitColorExpression(ColorExpression node) => node.value;
SassString visitInterpolationExpression(InterpolationExpression node) {
return new SassString(node.contents.map((value) {
if (value is String) return value;
return (value as Expression).accept(this);
}).join());
}
SassList visitListExpression(ListExpression node) => new SassList(
node.contents.map((expression) => expression.accept(this)),
node.separator,
@ -276,7 +269,7 @@ class PerformVisitor extends StatementVisitor
"Plain CSS functions don't support keyword arguments.");
}
var name = node.name.accept(this);
var name = _performInterpolation(node.name);
var arguments = node.arguments.positional
.map((expression) => expression.accept(this)).toList();
// TODO: if rest is an arglist that has keywords, error out.
@ -381,7 +374,7 @@ class PerformVisitor extends StatementVisitor
}
SassString visitStringExpression(StringExpression node) =>
visitInterpolationExpression(node.text);
new SassString(_performInterpolation(node.text));
// ## Utilities
@ -393,13 +386,20 @@ class PerformVisitor extends StatementVisitor
return result;
}
CssValue<String> _performInterpolation(
InterpolationExpression interpolation, {bool trim: false}) {
var result = visitInterpolationExpression(interpolation).text;
CssValue<String> _interpolationToValue(
Interpolation interpolation, {bool trim: false}) {
var result = _performInterpolation(interpolation);
return new CssValue(trim ? result.trim() : result,
span: interpolation.span);
}
String _performInterpolation(Interpolation interpolation) {
return interpolation.contents.map((value) {
if (value is String) return value;
return (value as Expression).accept(this);
}).join();
}
CssValue<Value> _performExpression(Expression expression) =>
new CssValue(expression.accept(this), span: expression.span);