mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-30 04:39:03 +01:00
Add an explicit distinction between statements and expressions.
This commit is contained in:
parent
7cc74b7c17
commit
f8cfb305a9
@ -4,10 +4,10 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../visitor.dart';
|
||||
import 'node.dart';
|
||||
import '../visitor/statement.dart';
|
||||
import 'statement.dart';
|
||||
|
||||
class CommentNode implements AstNode {
|
||||
class CommentNode implements Statement {
|
||||
final String text;
|
||||
|
||||
final bool isSilent;
|
||||
@ -18,7 +18,7 @@ class CommentNode implements AstNode {
|
||||
CommentNode(this.text, {bool silent, this.span})
|
||||
: isSilent = silent;
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(StatementVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitComment(this);
|
||||
|
||||
String toString() => text;
|
||||
|
@ -4,12 +4,12 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../visitor.dart';
|
||||
import '../visitor/statement.dart';
|
||||
import 'expression.dart';
|
||||
import 'expression/interpolation.dart';
|
||||
import 'node.dart';
|
||||
import 'statement.dart';
|
||||
|
||||
class DeclarationNode implements AstNode {
|
||||
class DeclarationNode implements Statement {
|
||||
final InterpolationExpression name;
|
||||
|
||||
final Expression value;
|
||||
@ -18,7 +18,7 @@ class DeclarationNode implements AstNode {
|
||||
|
||||
DeclarationNode(this.name, this.value, {this.span});
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(StatementVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitDeclaration(this);
|
||||
|
||||
String toString() => "$name: $value;";
|
||||
|
@ -2,6 +2,9 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import '../visitor/expression.dart';
|
||||
import 'node.dart';
|
||||
|
||||
abstract class Expression implements AstNode {}
|
||||
abstract class Expression implements AstNode {
|
||||
/*=T*/ visit/*<T>*/(ExpressionVisitor/*<T>*/ visitor);
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../visitor.dart';
|
||||
import '../../visitor/expression.dart';
|
||||
import '../expression.dart';
|
||||
import 'interpolation.dart';
|
||||
|
||||
@ -15,7 +15,7 @@ class IdentifierExpression implements Expression {
|
||||
|
||||
IdentifierExpression(this.text);
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitIdentifierExpression(this);
|
||||
|
||||
String toString() => text.toString();
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../visitor.dart';
|
||||
import '../../visitor/expression.dart';
|
||||
import '../expression.dart';
|
||||
|
||||
class InterpolationExpression implements Expression {
|
||||
@ -40,7 +40,7 @@ class InterpolationExpression implements Expression {
|
||||
}
|
||||
}
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitInterpolationExpression(this);
|
||||
|
||||
String toString() =>
|
||||
|
@ -5,7 +5,7 @@
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../utils.dart';
|
||||
import '../../visitor.dart';
|
||||
import '../../visitor/expression.dart';
|
||||
import '../expression.dart';
|
||||
|
||||
class ListExpression implements Expression {
|
||||
@ -23,7 +23,7 @@ class ListExpression implements Expression {
|
||||
: contents = contents,
|
||||
span = span ?? spanForList(contents);
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitListExpression(this);
|
||||
|
||||
// TODO: parenthesize nested lists if necessary
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../visitor.dart';
|
||||
import '../../visitor/expression.dart';
|
||||
import '../expression.dart';
|
||||
import 'interpolation.dart';
|
||||
|
||||
@ -23,7 +23,7 @@ class StringExpression implements Expression {
|
||||
/// Unlike [text], his doesn't resolve escapes and does include quotes.
|
||||
InterpolationExpression get asInterpolation => throw new UnimplementedError();
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitStringExpression(this);
|
||||
|
||||
StringExpression(this.text);
|
||||
|
@ -4,10 +4,6 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../visitor.dart';
|
||||
|
||||
abstract class AstNode {
|
||||
SourceSpan get span;
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor);
|
||||
}
|
10
lib/src/ast/statement.dart
Normal file
10
lib/src/ast/statement.dart
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import '../visitor/statement.dart';
|
||||
import 'node.dart';
|
||||
|
||||
abstract class Statement implements AstNode {
|
||||
/*=T*/ visit/*<T>*/(StatementVisitor/*<T>*/ visitor);
|
||||
}
|
@ -4,23 +4,23 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../visitor.dart';
|
||||
import '../visitor/statement.dart';
|
||||
import 'expression/interpolation.dart';
|
||||
import 'node.dart';
|
||||
import 'statement.dart';
|
||||
|
||||
class StyleRuleNode implements AstNode {
|
||||
class StyleRuleNode implements Statement {
|
||||
final InterpolationExpression selector;
|
||||
|
||||
final List<AstNode> children;
|
||||
final List<Statement> children;
|
||||
|
||||
final SourceSpan span;
|
||||
|
||||
// TODO: validate that children only contains variable, at-rule, declaration,
|
||||
// or style nodes?
|
||||
StyleRuleNode(this.selector, Iterable<AstNode> children, {this.span})
|
||||
StyleRuleNode(this.selector, Iterable<Statement> children, {this.span})
|
||||
: children = new List.unmodifiable(children);
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(StatementVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitStyleRule(this);
|
||||
|
||||
String toString() => "$selector {${children.join(" ")}}";
|
||||
|
@ -4,18 +4,18 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../visitor.dart';
|
||||
import 'node.dart';
|
||||
import '../visitor/statement.dart';
|
||||
import 'statement.dart';
|
||||
|
||||
class StylesheetNode implements AstNode {
|
||||
final List<AstNode> children;
|
||||
class StylesheetNode implements Statement {
|
||||
final List<Statement> children;
|
||||
|
||||
final SourceSpan span;
|
||||
|
||||
StylesheetNode(Iterable<AstNode> children, {this.span})
|
||||
StylesheetNode(Iterable<Statement> children, {this.span})
|
||||
: children = new List.unmodifiable(children);
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(StatementVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitStylesheet(this);
|
||||
|
||||
String toString() => children.map((child) => "$child").join(" ");
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../visitor.dart';
|
||||
import '../visitor/statement.dart';
|
||||
import 'expression.dart';
|
||||
import 'node.dart';
|
||||
import 'statement.dart';
|
||||
|
||||
class VariableDeclarationNode implements AstNode {
|
||||
class VariableDeclarationNode implements Statement {
|
||||
final String name;
|
||||
|
||||
final Expression expression;
|
||||
@ -24,7 +24,7 @@ class VariableDeclarationNode implements AstNode {
|
||||
: isGuarded = guarded,
|
||||
isGlobal = global;
|
||||
|
||||
/*=T*/ visit/*<T>*/(AstVisitor/*<T>*/ visitor) =>
|
||||
/*=T*/ visit/*<T>*/(StatementVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitVariableDeclaration(this);
|
||||
|
||||
String toString() => "\$$name: $expression;";
|
||||
|
@ -5,7 +5,6 @@
|
||||
import 'package:charcode/charcode.dart';
|
||||
import 'package:string_scanner/string_scanner.dart';
|
||||
|
||||
import 'ast/node.dart';
|
||||
import 'ast/comment.dart';
|
||||
import 'ast/declaration.dart';
|
||||
import 'ast/expression.dart';
|
||||
@ -13,6 +12,8 @@ import 'ast/expression/identifier.dart';
|
||||
import 'ast/expression/interpolation.dart';
|
||||
import 'ast/expression/list.dart';
|
||||
import 'ast/expression/string.dart';
|
||||
import 'ast/node.dart';
|
||||
import 'ast/statement.dart';
|
||||
import 'ast/style_rule.dart';
|
||||
import 'ast/stylesheet.dart';
|
||||
import 'ast/variable_declaration.dart';
|
||||
@ -36,7 +37,7 @@ class Parser {
|
||||
|
||||
StylesheetNode parse() {
|
||||
var start = _scanner.state;
|
||||
var children = <AstNode>[];
|
||||
var children = <Statement>[];
|
||||
do {
|
||||
children.addAll(_comments());
|
||||
switch (_scanner.peekChar()) {
|
||||
@ -103,9 +104,9 @@ class Parser {
|
||||
span: _scanner.spanFrom(start));
|
||||
}
|
||||
|
||||
List<AstNode> _styleRuleChildren() {
|
||||
List<Statement> _styleRuleChildren() {
|
||||
_expectChar($lbrace);
|
||||
var children = <AstNode>[];
|
||||
var children = <Statement>[];
|
||||
do {
|
||||
children.addAll(_comments());
|
||||
switch (_scanner.peekChar()) {
|
||||
|
@ -2,20 +2,24 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'ast/node.dart';
|
||||
import 'ast/comment.dart';
|
||||
import 'ast/declaration.dart';
|
||||
import 'ast/expression.dart';
|
||||
import 'ast/expression/identifier.dart';
|
||||
import 'ast/expression/interpolation.dart';
|
||||
import 'ast/expression/list.dart';
|
||||
import 'ast/expression/string.dart';
|
||||
import 'ast/node.dart';
|
||||
import 'ast/statement.dart';
|
||||
import 'ast/style_rule.dart';
|
||||
import 'ast/stylesheet.dart';
|
||||
import 'ast/variable_declaration.dart';
|
||||
import 'visitor/expression.dart';
|
||||
import 'visitor/statement.dart';
|
||||
|
||||
class AstVisitor<T> {
|
||||
T visit(AstNode node) => node.visit(this);
|
||||
class AstVisitor<T> extends ExpressionVisitor<T>
|
||||
implements StatementVisitor<T> {
|
||||
T visit(AstNode node) {
|
||||
if (node is Statement) return node.visit(this);
|
||||
if (node is Expression) return node.visit(this);
|
||||
throw new ArgumentError("Unknown node type $node.");
|
||||
}
|
||||
|
||||
T visitComment(CommentNode node) => null;
|
||||
|
||||
@ -44,28 +48,4 @@ class AstVisitor<T> {
|
||||
node.expression.visit(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
T visitIdentifierExpression(IdentifierExpression node) {
|
||||
visitInterpolationExpression(node.text);
|
||||
return null;
|
||||
}
|
||||
|
||||
T visitInterpolationExpression(InterpolationExpression node) {
|
||||
for (var value in node.contents) {
|
||||
if (value is Expression) value.visit(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
T visitListExpression(ListExpression node) {
|
||||
for (var expression in node.contents) {
|
||||
expression.visit(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
T visitStringExpression(StringExpression node) {
|
||||
visitInterpolationExpression(node.text);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
37
lib/src/visitor/expression.dart
Normal file
37
lib/src/visitor/expression.dart
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import '../ast/expression.dart';
|
||||
import '../ast/expression/identifier.dart';
|
||||
import '../ast/expression/interpolation.dart';
|
||||
import '../ast/expression/list.dart';
|
||||
import '../ast/expression/string.dart';
|
||||
|
||||
class ExpressionVisitor<T> {
|
||||
T visit(Expression expression) => expression.visit(this);
|
||||
|
||||
T visitIdentifierExpression(IdentifierExpression node) {
|
||||
visitInterpolationExpression(node.text);
|
||||
return null;
|
||||
}
|
||||
|
||||
T visitInterpolationExpression(InterpolationExpression node) {
|
||||
for (var value in node.contents) {
|
||||
if (value is Expression) value.visit(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
T visitListExpression(ListExpression node) {
|
||||
for (var expression in node.contents) {
|
||||
expression.visit(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
T visitStringExpression(StringExpression node) {
|
||||
visitInterpolationExpression(node.text);
|
||||
return null;
|
||||
}
|
||||
}
|
32
lib/src/visitor/statement.dart
Normal file
32
lib/src/visitor/statement.dart
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import '../ast/comment.dart';
|
||||
import '../ast/declaration.dart';
|
||||
import '../ast/statement.dart';
|
||||
import '../ast/style_rule.dart';
|
||||
import '../ast/stylesheet.dart';
|
||||
import '../ast/variable_declaration.dart';
|
||||
|
||||
class StatementVisitor<T> {
|
||||
T visit(Statement node) => node.visit(this);
|
||||
|
||||
T visitComment(CommentNode node) => null;
|
||||
T visitDeclaration(DeclarationNode node) => null;
|
||||
T visitVariableDeclaration(VariableDeclarationNode node) => null;
|
||||
|
||||
T visitStyleRule(StyleRuleNode node) {
|
||||
for (var child in node.children) {
|
||||
child.visit(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
T visitStylesheet(StylesheetNode node) {
|
||||
for (var child in node.children) {
|
||||
child.visit(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user