mirror of
https://github.com/Noratrieb/Hunterlang.git
synced 2026-01-14 04:25:01 +01:00
basic interpreter kind of working
This commit is contained in:
parent
6270363d96
commit
116ec117fa
12 changed files with 439 additions and 58 deletions
|
|
@ -6,6 +6,7 @@ public class FunctionArgLookup {
|
|||
return switch (name) {
|
||||
case "Leorio.say" -> 1;
|
||||
case "Leorio.listen" -> 0;
|
||||
case "Wing.dump" -> 0;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
package com.github.nilstrieb.hunterlang.hllibrary;
|
||||
|
||||
import com.github.nilstrieb.hunterlang.interpreter.RuntimeException;
|
||||
import com.github.nilstrieb.hunterlang.interpreter.Value;
|
||||
import com.github.nilstrieb.hunterlang.lexer.WordType;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Leorio {
|
||||
|
||||
public static void say(Value s) {
|
||||
System.out.println(s.toPrintString());
|
||||
}
|
||||
|
||||
public static String listen() {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
return sc.nextLine();
|
||||
}
|
||||
|
||||
public static Value call(String name, Object[] args) throws RuntimeException {
|
||||
switch (name) {
|
||||
case "say" -> {
|
||||
say((Value) args[0]);
|
||||
return new Value();
|
||||
}
|
||||
case "listen" -> {
|
||||
return new Value(listen(), WordType.STRING);
|
||||
}
|
||||
default -> {
|
||||
throw new RuntimeException("function not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.github.nilstrieb.hunterlang.hllibrary;
|
||||
|
||||
import com.github.nilstrieb.hunterlang.interpreter.RuntimeException;
|
||||
import com.github.nilstrieb.hunterlang.interpreter.Value;
|
||||
|
||||
public class Library {
|
||||
public static Object call(String name, Object ... args) throws RuntimeException {
|
||||
String[] parts = name.split("\\.");
|
||||
return switch (parts[0]){
|
||||
case "Leorio" -> Leorio.call(parts[1], args);
|
||||
case "Wing" -> Wing.call(parts[1], args);
|
||||
default -> throw new RuntimeException("Unexpected lib: " + parts[0]);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.github.nilstrieb.hunterlang.hllibrary;
|
||||
|
||||
import com.github.nilstrieb.hunterlang.interpreter.Memory;
|
||||
import com.github.nilstrieb.hunterlang.interpreter.RuntimeException;
|
||||
import com.github.nilstrieb.hunterlang.interpreter.Value;
|
||||
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Wing {
|
||||
public static void dump(Memory m) {
|
||||
ArrayList<Value> list = m.getList();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Value value = list.get(i);
|
||||
System.out.println(ConsoleColors.CYAN + i + ConsoleColors.YELLOW + " " + value + ConsoleColors.RESET);
|
||||
}
|
||||
}
|
||||
|
||||
public static Value call(String name, Object ... args) throws RuntimeException {
|
||||
switch (name) {
|
||||
case "dump" -> {
|
||||
dump((Memory) args[0]);
|
||||
return new Value();
|
||||
}
|
||||
default -> {
|
||||
throw new RuntimeException("function not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package com.github.nilstrieb.hunterlang.interpreter;
|
||||
|
||||
import com.github.nilstrieb.hunterlang.hllibrary.Library;
|
||||
import com.github.nilstrieb.hunterlang.hllibrary.Wing;
|
||||
import com.github.nilstrieb.hunterlang.lexer.WordType;
|
||||
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
||||
import com.github.nilstrieb.hunterlang.parser.ParseTreeBodyNode;
|
||||
import com.github.nilstrieb.hunterlang.parser.ParseTreeNode;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Interpreter {
|
||||
|
||||
ArrayList<ParseTreeNode> statements;
|
||||
Memory memory;
|
||||
|
||||
public void start(ArrayList<ParseTreeNode> statementNodes) throws RuntimeException {
|
||||
System.out.println(ConsoleColors.GREEN_BACKGROUND + ConsoleColors.BLACK_BOLD + "------START INTERPRETER------" + ConsoleColors.RESET);
|
||||
interpret(statementNodes);
|
||||
System.out.println(ConsoleColors.GREEN_BACKGROUND + ConsoleColors.BLACK_BOLD + "------STOP INTERPRETER------" + ConsoleColors.RESET);
|
||||
}
|
||||
|
||||
public void interpret(ArrayList<ParseTreeNode> statementNodes) throws RuntimeException {
|
||||
|
||||
statements = statementNodes;
|
||||
memory = new Memory();
|
||||
boolean lastIfTrue = false;
|
||||
|
||||
for (ParseTreeNode statement : statements) {
|
||||
switch (statement.getKey()) {
|
||||
case ASSIGNMENT -> {
|
||||
ParseTreeNode memoryNode = statement.getChild(0);
|
||||
ParseTreeNode valueNode = statement.getChild(1);
|
||||
|
||||
int memoryAdress = evaluateInt(memoryNode.getChild(0));
|
||||
Value value = evaluate(valueNode);
|
||||
|
||||
memory.set(memoryAdress, value);
|
||||
//Wing.dump(memory);
|
||||
}
|
||||
case IF -> {
|
||||
if(evaluate(statement.getChild(0)).getBoolValue()){
|
||||
lastIfTrue = true;
|
||||
interpret(((ParseTreeBodyNode) statement).getStatements());
|
||||
} else {
|
||||
lastIfTrue = false;
|
||||
}
|
||||
}
|
||||
case WANTS -> {
|
||||
|
||||
}
|
||||
case ELSE -> {
|
||||
|
||||
}
|
||||
case LIBFUNCCALL -> {
|
||||
String call = statement.getValue();
|
||||
ArrayList<ParseTreeNode> argsNode = statement.getChildren();
|
||||
ArrayList<Value> args = new ArrayList<>();
|
||||
for (ParseTreeNode parseTreeNode : argsNode) {
|
||||
args.add(evaluate(parseTreeNode));
|
||||
}
|
||||
if (call.equals("Wing.dump")) {
|
||||
Library.call(call, memory);
|
||||
} else {
|
||||
Library.call(call, args.toArray());
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
throw new RuntimeException("illegal statement type: " + statement.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int evaluateInt(ParseTreeNode parent) {
|
||||
return evaluate(parent).getIntValue();
|
||||
}
|
||||
|
||||
private Value evaluate(ParseTreeNode parent) {
|
||||
switch (parent.getKey()) {
|
||||
case MEMCALL -> {
|
||||
return memory.get(evaluateInt(parent.getChild(0)));
|
||||
}
|
||||
case NUMBER -> {
|
||||
return new Value(parent.getValue(), WordType.NUMBER);
|
||||
}
|
||||
case GTHAN -> {
|
||||
Value v2 = evaluate(parent.getChild(1));
|
||||
int comp = evaluate(parent.getChild(0)).compareTo(v2);
|
||||
return comp > 0 ? new Value(true) : new Value(false);
|
||||
}
|
||||
case LTHAN -> {
|
||||
int comp = evaluate(parent.getChild(0)).compareTo(evaluate(parent.getChild(1)));
|
||||
return comp < 0 ? new Value(true) : new Value(false);
|
||||
}
|
||||
case EQUALS -> {
|
||||
int comp = evaluate(parent.getChild(0)).compareTo(evaluate(parent.getChild(1)));
|
||||
return comp == 0 ? new Value(true) : new Value(false);
|
||||
}
|
||||
case STRING -> {
|
||||
return new Value(parent.getValue(), WordType.STRING);
|
||||
}
|
||||
case BOOL -> {
|
||||
return new Value(parent.getValue(), WordType.BOOL);
|
||||
}
|
||||
default -> {
|
||||
return new Value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.github.nilstrieb.hunterlang.interpreter;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Memory {
|
||||
private ArrayList<Value> mem;
|
||||
|
||||
public Memory() {
|
||||
mem = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Value get(int i){
|
||||
if(i >= mem.size()){
|
||||
return new Value();
|
||||
} else {
|
||||
return mem.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(int i, Value v){
|
||||
if(i >= mem.size()){
|
||||
int dif = i - mem.size() + 1;
|
||||
for (int j = 0; j < dif; j++) {
|
||||
mem.add(new Value());
|
||||
}
|
||||
}
|
||||
|
||||
mem.set(i, v);
|
||||
}
|
||||
|
||||
public ArrayList<Value> getList() {
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.github.nilstrieb.hunterlang.interpreter;
|
||||
|
||||
public class RuntimeException extends Exception {
|
||||
public RuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
package com.github.nilstrieb.hunterlang.interpreter;
|
||||
|
||||
import com.github.nilstrieb.hunterlang.lexer.WordType;
|
||||
|
||||
public class Value {
|
||||
private Type type;
|
||||
private String stringValue;
|
||||
private int intValue;
|
||||
private double floatValue;
|
||||
private boolean boolValue;
|
||||
|
||||
public Value(String value, WordType tType) {
|
||||
if (tType == WordType.NUMBER && value.matches("\\d+")) {
|
||||
type = Type.INT;
|
||||
fromInt(value);
|
||||
} else if (tType == WordType.NUMBER && value.matches("\\d+.\\d")) {
|
||||
type = Type.FLOAT;
|
||||
fromFloat(value);
|
||||
} else if (tType == WordType.BOOL) {
|
||||
type = Type.BOOL;
|
||||
fromBool(value);
|
||||
} else if (tType == WordType.STRING) {
|
||||
type = Type.STRING;
|
||||
fromString(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Value() {
|
||||
type = Type.INT;
|
||||
fromInt("0");
|
||||
}
|
||||
|
||||
public Value(boolean b) {
|
||||
type = Type.BOOL;
|
||||
fromBool(String.valueOf(b));
|
||||
}
|
||||
|
||||
private void fromInt(String value){
|
||||
intValue = Integer.parseInt(value);
|
||||
stringValue = value;
|
||||
floatValue = intValue;
|
||||
boolValue = intValue != 0;
|
||||
}
|
||||
|
||||
private void fromFloat(String value){
|
||||
floatValue = Double.parseDouble(value);
|
||||
intValue = (int) floatValue;
|
||||
stringValue = value;
|
||||
boolValue = intValue != 0;
|
||||
}
|
||||
|
||||
private void fromBool(String value){
|
||||
boolValue = Boolean.parseBoolean(value);
|
||||
intValue = boolValue ? 1 : 0;
|
||||
floatValue = intValue;
|
||||
stringValue = value;
|
||||
}
|
||||
|
||||
private void fromString(String value){
|
||||
stringValue = value;
|
||||
boolValue = false;
|
||||
intValue = stringValue.length();
|
||||
floatValue = intValue;
|
||||
}
|
||||
|
||||
public String getStringValue() {
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
public int getIntValue() {
|
||||
return intValue;
|
||||
}
|
||||
|
||||
public double getFloatValue() {
|
||||
return floatValue;
|
||||
}
|
||||
|
||||
public boolean isBoolValue() {
|
||||
return boolValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return stringValue + " " + type;
|
||||
}
|
||||
|
||||
public void setValue(String value){
|
||||
|
||||
}
|
||||
|
||||
public int compareTo(Value v2) {
|
||||
return Double.compare(this.floatValue, v2.floatValue);
|
||||
}
|
||||
|
||||
public String toPrintString() {
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
public boolean getBoolValue() {
|
||||
return boolValue;
|
||||
}
|
||||
|
||||
enum Type {
|
||||
INT, FLOAT, STRING, BOOL
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.github.nilstrieb.hunterlang.lexer;
|
||||
|
||||
import com.github.nilstrieb.hunterlang.interpreter.Interpreter;
|
||||
import com.github.nilstrieb.hunterlang.interpreter.RuntimeException;
|
||||
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
||||
import com.github.nilstrieb.hunterlang.parser.ParseException;
|
||||
import com.github.nilstrieb.hunterlang.parser.ParseTreeNode;
|
||||
|
|
@ -32,7 +34,7 @@ public class Lexer {
|
|||
|
||||
public static final String BOOL_REGEX = "(true|false).*";
|
||||
public static final String STRING_REGEX = "^\"(.*)\".*";
|
||||
public static final String NUMBER_REGEX = "^(-?\\d+.?\\d*).*";
|
||||
public static final String NUMBER_REGEX = "^(-?\\d+\\.?\\d*).*";
|
||||
|
||||
private ArrayList<LexToken> tokens;
|
||||
private ArrayList<LexToken> temp;
|
||||
|
|
@ -149,58 +151,4 @@ public class Lexer {
|
|||
temp.add(new LexToken(type));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Lexer l = new Lexer();
|
||||
|
||||
String assign = """
|
||||
killua70 hunts 3 > 0
|
||||
killua0 hunts 3
|
||||
killua0 hunts -3.4 #hunts nothing
|
||||
killua1 hunts "hallo"
|
||||
#comment""";
|
||||
String ifs = """
|
||||
killua0 hunts 3 > 0
|
||||
Gon wants false {
|
||||
Leorio does say "false"
|
||||
}
|
||||
wants killua0 > 3 {
|
||||
Leorio does say "big killua"
|
||||
} got {
|
||||
Leorio does say "small killua"
|
||||
}
|
||||
Gon wants true {
|
||||
Gon wants true {
|
||||
Leorio does say "that is actually very true"
|
||||
}
|
||||
}
|
||||
""";
|
||||
String ifif = """
|
||||
Gon wants true {
|
||||
Gon wants true {
|
||||
Leorio does say "hallo"
|
||||
}
|
||||
}
|
||||
""";
|
||||
String sif = """
|
||||
Gon wants true {
|
||||
Leorio does say "hallo"
|
||||
}
|
||||
""";
|
||||
String hierarchy = """
|
||||
killua0 hunts 3 > 3
|
||||
""";
|
||||
|
||||
ArrayList<LexToken> tokens = l.lex(ifs);
|
||||
|
||||
Parser p = new Parser();
|
||||
try {
|
||||
ArrayList<ParseTreeNode> nodes = p.parse(tokens);
|
||||
|
||||
for (ParseTreeNode parseTreeNode : nodes) {
|
||||
System.out.println(parseTreeNode);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ public class ParseTreeNode {
|
|||
this(WordType.EMPTY, "");
|
||||
}
|
||||
|
||||
public ArrayList<ParseTreeNode> getChildren() {
|
||||
return children;
|
||||
public ParseTreeNode getChild(int index) {
|
||||
return children.get(index);
|
||||
}
|
||||
|
||||
public void addChild(ParseTreeNode n, boolean pre) {
|
||||
|
|
@ -96,4 +96,8 @@ public class ParseTreeNode {
|
|||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public ArrayList<ParseTreeNode> getChildren() {
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@ public class Parser {
|
|||
}
|
||||
case LIBFUNCCALL -> {
|
||||
parent = current.toNode();
|
||||
parent.addChild(evaluate(tokens.subList(1, tokens.size())));
|
||||
if(current.hasPostfix()) {
|
||||
parent.addChild(evaluate(statement.subList(1, statement.size())));
|
||||
}
|
||||
}
|
||||
|
||||
default -> throw new ParseException("Unexpected value at start of statement: " + current.getKey());
|
||||
|
|
|
|||
85
src/main/java/com/github/nilstrieb/hunterlang/run/Main.java
Normal file
85
src/main/java/com/github/nilstrieb/hunterlang/run/Main.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package com.github.nilstrieb.hunterlang.run;
|
||||
|
||||
import com.github.nilstrieb.hunterlang.interpreter.Interpreter;
|
||||
import com.github.nilstrieb.hunterlang.interpreter.RuntimeException;
|
||||
import com.github.nilstrieb.hunterlang.lexer.LexToken;
|
||||
import com.github.nilstrieb.hunterlang.lexer.Lexer;
|
||||
import com.github.nilstrieb.hunterlang.parser.ParseException;
|
||||
import com.github.nilstrieb.hunterlang.parser.ParseTreeNode;
|
||||
import com.github.nilstrieb.hunterlang.parser.Parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Lexer l = new Lexer();
|
||||
|
||||
String assign = """
|
||||
killua70 hunts 3 > 0
|
||||
killua0 hunts 3
|
||||
killua0 hunts -3.4 #hunts nothing
|
||||
killua1 hunts "hallo"
|
||||
#comment""";
|
||||
String ifs = """
|
||||
killua0 hunts 3 > 0
|
||||
Gon wants false {
|
||||
Leorio does say "false"
|
||||
}
|
||||
wants killua0 > 3 {
|
||||
Leorio does say "big killua"
|
||||
} got {
|
||||
Leorio does say "small killua"
|
||||
}
|
||||
Gon wants true {
|
||||
Gon wants true {
|
||||
Leorio does say "that is actually very true"
|
||||
}
|
||||
}
|
||||
""";
|
||||
String ifif = """
|
||||
Gon wants true {
|
||||
Gon wants true {
|
||||
Leorio does say "hallo"
|
||||
}
|
||||
}
|
||||
""";
|
||||
String sif = """
|
||||
Gon wants true {
|
||||
Leorio does say "hallo"
|
||||
}
|
||||
""";
|
||||
String hierarchy = """
|
||||
killua0 hunts 3 > 3
|
||||
""";
|
||||
|
||||
String weird = """
|
||||
killua1 hunts 2
|
||||
Wing does dump
|
||||
Gon wants 5 < killua1 {
|
||||
Leorio does say "its actually smaller gon!!!"
|
||||
} wants 1 < killua1 {
|
||||
Leorio does say "at least that"
|
||||
}
|
||||
""";
|
||||
String hw = """
|
||||
Leorio does say "Hello World!"
|
||||
""";
|
||||
|
||||
ArrayList<LexToken> tokens = l.lex(weird);
|
||||
|
||||
Parser p = new Parser();
|
||||
try {
|
||||
ArrayList<ParseTreeNode> nodes = p.parse(tokens);
|
||||
|
||||
for (ParseTreeNode parseTreeNode : nodes) {
|
||||
System.out.println(parseTreeNode);
|
||||
}
|
||||
|
||||
Interpreter i = new Interpreter();
|
||||
i.start(nodes);
|
||||
} catch (ParseException | RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue