Single-char unary operators.

This commit is contained in:
Natalie Weizenbaum 2016-05-24 17:04:16 -07:00
parent 27a819243b
commit 110bdf9efc
6 changed files with 86 additions and 3 deletions

View File

@ -9,6 +9,7 @@ export 'expression/identifier.dart';
export 'expression/interpolation.dart';
export 'expression/list.dart';
export 'expression/string.dart';
export 'expression/unary_operator.dart';
export 'expression/variable.dart';
abstract class Expression implements SassNode {

View File

@ -0,0 +1,38 @@
// 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 'package:source_span/source_span.dart';
import 'package:charcode/charcode.dart';
import '../../../visitor/expression.dart';
import '../expression.dart';
class UnaryOperatorExpression implements Expression {
final UnaryOperator operator;
final Expression operand;
final SourceSpan span;
UnaryOperatorExpression(this.operator, this.operand, {this.span});
/*=T*/ visit/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
visitor.visitUnaryOperatorExpression(this);
String toString() => "${operator.operator}${operand}";
}
class UnaryOperator {
static const plus = const UnaryOperator._("plus", "+");
static const minus = const UnaryOperator._("minus", "-");
static const divide = const UnaryOperator._("divide", "/");
final String name;
final String operator;
const UnaryOperator._(this.name, this.operator);
String toString() => name;
}

View File

@ -355,7 +355,7 @@ class Parser {
if (!_isExpressionStart(_scanner.peekChar())) {
_expectChar($rparen);
return new ListExpression([], ListSeparator.none,
span: _scanner.spanFrom(state));
span: _scanner.spanFrom(start));
}
// TODO: support maps
@ -364,7 +364,19 @@ class Parser {
return result;
}
Expression _unaryOperator() => throw new UnimplementedError();
UnaryOperatorExpression _unaryOperator() {
var start = _scanner.state;
var operator = _unaryOperatorFor(_scanner.readChar());
if (operator == null) {
_scanner.error("Expected unary operator",
position: _scanner.position - 1);
}
var operand = _singleExpression();
return new UnaryOperatorExpression(operator, operand,
span: _scanner.spanFrom(start));
}
Expression _number() => throw new UnimplementedError();
Expression _bracketList() => throw new UnimplementedError();
@ -613,6 +625,15 @@ class Parser {
return 10 + character - $A;
}
UnaryOperator _unaryOperatorFor(int character) {
switch (character) {
case $plus: return UnaryOperator.plus;
case $minus: return UnaryOperator.minus;
case $slash: return UnaryOperator.divide;
default: return null;
}
}
int _escape() {
// See https://drafts.csswg.org/css-syntax-3/#consume-escaped-code-point.

View File

@ -2,8 +2,17 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'value/string.dart';
export 'value/identifier.dart';
export 'value/list.dart';
export 'value/string.dart';
class Value {}
class Value {
// TODO: call the proper stringifying method
Value unaryPlus() => new SassString("+$this");
Value unaryMinus() => new SassString("-$this");
Value unaryDivide() => new SassString("/$this");
}

View File

@ -9,6 +9,11 @@ class ExpressionVisitor<T> {
T visitVariableExpression(VariableExpression node) => null;
T visitUnaryOperatorExpression(UnaryOperatorExpression node) {
node.operand.visit(this);
return null;
}
T visitIdentifierExpression(IdentifierExpression node) {
visitInterpolationExpression(node.text);
return null;

View File

@ -22,6 +22,15 @@ class PerformExpressionVisitor extends ExpressionVisitor<Value> {
throw node.span.message("undefined variable");
}
Value visitUnaryOperatorExpression(UnaryOperatorExpression node) {
switch (node.operator) {
case UnaryOperator.plus: return node.unaryPlus();
case UnaryOperator.minus: return node.unaryMinus();
case UnaryOperator.divide: return node.unaryDivide();
default: throw new StateError("Unknown unary operator ${node.operator}.");
}
}
Identifier visitIdentifierExpression(IdentifierExpression node) =>
new Identifier(visitInterpolationExpression(node.text).text);