mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Добавлен тип данных Map
This commit is contained in:
parent
08847a59f1
commit
cea99d4105
@ -82,3 +82,9 @@ for i = 0, i < 4, i = i + 1 {
|
||||
print "\n"
|
||||
print function(functions[i], 6, 3)
|
||||
}
|
||||
|
||||
// map
|
||||
map = {"+" : add, "-" : sub. "*" : mul, "/" : div}
|
||||
//print map["+"]
|
||||
print "\n"
|
||||
print function(map["+"], 4, 5)
|
@ -18,7 +18,7 @@ import java.util.List;
|
||||
public final class Main {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
final String file = "examples/game/agar.own";
|
||||
final String file = "program.own";
|
||||
final String input = new String( Files.readAllBytes(Paths.get(file)), "UTF-8");
|
||||
final List<Token> tokens = new Lexer(input).tokenize();
|
||||
for (int i = 0; i < tokens.size(); i++) {
|
||||
|
@ -41,6 +41,25 @@ public final class ArrayValue implements Value {
|
||||
return Arrays.toString(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 79 * hash + Arrays.deepHashCode(this.elements);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final ArrayValue other = (ArrayValue) obj;
|
||||
return Arrays.deepEquals(this.elements, other.elements);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return asString();
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.annimon.ownlang.lib;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
@ -26,6 +28,23 @@ public final class FunctionValue implements Value {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 71 * hash + Objects.hashCode(this.value);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final FunctionValue other = (FunctionValue) obj;
|
||||
return Objects.equals(this.value, other.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return asString();
|
||||
|
60
src/com/annimon/ownlang/lib/MapValue.java
Normal file
60
src/com/annimon/ownlang/lib/MapValue.java
Normal file
@ -0,0 +1,60 @@
|
||||
package com.annimon.ownlang.lib;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class MapValue implements Value {
|
||||
|
||||
private final Map<Value, Value> map;
|
||||
|
||||
public MapValue(int size) {
|
||||
this.map = new HashMap<>(size);
|
||||
}
|
||||
|
||||
public Value get(Value key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public void set(Value key, Value value) {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double asNumber() {
|
||||
throw new RuntimeException("Cannot cast map to number");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return map.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 37 * hash + Objects.hashCode(this.map);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final MapValue other = (MapValue) obj;
|
||||
return Objects.equals(this.map, other.map);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return asString();
|
||||
}
|
||||
}
|
@ -29,6 +29,25 @@ public final class NumberValue implements Value {
|
||||
return Double.toString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 71 * hash + (int) (Double.doubleToLongBits(this.value) ^ (Double.doubleToLongBits(this.value) >>> 32));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final NumberValue other = (NumberValue) obj;
|
||||
return Double.doubleToLongBits(this.value) == Double.doubleToLongBits(other.value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return asString();
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.annimon.ownlang.lib;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
@ -26,6 +28,23 @@ public final class StringValue implements Value {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 97 * hash + Objects.hashCode(this.value);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final StringValue other = (StringValue) obj;
|
||||
return Objects.equals(this.value, other.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return asString();
|
||||
|
@ -36,4 +36,9 @@ public final class UserDefinedFunction implements Function {
|
||||
return rt.getResult();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("function %s %s", argNames.toString(), body.toString());
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ package com.annimon.ownlang.parser;
|
||||
import com.annimon.ownlang.lib.UserDefinedFunction;
|
||||
import com.annimon.ownlang.parser.ast.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -170,6 +172,19 @@ public final class Parser {
|
||||
return new ArrayExpression(elements);
|
||||
}
|
||||
|
||||
private Expression map() {
|
||||
consume(TokenType.LBRACE);
|
||||
final Map<Expression, Expression> elements = new HashMap<>();
|
||||
while (!match(TokenType.RBRACE)) {
|
||||
final Expression key = primary();
|
||||
consume(TokenType.COLON);
|
||||
final Expression value = expression();
|
||||
elements.put(key, value);
|
||||
match(TokenType.COMMA);
|
||||
}
|
||||
return new MapExpression(elements);
|
||||
}
|
||||
|
||||
private ArrayAccessExpression element() {
|
||||
final String variable = consume(TokenType.WORD).getText();
|
||||
final List<Expression> indices = new ArrayList<>();
|
||||
@ -393,15 +408,18 @@ public final class Parser {
|
||||
if (match(TokenType.HEX_NUMBER)) {
|
||||
return new ValueExpression(Long.parseLong(current.getText(), 16));
|
||||
}
|
||||
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.WORD) && lookMatch(1, TokenType.LPAREN)) {
|
||||
return function();
|
||||
}
|
||||
if (lookMatch(0, TokenType.LBRACKET)) {
|
||||
return array();
|
||||
}
|
||||
if (lookMatch(0, TokenType.LBRACE)) {
|
||||
return map();
|
||||
}
|
||||
if (match(TokenType.WORD)) {
|
||||
return new VariableExpression(current.getText());
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.ArrayValue;
|
||||
import com.annimon.ownlang.lib.MapValue;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
import com.annimon.ownlang.lib.Variables;
|
||||
import java.util.List;
|
||||
@ -21,7 +22,11 @@ public final class ArrayAccessExpression implements Expression {
|
||||
|
||||
@Override
|
||||
public Value eval() {
|
||||
return getArray().get(lastIndex());
|
||||
Value container = Variables.get(variable);
|
||||
if (container instanceof ArrayValue) {
|
||||
return getArray().get(lastIndex());
|
||||
}
|
||||
return consumeMap(container).get(indices.get(0).eval());
|
||||
}
|
||||
|
||||
public ArrayValue getArray() {
|
||||
@ -49,6 +54,14 @@ public final class ArrayAccessExpression implements Expression {
|
||||
}
|
||||
}
|
||||
|
||||
private MapValue consumeMap(Value value) {
|
||||
if (value instanceof MapValue) {
|
||||
return (MapValue) value;
|
||||
} else {
|
||||
throw new RuntimeException("Map expected");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor visitor) {
|
||||
visitor.visit(this);
|
||||
|
38
src/com/annimon/ownlang/parser/ast/MapExpression.java
Normal file
38
src/com/annimon/ownlang/parser/ast/MapExpression.java
Normal file
@ -0,0 +1,38 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.MapValue;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class MapExpression implements Expression {
|
||||
|
||||
public final Map<Expression, Expression> elements;
|
||||
|
||||
public MapExpression(Map<Expression, Expression> arguments) {
|
||||
this.elements = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval() {
|
||||
final int size = elements.size();
|
||||
final MapValue map = new MapValue(size);
|
||||
for (Expression key : elements.keySet()) {
|
||||
map.set(key.eval(), elements.get(key).eval());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return elements.toString();
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ public interface Visitor {
|
||||
void visit(FunctionStatement s);
|
||||
void visit(FunctionalExpression s);
|
||||
void visit(IfStatement s);
|
||||
void visit(MapExpression s);
|
||||
void visit(PrintStatement s);
|
||||
void visit(ReturnStatement s);
|
||||
void visit(TernaryExpression s);
|
||||
|
@ -100,6 +100,14 @@ public abstract class AbstractVisitor implements Visitor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MapExpression s) {
|
||||
for (Expression key : s.elements.keySet()) {
|
||||
key.accept(this);
|
||||
s.elements.get(key).accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PrintStatement s) {
|
||||
s.expression.accept(this);
|
||||
|
Loading…
Reference in New Issue
Block a user