Урок 11. Одномерные массивы

This commit is contained in:
Victor 2015-06-23 17:23:32 +03:00
parent 207f91a228
commit c678d5d5e1
10 changed files with 209 additions and 6 deletions

View File

@ -48,4 +48,13 @@ def sum(a,b) {
name(1,"text")
print sum(10, 15)
print a
print a + "\n"
arr = [1, "text", sum(10, 15), [], ["text", [90, [7 + 6, [50]]]]]
print arr + "\n"
arr[0] = arr[0] + 1000 + arr[2]
print arr + "\n"
arr4 = arr[4]
print arr4 + "\n"
arr41 = arr4[1]
print arr41 + "\n"

View File

@ -0,0 +1,48 @@
package com.annimon.ownlang.lib;
import java.util.Arrays;
/**
*
* @author aNNiMON
*/
public final class ArrayValue implements Value {
private final Value[] elements;
public ArrayValue(int size) {
this.elements = new Value[size];
}
public ArrayValue(Value[] elements) {
this.elements = new Value[elements.length];
System.arraycopy(elements, 0, this.elements, 0, elements.length);
}
public ArrayValue(ArrayValue array) {
this(array.elements);
}
public Value get(int index) {
return elements[index];
}
public void set(int index, Value value) {
elements[index] = value;
}
@Override
public double asNumber() {
throw new RuntimeException("Cannot cast array to number");
}
@Override
public String asString() {
return Arrays.toString(elements);
}
@Override
public String toString() {
return asString();
}
}

View File

@ -31,6 +31,9 @@ public final class Functions {
}
return NumberValue.ZERO;
});
functions.put("newarray", args -> {
return new ArrayValue(args);
});
}
public static boolean isExists(String key) {

View File

@ -11,7 +11,7 @@ import java.util.Map;
*/
public final class Lexer {
private static final String OPERATOR_CHARS = "+-*/(){}=<>!&|,";
private static final String OPERATOR_CHARS = "+-*/()[]{}=<>!&|,";
private static final Map<String, TokenType> OPERATORS;
static {
@ -22,6 +22,8 @@ public final class Lexer {
OPERATORS.put("/", TokenType.SLASH);
OPERATORS.put("(", TokenType.LPAREN);
OPERATORS.put(")", TokenType.RPAREN);
OPERATORS.put("[", TokenType.LBRACKET);
OPERATORS.put("]", TokenType.RBRACKET);
OPERATORS.put("{", TokenType.LBRACE);
OPERATORS.put("}", TokenType.RBRACE);
OPERATORS.put("=", TokenType.EQ);

View File

@ -80,12 +80,19 @@ public final class Parser {
private Statement assignmentStatement() {
// WORD EQ
final Token current = get(0);
if (match(TokenType.WORD) && lookMatch(0, TokenType.EQ)) {
final String variable = current.getText();
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 (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LBRACKET)) {
final String variable = consume(TokenType.WORD).getText();
consume(TokenType.LBRACKET);
final Expression index = expression();
consume(TokenType.RBRACKET);
consume(TokenType.EQ);
return new ArrayAssignmentStatement(variable, index, expression());
}
throw new RuntimeException("Unknown statement");
}
@ -147,6 +154,24 @@ public final class Parser {
return function;
}
private Expression array() {
consume(TokenType.LBRACKET);
final List<Expression> elements = new ArrayList<>();
while (!match(TokenType.RBRACKET)) {
elements.add(expression());
match(TokenType.COMMA);
}
return new ArrayExpression(elements);
}
private Expression element() {
final String variable = consume(TokenType.WORD).getText();
consume(TokenType.LBRACKET);
final Expression index = expression();
consume(TokenType.RBRACKET);
return new ArrayAccessExpression(variable, index);
}
private Expression expression() {
return logicalOr();
}
@ -275,6 +300,12 @@ public final class Parser {
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
return function();
}
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LBRACKET)) {
return element();
}
if (lookMatch(0, TokenType.LBRACKET)) {
return array();
}
if (match(TokenType.WORD)) {
return new VariableExpression(current.getText());
}

View File

@ -43,6 +43,8 @@ public enum TokenType {
LPAREN, // (
RPAREN, // )
LBRACKET, // [
RBRACKET, // ]
LBRACE, // {
RBRACE, // }
COMMA, // ,

View File

@ -0,0 +1,36 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables;
/**
*
* @author aNNiMON
*/
public final class ArrayAccessExpression implements Expression {
private final String variable;
private final Expression index;
public ArrayAccessExpression(String variable, Expression index) {
this.variable = variable;
this.index = index;
}
@Override
public Value eval() {
final Value var = Variables.get(variable);
if (var instanceof ArrayValue) {
final ArrayValue array = (ArrayValue) var;
return array.get((int) index.eval().asNumber());
} else {
throw new RuntimeException("Array expected");
}
}
@Override
public String toString() {
return String.format("%s[%s]", variable, index);
}
}

View File

@ -0,0 +1,38 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables;
/**
*
* @author aNNiMON
*/
public final class ArrayAssignmentStatement implements Statement {
private final String variable;
private final Expression index;
private final Expression expression;
public ArrayAssignmentStatement(String variable, Expression index, Expression expression) {
this.variable = variable;
this.index = index;
this.expression = expression;
}
@Override
public void execute() {
final Value var = Variables.get(variable);
if (var instanceof ArrayValue) {
final ArrayValue array = (ArrayValue) var;
array.set((int) index.eval().asNumber(), expression.eval());
} else {
throw new RuntimeException("Array expected");
}
}
@Override
public String toString() {
return String.format("%s[%s] = %s", variable, index, expression);
}
}

View File

@ -0,0 +1,33 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.Value;
import java.util.List;
/**
*
* @author aNNiMON
*/
public final class ArrayExpression implements Expression {
private final List<Expression> elements;
public ArrayExpression(List<Expression> arguments) {
this.elements = arguments;
}
@Override
public Value eval() {
final int size = elements.size();
final ArrayValue array = new ArrayValue(size);
for (int i = 0; i < size; i++) {
array.set(i, elements.get(i).eval());
}
return array;
}
@Override
public String toString() {
return elements.toString();
}
}

View File

@ -1,5 +1,6 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
@ -23,7 +24,7 @@ public final class BinaryExpression implements Expression {
public Value eval() {
final Value value1 = expr1.eval();
final Value value2 = expr2.eval();
if (value1 instanceof StringValue) {
if ( (value1 instanceof StringValue) || (value1 instanceof ArrayValue) ) {
final String string1 = value1.asString();
switch (operation) {
case '*': {