mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Присваивание как выражение
This commit is contained in:
parent
cb07629f06
commit
802927e06e
@ -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)
|
@ -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();
|
||||
|
||||
|
@ -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
|
@ -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());
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user