mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44: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("*")
|
||||||
println funcWithOptionalArgs("+", 2)
|
println funcWithOptionalArgs("+", 2)
|
||||||
println funcWithOptionalArgs("*", 10, "<!")
|
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)) {
|
if (match(TokenType.MATCH)) {
|
||||||
return new ExprStatement(match());
|
return new ExprStatement(match());
|
||||||
}
|
}
|
||||||
if (match(TokenType.EXTRACT)) {
|
|
||||||
return destructuringAssignment();
|
|
||||||
}
|
|
||||||
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
|
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
|
||||||
return new ExprStatement(function(qualifiedName()));
|
return new ExprStatement(function(qualifiedName()));
|
||||||
}
|
}
|
||||||
@ -97,17 +94,12 @@ public final class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Statement assignmentStatement() {
|
private Statement assignmentStatement() {
|
||||||
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.EQ)) {
|
if (match(TokenType.EXTRACT)) {
|
||||||
final String variable = consume(TokenType.WORD).getText();
|
return destructuringAssignment();
|
||||||
consume(TokenType.EQ);
|
|
||||||
return new AssignmentStatement(variable, expression());
|
|
||||||
}
|
}
|
||||||
|
final Expression assignment = assignmentStrict();
|
||||||
final Expression qualifiedNameExpr = qualifiedName();
|
if (assignment != null) {
|
||||||
if (lookMatch(0, TokenType.EQ) && (qualifiedNameExpr instanceof ContainerAccessExpression)) {
|
return new ExprStatement(assignment);
|
||||||
consume(TokenType.EQ);
|
|
||||||
final ContainerAccessExpression containerExpr = (ContainerAccessExpression) qualifiedNameExpr;
|
|
||||||
return new ContainerAssignmentStatement(containerExpr, expression());
|
|
||||||
}
|
}
|
||||||
throw new ParseException("Unknown statement: " + get(0));
|
throw new ParseException("Unknown statement: " + get(0));
|
||||||
}
|
}
|
||||||
@ -330,9 +322,36 @@ public final class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Expression expression() {
|
private Expression expression() {
|
||||||
|
return assignment();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Expression assignment() {
|
||||||
|
final Expression assignment = assignmentStrict();
|
||||||
|
if (assignment != null) {
|
||||||
|
return assignment;
|
||||||
|
}
|
||||||
return ternary();
|
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() {
|
private Expression ternary() {
|
||||||
Expression result = logicalOr();
|
Expression result = logicalOr();
|
||||||
|
|
||||||
|
@ -7,20 +7,21 @@ import com.annimon.ownlang.lib.Variables;
|
|||||||
*
|
*
|
||||||
* @author aNNiMON
|
* @author aNNiMON
|
||||||
*/
|
*/
|
||||||
public final class AssignmentStatement implements Statement {
|
public final class AssignmentExpression implements Expression {
|
||||||
|
|
||||||
public final String variable;
|
public final String variable;
|
||||||
public final Expression expression;
|
public final Expression expression;
|
||||||
|
|
||||||
public AssignmentStatement(String variable, Expression expression) {
|
public AssignmentExpression(String variable, Expression expression) {
|
||||||
this.variable = variable;
|
this.variable = variable;
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public Value eval() {
|
||||||
final Value result = expression.eval();
|
final Value result = expression.eval();
|
||||||
Variables.set(variable, result);
|
Variables.set(variable, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -10,29 +10,33 @@ import com.annimon.ownlang.lib.Value;
|
|||||||
*
|
*
|
||||||
* @author aNNiMON
|
* @author aNNiMON
|
||||||
*/
|
*/
|
||||||
public final class ContainerAssignmentStatement implements Statement {
|
public final class ContainerAssignmentExpression implements Expression {
|
||||||
|
|
||||||
public final ContainerAccessExpression containerExpr;
|
public final ContainerAccessExpression containerExpr;
|
||||||
public final Expression expression;
|
public final Expression expression;
|
||||||
|
|
||||||
public ContainerAssignmentStatement(ContainerAccessExpression array, Expression expression) {
|
public ContainerAssignmentExpression(ContainerAccessExpression array, Expression expression) {
|
||||||
this.containerExpr = array;
|
this.containerExpr = array;
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public Value eval() {
|
||||||
final Value container = containerExpr.getContainer();
|
final Value container = containerExpr.getContainer();
|
||||||
final Value lastIndex = containerExpr.lastIndex();
|
final Value lastIndex = containerExpr.lastIndex();
|
||||||
switch (container.type()) {
|
switch (container.type()) {
|
||||||
case Types.ARRAY:
|
case Types.ARRAY: {
|
||||||
|
final Value result = expression.eval();
|
||||||
final int arrayIndex = (int) lastIndex.asNumber();
|
final int arrayIndex = (int) lastIndex.asNumber();
|
||||||
((ArrayValue) container).set(arrayIndex, expression.eval());
|
((ArrayValue) container).set(arrayIndex, result);
|
||||||
return;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
case Types.MAP:
|
case Types.MAP: {
|
||||||
((MapValue) container).set(lastIndex, expression.eval());
|
final Value result = expression.eval();
|
||||||
return;
|
((MapValue) container).set(lastIndex, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new TypeException("Array or map expected. Got " + container.type());
|
throw new TypeException("Array or map expected. Got " + container.type());
|
@ -7,13 +7,13 @@ package com.annimon.ownlang.parser.ast;
|
|||||||
public interface Visitor {
|
public interface Visitor {
|
||||||
|
|
||||||
void visit(ArrayExpression s);
|
void visit(ArrayExpression s);
|
||||||
void visit(AssignmentStatement s);
|
void visit(AssignmentExpression s);
|
||||||
void visit(BinaryExpression s);
|
void visit(BinaryExpression s);
|
||||||
void visit(BlockStatement s);
|
void visit(BlockStatement s);
|
||||||
void visit(BreakStatement s);
|
void visit(BreakStatement s);
|
||||||
void visit(ConditionalExpression s);
|
void visit(ConditionalExpression s);
|
||||||
void visit(ContainerAccessExpression s);
|
void visit(ContainerAccessExpression s);
|
||||||
void visit(ContainerAssignmentStatement s);
|
void visit(ContainerAssignmentExpression s);
|
||||||
void visit(ContinueStatement s);
|
void visit(ContinueStatement s);
|
||||||
void visit(DoWhileStatement s);
|
void visit(DoWhileStatement s);
|
||||||
void visit(DestructuringAssignmentStatement s);
|
void visit(DestructuringAssignmentStatement s);
|
||||||
|
@ -18,7 +18,7 @@ public abstract class AbstractVisitor implements Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignmentStatement s) {
|
public void visit(AssignmentExpression s) {
|
||||||
s.expression.accept(this);
|
s.expression.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public abstract class AbstractVisitor implements Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ContainerAssignmentStatement s) {
|
public void visit(ContainerAssignmentExpression s) {
|
||||||
s.containerExpr.accept(this);
|
s.containerExpr.accept(this);
|
||||||
s.expression.accept(this);
|
s.expression.accept(this);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import com.annimon.ownlang.parser.ast.*;
|
|||||||
public final class AssignValidator extends AbstractVisitor {
|
public final class AssignValidator extends AbstractVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignmentStatement s) {
|
public void visit(AssignmentExpression s) {
|
||||||
super.visit(s);
|
super.visit(s);
|
||||||
if (Variables.isExists(s.variable)) {
|
if (Variables.isExists(s.variable)) {
|
||||||
throw new RuntimeException("Cannot assign value to constant");
|
throw new RuntimeException("Cannot assign value to constant");
|
||||||
|
@ -9,7 +9,7 @@ import com.annimon.ownlang.parser.ast.*;
|
|||||||
public final class VariablePrinter extends AbstractVisitor {
|
public final class VariablePrinter extends AbstractVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignmentStatement s) {
|
public void visit(AssignmentExpression s) {
|
||||||
super.visit(s);
|
super.visit(s);
|
||||||
System.out.println(s.variable);
|
System.out.println(s.variable);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user