mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44: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 "\n"
|
||||||
print function(functions[i], 6, 3)
|
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 final class Main {
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
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 String input = new String( Files.readAllBytes(Paths.get(file)), "UTF-8");
|
||||||
final List<Token> tokens = new Lexer(input).tokenize();
|
final List<Token> tokens = new Lexer(input).tokenize();
|
||||||
for (int i = 0; i < tokens.size(); i++) {
|
for (int i = 0; i < tokens.size(); i++) {
|
||||||
|
@ -41,6 +41,25 @@ public final class ArrayValue implements Value {
|
|||||||
return Arrays.toString(elements);
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return asString();
|
return asString();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.annimon.ownlang.lib;
|
package com.annimon.ownlang.lib;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author aNNiMON
|
* @author aNNiMON
|
||||||
@ -26,6 +28,23 @@ public final class FunctionValue implements Value {
|
|||||||
return 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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return asString();
|
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);
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return asString();
|
return asString();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.annimon.ownlang.lib;
|
package com.annimon.ownlang.lib;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author aNNiMON
|
* @author aNNiMON
|
||||||
@ -26,6 +28,23 @@ public final class StringValue implements Value {
|
|||||||
return 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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return asString();
|
return asString();
|
||||||
|
@ -36,4 +36,9 @@ public final class UserDefinedFunction implements Function {
|
|||||||
return rt.getResult();
|
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.lib.UserDefinedFunction;
|
||||||
import com.annimon.ownlang.parser.ast.*;
|
import com.annimon.ownlang.parser.ast.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -170,6 +172,19 @@ public final class Parser {
|
|||||||
return new ArrayExpression(elements);
|
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() {
|
private ArrayAccessExpression element() {
|
||||||
final String variable = consume(TokenType.WORD).getText();
|
final String variable = consume(TokenType.WORD).getText();
|
||||||
final List<Expression> indices = new ArrayList<>();
|
final List<Expression> indices = new ArrayList<>();
|
||||||
@ -393,15 +408,18 @@ public final class Parser {
|
|||||||
if (match(TokenType.HEX_NUMBER)) {
|
if (match(TokenType.HEX_NUMBER)) {
|
||||||
return new ValueExpression(Long.parseLong(current.getText(), 16));
|
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)) {
|
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LBRACKET)) {
|
||||||
return element();
|
return element();
|
||||||
}
|
}
|
||||||
|
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
|
||||||
|
return function();
|
||||||
|
}
|
||||||
if (lookMatch(0, TokenType.LBRACKET)) {
|
if (lookMatch(0, TokenType.LBRACKET)) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
if (lookMatch(0, TokenType.LBRACE)) {
|
||||||
|
return map();
|
||||||
|
}
|
||||||
if (match(TokenType.WORD)) {
|
if (match(TokenType.WORD)) {
|
||||||
return new VariableExpression(current.getText());
|
return new VariableExpression(current.getText());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.annimon.ownlang.parser.ast;
|
package com.annimon.ownlang.parser.ast;
|
||||||
|
|
||||||
import com.annimon.ownlang.lib.ArrayValue;
|
import com.annimon.ownlang.lib.ArrayValue;
|
||||||
|
import com.annimon.ownlang.lib.MapValue;
|
||||||
import com.annimon.ownlang.lib.Value;
|
import com.annimon.ownlang.lib.Value;
|
||||||
import com.annimon.ownlang.lib.Variables;
|
import com.annimon.ownlang.lib.Variables;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -21,8 +22,12 @@ public final class ArrayAccessExpression implements Expression {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value eval() {
|
public Value eval() {
|
||||||
|
Value container = Variables.get(variable);
|
||||||
|
if (container instanceof ArrayValue) {
|
||||||
return getArray().get(lastIndex());
|
return getArray().get(lastIndex());
|
||||||
}
|
}
|
||||||
|
return consumeMap(container).get(indices.get(0).eval());
|
||||||
|
}
|
||||||
|
|
||||||
public ArrayValue getArray() {
|
public ArrayValue getArray() {
|
||||||
ArrayValue array = consumeArray(Variables.get(variable));
|
ArrayValue array = consumeArray(Variables.get(variable));
|
||||||
@ -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
|
@Override
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
visitor.visit(this);
|
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(FunctionStatement s);
|
||||||
void visit(FunctionalExpression s);
|
void visit(FunctionalExpression s);
|
||||||
void visit(IfStatement s);
|
void visit(IfStatement s);
|
||||||
|
void visit(MapExpression s);
|
||||||
void visit(PrintStatement s);
|
void visit(PrintStatement s);
|
||||||
void visit(ReturnStatement s);
|
void visit(ReturnStatement s);
|
||||||
void visit(TernaryExpression 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
|
@Override
|
||||||
public void visit(PrintStatement s) {
|
public void visit(PrintStatement s) {
|
||||||
s.expression.accept(this);
|
s.expression.accept(this);
|
||||||
|
Loading…
Reference in New Issue
Block a user