Присваивание как выражение

This commit is contained in:
Victor 2016-02-13 18:46:41 +02:00
parent cb07629f06
commit 802927e06e
8 changed files with 59 additions and 32 deletions

View File

@ -218,3 +218,6 @@ def funcWithOptionalArgs(str, count = 5, prefix = "<", suffix = ">") = prefix +
println funcWithOptionalArgs("*")
println funcWithOptionalArgs("+", 2)
println funcWithOptionalArgs("*", 10, "<!")
v1 = v2 = v3 = v4 = 5
echo(v1, v2, v3, v4)

View File

@ -87,9 +87,6 @@ public final class Parser {
if (match(TokenType.MATCH)) {
return new ExprStatement(match());
}
if (match(TokenType.EXTRACT)) {
return destructuringAssignment();
}
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
return new ExprStatement(function(qualifiedName()));
}
@ -97,17 +94,12 @@ public final class Parser {
}
private Statement assignmentStatement() {
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.EQ)) {
final String variable = consume(TokenType.WORD).getText();
consume(TokenType.EQ);
return new AssignmentStatement(variable, expression());
if (match(TokenType.EXTRACT)) {
return destructuringAssignment();
}
final Expression qualifiedNameExpr = qualifiedName();
if (lookMatch(0, TokenType.EQ) && (qualifiedNameExpr instanceof ContainerAccessExpression)) {
consume(TokenType.EQ);
final ContainerAccessExpression containerExpr = (ContainerAccessExpression) qualifiedNameExpr;
return new ContainerAssignmentStatement(containerExpr, expression());
final Expression assignment = assignmentStrict();
if (assignment != null) {
return new ExprStatement(assignment);
}
throw new ParseException("Unknown statement: " + get(0));
}
@ -330,9 +322,36 @@ public final class Parser {
}
private Expression expression() {
return assignment();
}
private Expression assignment() {
final Expression assignment = assignmentStrict();
if (assignment != null) {
return assignment;
}
return ternary();
}
private Expression assignmentStrict() {
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.EQ)) {
final String variable = consume(TokenType.WORD).getText();
consume(TokenType.EQ);
return new AssignmentExpression(variable, expression());
}
final int position = pos;
final Expression qualifiedNameExpr = qualifiedName();
if (lookMatch(0, TokenType.EQ) && (qualifiedNameExpr instanceof ContainerAccessExpression)) {
consume(TokenType.EQ);
final ContainerAccessExpression containerExpr = (ContainerAccessExpression) qualifiedNameExpr;
return new ContainerAssignmentExpression(containerExpr, expression());
}
pos = position;
return null;
}
private Expression ternary() {
Expression result = logicalOr();

View File

@ -7,20 +7,21 @@ import com.annimon.ownlang.lib.Variables;
*
* @author aNNiMON
*/
public final class AssignmentStatement implements Statement {
public final class AssignmentExpression implements Expression {
public final String variable;
public final Expression expression;
public AssignmentStatement(String variable, Expression expression) {
public AssignmentExpression(String variable, Expression expression) {
this.variable = variable;
this.expression = expression;
}
@Override
public void execute() {
public Value eval() {
final Value result = expression.eval();
Variables.set(variable, result);
return result;
}
@Override

View File

@ -10,29 +10,33 @@ import com.annimon.ownlang.lib.Value;
*
* @author aNNiMON
*/
public final class ContainerAssignmentStatement implements Statement {
public final class ContainerAssignmentExpression implements Expression {
public final ContainerAccessExpression containerExpr;
public final Expression expression;
public ContainerAssignmentStatement(ContainerAccessExpression array, Expression expression) {
public ContainerAssignmentExpression(ContainerAccessExpression array, Expression expression) {
this.containerExpr = array;
this.expression = expression;
}
@Override
public void execute() {
public Value eval() {
final Value container = containerExpr.getContainer();
final Value lastIndex = containerExpr.lastIndex();
switch (container.type()) {
case Types.ARRAY:
case Types.ARRAY: {
final Value result = expression.eval();
final int arrayIndex = (int) lastIndex.asNumber();
((ArrayValue) container).set(arrayIndex, expression.eval());
return;
((ArrayValue) container).set(arrayIndex, result);
return result;
}
case Types.MAP:
((MapValue) container).set(lastIndex, expression.eval());
return;
case Types.MAP: {
final Value result = expression.eval();
((MapValue) container).set(lastIndex, result);
return result;
}
default:
throw new TypeException("Array or map expected. Got " + container.type());

View File

@ -7,13 +7,13 @@ package com.annimon.ownlang.parser.ast;
public interface Visitor {
void visit(ArrayExpression s);
void visit(AssignmentStatement s);
void visit(AssignmentExpression s);
void visit(BinaryExpression s);
void visit(BlockStatement s);
void visit(BreakStatement s);
void visit(ConditionalExpression s);
void visit(ContainerAccessExpression s);
void visit(ContainerAssignmentStatement s);
void visit(ContainerAssignmentExpression s);
void visit(ContinueStatement s);
void visit(DoWhileStatement s);
void visit(DestructuringAssignmentStatement s);

View File

@ -18,7 +18,7 @@ public abstract class AbstractVisitor implements Visitor {
}
@Override
public void visit(AssignmentStatement s) {
public void visit(AssignmentExpression s) {
s.expression.accept(this);
}
@ -53,7 +53,7 @@ public abstract class AbstractVisitor implements Visitor {
}
@Override
public void visit(ContainerAssignmentStatement s) {
public void visit(ContainerAssignmentExpression s) {
s.containerExpr.accept(this);
s.expression.accept(this);
}

View File

@ -10,7 +10,7 @@ import com.annimon.ownlang.parser.ast.*;
public final class AssignValidator extends AbstractVisitor {
@Override
public void visit(AssignmentStatement s) {
public void visit(AssignmentExpression s) {
super.visit(s);
if (Variables.isExists(s.variable)) {
throw new RuntimeException("Cannot assign value to constant");

View File

@ -9,7 +9,7 @@ import com.annimon.ownlang.parser.ast.*;
public final class VariablePrinter extends AbstractVisitor {
@Override
public void visit(AssignmentStatement s) {
public void visit(AssignmentExpression s) {
super.visit(s);
System.out.println(s.variable);
}