mirror of
https://github.com/Noratrieb/Hunterlang.git
synced 2026-01-14 20:45:00 +01:00
assignment parsing works
This commit is contained in:
parent
9de19a993e
commit
313a584631
12 changed files with 424 additions and 108 deletions
2
.idea/.gitignore
generated
vendored
2
.idea/.gitignore
generated
vendored
|
|
@ -2,4 +2,4 @@
|
||||||
/shelf/
|
/shelf/
|
||||||
/workspace.xml
|
/workspace.xml
|
||||||
out\
|
out\
|
||||||
.class
|
*.class
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.github.nilstrieb.hunterlang.editor.EditorView">
|
|
||||||
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
|
||||||
<constraints>
|
|
||||||
<xy x="20" y="20" width="500" height="400"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children>
|
|
||||||
<component id="beb13" class="javax.swing.JEditorPane" binding="editorPane1" default-binding="true">
|
|
||||||
<constraints>
|
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
|
||||||
<preferred-size width="150" height="50"/>
|
|
||||||
</grid>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
</component>
|
|
||||||
</children>
|
|
||||||
</grid>
|
|
||||||
</form>
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package com.github.nilstrieb.hunterlang.editor;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
public class EditorView {
|
|
||||||
private JEditorPane editorPane1;
|
|
||||||
private JPanel panel1;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.github.nilstrieb.hunterlang.hllibrary;
|
||||||
|
|
||||||
|
public class FunctionArgLookup {
|
||||||
|
|
||||||
|
public static int argLookup(String lib, String name){
|
||||||
|
return switch (lib){
|
||||||
|
case "Leorio" -> switch (name){
|
||||||
|
case "say" -> 1;
|
||||||
|
case "listen" -> 0;
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.github.nilstrieb.hunterlang.lexer;
|
package com.github.nilstrieb.hunterlang.lexer;
|
||||||
|
|
||||||
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
||||||
|
import com.github.nilstrieb.hunterlang.parser.ParseTreeNode;
|
||||||
|
|
||||||
public class LexToken {
|
public class LexToken {
|
||||||
WordType key;
|
WordType key;
|
||||||
|
|
@ -11,11 +12,34 @@ public class LexToken {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LexToken(WordType key) {
|
||||||
|
this(key, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int expectsPostArgCount() {
|
||||||
|
return key.expectsPostArg();
|
||||||
|
}
|
||||||
|
public boolean expectsPreArg() {
|
||||||
|
return key.expectsPreArg() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParseTreeNode toNode(){
|
||||||
|
return new ParseTreeNode(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return ConsoleColors.BLUE_BOLD + "{Key=" +
|
return ConsoleColors.PURPLE_BOLD + "T" + ConsoleColors.BLUE_BOLD + "{Key=" +
|
||||||
ConsoleColors.RED_BOLD_BRIGHT + key +
|
ConsoleColors.RED_BOLD_BRIGHT + key +
|
||||||
ConsoleColors.BLUE_BOLD + ", value=" +
|
ConsoleColors.BLUE_BOLD + ", value=" +
|
||||||
ConsoleColors.YELLOW + value + ConsoleColors.BLUE_BOLD + "}";
|
ConsoleColors.YELLOW + value + ConsoleColors.BLUE_BOLD + "}" + ConsoleColors.RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WordType getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package com.github.nilstrieb.hunterlang.lexer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class LexedList {
|
|
||||||
private ArrayList<ArrayList<LexToken>> list;
|
|
||||||
|
|
||||||
public LexedList() {
|
|
||||||
list = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void newLine(){
|
|
||||||
list.add(new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(int line, WordType type, String value) {
|
|
||||||
list.get(line).add(new LexToken(type, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(int line, WordType type){
|
|
||||||
add(line, type, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<LexToken> get(int i) {
|
|
||||||
return list.get(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
package com.github.nilstrieb.hunterlang.lexer;
|
package com.github.nilstrieb.hunterlang.lexer;
|
||||||
|
|
||||||
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
||||||
|
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;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
@ -31,15 +34,16 @@ public class Lexer {
|
||||||
public static final String STRING_REGEX = "^\"(.*)\".*";
|
public static final String STRING_REGEX = "^\"(.*)\".*";
|
||||||
public static final String NUMBER_REGEX = "^(-?\\d+.?\\d*).*";
|
public static final String NUMBER_REGEX = "^(-?\\d+.?\\d*).*";
|
||||||
|
|
||||||
private LexedList tokens;
|
private ArrayList<LexToken> tokens;
|
||||||
|
private ArrayList<LexToken> temp;
|
||||||
|
|
||||||
|
public ArrayList<LexToken> lex(String code) {
|
||||||
|
tokens = new ArrayList<>();
|
||||||
|
temp = new ArrayList<>();
|
||||||
|
|
||||||
public LexedList lex(String code) {
|
|
||||||
tokens = new LexedList();
|
|
||||||
ArrayList<LexToken> tempList = new ArrayList<>();
|
|
||||||
String[] lines = code.split("\\r\\n|\\n");
|
String[] lines = code.split("\\r\\n|\\n");
|
||||||
|
|
||||||
for (int i = 0; i < lines.length; i++) {
|
for (int i = 0; i < lines.length; i++) {
|
||||||
tokens.newLine();
|
|
||||||
String line = lines[i];
|
String line = lines[i];
|
||||||
for (int j = 0; j < line.length(); j++) {
|
for (int j = 0; j < line.length(); j++) {
|
||||||
String sub = line.substring(j);
|
String sub = line.substring(j);
|
||||||
|
|
@ -53,103 +57,127 @@ public class Lexer {
|
||||||
//FIXED KEYWORDS
|
//FIXED KEYWORDS
|
||||||
|
|
||||||
else if (sub.startsWith(MEMCALL)) {
|
else if (sub.startsWith(MEMCALL)) {
|
||||||
tokens.add(i, WordType.MEMCALL);
|
addToken(WordType.MEMCALL);
|
||||||
j += MEMCALL.length() - 1;
|
j += MEMCALL.length() - 1;
|
||||||
} else if (sub.startsWith(ASSIGNMENT)) {
|
} else if (sub.startsWith(ASSIGNMENT)) {
|
||||||
tokens.add(i, WordType.ASSIGNMENT);
|
addToken(WordType.ASSIGNMENT);
|
||||||
j += ASSIGNMENT.length() - 1;
|
j += ASSIGNMENT.length() - 1;
|
||||||
} else if (sub.startsWith(IF)) {
|
} else if (sub.startsWith(IF)) {
|
||||||
tokens.add(i, WordType.IF);
|
addToken(WordType.IF);
|
||||||
j += IF.length() - 1;
|
j += IF.length() - 1;
|
||||||
} else if (sub.startsWith(WANTS)){
|
} else if (sub.startsWith(WANTS)) {
|
||||||
tokens.add(i, WordType.WANTS);
|
addToken(WordType.WANTS);
|
||||||
j += WANTS.length() - 1;
|
j += WANTS.length() - 1;
|
||||||
} else if (sub.startsWith(ELSE)){
|
} else if (sub.startsWith(ELSE)) {
|
||||||
tokens.add(i, WordType.ELSE);
|
addToken(WordType.ELSE);
|
||||||
j += ELSE.length() - 1;
|
j += ELSE.length() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//CONDITIONS
|
//CONDITIONS
|
||||||
else if (sub.startsWith(GTHAN)){
|
else if (sub.startsWith(GTHAN)) {
|
||||||
tokens.add(i, WordType.GTHAN);
|
addToken(WordType.GTHAN);
|
||||||
j += GTHAN.length() - 1;
|
j += GTHAN.length() - 1;
|
||||||
} else if (sub.startsWith(LTHAN)){
|
} else if (sub.startsWith(LTHAN)) {
|
||||||
tokens.add(i, WordType.LTHAN);
|
addToken(WordType.LTHAN);
|
||||||
j += LTHAN.length() - 1;
|
j += LTHAN.length() - 1;
|
||||||
} else if (sub.startsWith(EQUALS)){
|
} else if (sub.startsWith(EQUALS)) {
|
||||||
tokens.add(i, WordType.EQUALS);
|
addToken(WordType.EQUALS);
|
||||||
j += EQUALS.length() - 1;
|
j += EQUALS.length() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//OPERATORS
|
//OPERATORS
|
||||||
else if (sub.startsWith(PLUS)){
|
else if (sub.startsWith(PLUS)) {
|
||||||
tokens.add(i, WordType.PLUS);
|
addToken(WordType.PLUS);
|
||||||
} else if (sub.startsWith(MINUS)){
|
} else if (sub.startsWith(MINUS)) {
|
||||||
tokens.add(i, WordType.MINUS);
|
addToken(WordType.MINUS);
|
||||||
} else if (sub.startsWith(MULTIPLY)){
|
} else if (sub.startsWith(MULTIPLY)) {
|
||||||
tokens.add(i, WordType.MULTIPLY);
|
addToken(WordType.MULTIPLY);
|
||||||
}else if (sub.startsWith(DIVIDE)){
|
} else if (sub.startsWith(DIVIDE)) {
|
||||||
tokens.add(i, WordType.DIVIDE);
|
addToken(WordType.DIVIDE);
|
||||||
} else if (sub.startsWith(MOD)){
|
} else if (sub.startsWith(MOD)) {
|
||||||
tokens.add(i, WordType.MOD);
|
addToken(WordType.MOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BRACKETS
|
// BRACKETS
|
||||||
else if (sub.startsWith(BOPEN)){
|
else if (sub.startsWith(BOPEN)) {
|
||||||
tokens.add(i, WordType.BOPEN);
|
addToken(WordType.BOPEN);
|
||||||
} else if (sub.startsWith(BCLOSE)){
|
} else if (sub.startsWith(BCLOSE)) {
|
||||||
tokens.add(i, WordType.BCLOSE);
|
addToken(WordType.BCLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//VALUES
|
//VALUES
|
||||||
else if (sub.matches(STRING_REGEX)) {
|
else if (sub.matches(STRING_REGEX)) {
|
||||||
String string = sub.replaceAll(STRING_REGEX, "$1");
|
String string = sub.replaceAll(STRING_REGEX, "$1");
|
||||||
tokens.add(i, WordType.STRING, string);
|
addToken(WordType.STRING, string);
|
||||||
j += string.length() + 1;
|
j += string.length() + 1;
|
||||||
} else if (sub.matches(NUMBER_REGEX)) {
|
} else if (sub.matches(NUMBER_REGEX)) {
|
||||||
String number = sub.replaceAll(NUMBER_REGEX, "$1");
|
String number = sub.replaceAll(NUMBER_REGEX, "$1");
|
||||||
tokens.add(i, WordType.NUMBER, number);
|
addToken(WordType.NUMBER, number);
|
||||||
j += number.length() - 1;
|
j += number.length() - 1;
|
||||||
} else if (sub.matches(BOOL_REGEX)){
|
} else if (sub.matches(BOOL_REGEX)) {
|
||||||
String bool = sub.replaceAll(BOOL_REGEX, "$1");
|
String bool = sub.replaceAll(BOOL_REGEX, "$1");
|
||||||
tokens.add(i, WordType.BOOL, bool);
|
addToken(WordType.BOOL, bool);
|
||||||
j += bool.length() - 1;
|
j += bool.length() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Calls
|
//Calls
|
||||||
else if(sub.matches(LIBFUNCCALL_REGEX)){
|
else if (sub.matches(LIBFUNCCALL_REGEX)) {
|
||||||
String libName = sub.replaceAll(LIBFUNCCALL_REGEX, "$1");
|
String libName = sub.replaceAll(LIBFUNCCALL_REGEX, "$1");
|
||||||
String funcName = sub.replaceAll(LIBFUNCCALL_REGEX, "$2");
|
String funcName = sub.replaceAll(LIBFUNCCALL_REGEX, "$2");
|
||||||
tokens.add(i, WordType.LIB, libName);
|
addToken(WordType.LIB, libName);
|
||||||
tokens.add(i, WordType.FUNCCALL, funcName);
|
addToken(WordType.FUNCCALL, funcName);
|
||||||
j += libName.length(); //lib name
|
j += libName.length(); //lib name
|
||||||
j += 1 + 4 + 1; // space + does + space
|
j += 1 + 4 + 1; // space + does + space
|
||||||
j += funcName.length() - 1; //func name
|
j += funcName.length() - 1; //func name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println(ConsoleColors.GREEN_BOLD + line);
|
System.out.println(ConsoleColors.GREEN_BOLD + line);
|
||||||
System.out.println(ConsoleColors.BLUE_BOLD + tokens.get(i));
|
System.out.println(ConsoleColors.BLUE_BOLD + temp);
|
||||||
|
tokens.addAll(temp);
|
||||||
|
temp.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addToken(WordType type, String value) {
|
||||||
|
temp.add(new LexToken(type, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addToken(WordType type) {
|
||||||
|
temp.add(new LexToken(type));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Lexer l = new Lexer();
|
Lexer l = new Lexer();
|
||||||
|
|
||||||
LexedList tokens = l.lex("""
|
String assign = """
|
||||||
killua0 hunts 3
|
killua0 hunts 3
|
||||||
killua0 hunts -3.4 #hunts nothing
|
killua0 hunts -3.4 #hunts nothing
|
||||||
killua0 hunts 4
|
|
||||||
killua1 hunts "hallo"
|
killua1 hunts "hallo"
|
||||||
#comment
|
#comment""";
|
||||||
|
String ifs = """
|
||||||
Gon wants false {
|
Gon wants false {
|
||||||
Leorio does say "false"
|
Leorio does say "false"
|
||||||
} wants killua0 > 3 {
|
}
|
||||||
|
wants killua0 > 3 {
|
||||||
Leorio does say "big killua"
|
Leorio does say "big killua"
|
||||||
} got {
|
} got {
|
||||||
Leorio does say "small killua"
|
Leorio does say "small killua"
|
||||||
}
|
}
|
||||||
""");
|
""";
|
||||||
|
|
||||||
|
ArrayList<LexToken> tokens = l.lex(ifs);
|
||||||
|
|
||||||
|
Parser p = new Parser();
|
||||||
|
try {
|
||||||
|
ArrayList<ParseTreeNode> nodes = p.parse(tokens);
|
||||||
|
|
||||||
|
for (ParseTreeNode node : nodes) {
|
||||||
|
System.out.println(node);
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,49 @@
|
||||||
package com.github.nilstrieb.hunterlang.lexer;
|
package com.github.nilstrieb.hunterlang.lexer;
|
||||||
|
|
||||||
public enum WordType {
|
public enum WordType {
|
||||||
ASSIGNMENT, MEMCALL, STRING, NUMBER, BOOL, IF, WANTS, ELSE, BOPEN, BCLOSE, GTHAN, LTHAN, EQUALS, FUNCNAME, FUNCARGS, FUNCRETURN, IOCALL, FUNCCALL, OPERATOR, LIB, MINUS, DEFAULT, PLUS, MULTIPLY, DIVIDE, MOD;
|
ASSIGNMENT(1, 1), //memory, value
|
||||||
|
MEMCALL(1), //adress
|
||||||
|
STRING,
|
||||||
|
NUMBER,
|
||||||
|
BOOL,
|
||||||
|
IF(1), //wants
|
||||||
|
WANTS(2), //condition, body
|
||||||
|
ELSE(1), //body
|
||||||
|
BOPEN(-1), //body, close
|
||||||
|
BCLOSE,
|
||||||
|
GTHAN(1, 1),
|
||||||
|
LTHAN(1, 1),
|
||||||
|
EQUALS(1, 1),
|
||||||
|
FUNCCALL(-1), //args
|
||||||
|
LIB(1), //function
|
||||||
|
MINUS(1, 1),
|
||||||
|
PLUS(1, 1),
|
||||||
|
MULTIPLY(1, 1),
|
||||||
|
DIVIDE(1, 1),
|
||||||
|
MOD(1, 1),
|
||||||
|
NEGATIVE(1),
|
||||||
|
EMPTY;
|
||||||
|
|
||||||
|
private int postArgAmount;
|
||||||
|
private int preArgAmount;
|
||||||
|
|
||||||
|
WordType(int postArgAmount, int preArgAmount) {
|
||||||
|
this.postArgAmount = postArgAmount;
|
||||||
|
this.preArgAmount = preArgAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
WordType(int postArgAmount) {
|
||||||
|
this(postArgAmount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
WordType() {
|
||||||
|
this(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int expectsPostArg() {
|
||||||
|
return postArgAmount;
|
||||||
|
}
|
||||||
|
public int expectsPreArg() {
|
||||||
|
return preArgAmount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.github.nilstrieb.hunterlang.parser;
|
||||||
|
|
||||||
|
public class ParseException extends Exception{
|
||||||
|
public ParseException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.github.nilstrieb.hunterlang.parser;
|
||||||
|
|
||||||
|
import com.github.nilstrieb.hunterlang.lexer.LexToken;
|
||||||
|
import com.github.nilstrieb.hunterlang.lexer.WordType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ParseTreeBodyNode extends ParseTreeNode{
|
||||||
|
private ArrayList<ParseTreeNode> statements;
|
||||||
|
private ArrayList<LexToken> tokens;
|
||||||
|
|
||||||
|
public ParseTreeBodyNode(WordType key, String value) {
|
||||||
|
super(key, value);
|
||||||
|
this.statements = new ArrayList<>();
|
||||||
|
this.tokens = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParseTreeBodyNode(ParseTreeNode node) {
|
||||||
|
this(node.key, node.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<ParseTreeNode> getStatements() {
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addToken(LexToken currentToken) {
|
||||||
|
tokens.add(currentToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString() + statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(String indent) {
|
||||||
|
return super.toString(indent) + statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse() throws ParseException {
|
||||||
|
Parser p = new Parser();
|
||||||
|
statements = p.parse(tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.github.nilstrieb.hunterlang.parser;
|
||||||
|
|
||||||
|
import com.github.nilstrieb.hunterlang.lexer.WordType;
|
||||||
|
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ParseTreeNode {
|
||||||
|
WordType key;
|
||||||
|
String value;
|
||||||
|
ArrayList<ParseTreeNode> children;
|
||||||
|
|
||||||
|
int remainingPreArgs;
|
||||||
|
int remainingPostArgs;
|
||||||
|
|
||||||
|
public ParseTreeNode(WordType key, String value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
children = new ArrayList<>();
|
||||||
|
remainingPostArgs = key.expectsPostArg();
|
||||||
|
remainingPreArgs = key.expectsPreArg();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParseTreeNode() {
|
||||||
|
this(WordType.EMPTY, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<ParseTreeNode> getChildren() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChild(ParseTreeNode n, boolean pre) {
|
||||||
|
children.add(n);
|
||||||
|
if (pre) {
|
||||||
|
remainingPreArgs--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChild(ParseTreeNode n) {
|
||||||
|
addChild(n, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int expectsPostArgCount() {
|
||||||
|
return remainingPostArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean expectsPreArg() {
|
||||||
|
return remainingPreArgs > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(WordType key) {
|
||||||
|
this.key = key;
|
||||||
|
remainingPostArgs = key.expectsPostArg();
|
||||||
|
remainingPreArgs = key.expectsPreArg();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return ConsoleColors.PURPLE_BOLD + "N" + ConsoleColors.BLUE_BOLD + "{name=" +
|
||||||
|
ConsoleColors.RED_BOLD_BRIGHT + key +
|
||||||
|
ConsoleColors.BLUE_BOLD + ", value=" +
|
||||||
|
ConsoleColors.YELLOW + value +
|
||||||
|
ConsoleColors.BLUE_BOLD + ", children=" + printList(children, "") +
|
||||||
|
ConsoleColors.BLUE_BOLD + "}" + ConsoleColors.RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(String indent) {
|
||||||
|
return ConsoleColors.PURPLE_BOLD + indent + "N" + ConsoleColors.BLUE_BOLD + "{name=" +
|
||||||
|
ConsoleColors.RED_BOLD_BRIGHT + key +
|
||||||
|
ConsoleColors.BLUE_BOLD + ", value=" +
|
||||||
|
ConsoleColors.YELLOW + value +
|
||||||
|
ConsoleColors.BLUE_BOLD + ", children=" + printList(children, indent + " ") +
|
||||||
|
ConsoleColors.BLUE_BOLD + "}" + ConsoleColors.RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String printList(ArrayList<ParseTreeNode> list, String indent) {
|
||||||
|
if(list.size() == 0){
|
||||||
|
return "[]";
|
||||||
|
}
|
||||||
|
|
||||||
|
String indentHigher = indent + " ";
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (ParseTreeNode node : list) {
|
||||||
|
sb.append("[\n");
|
||||||
|
sb.append(node.toString(indentHigher));
|
||||||
|
}
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WordType getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,118 @@
|
||||||
package com.github.nilstrieb.hunterlang.parser;
|
package com.github.nilstrieb.hunterlang.parser;
|
||||||
|
|
||||||
public class Parser {
|
import com.github.nilstrieb.hunterlang.hllibrary.FunctionArgLookup;
|
||||||
}
|
import com.github.nilstrieb.hunterlang.lexer.LexToken;
|
||||||
|
import com.github.nilstrieb.hunterlang.lexer.WordType;
|
||||||
|
import com.github.nilstrieb.hunterlang.lib.ConsoleColors;
|
||||||
|
|
||||||
class ParseTreeNode {
|
import java.util.ArrayList;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
public class Parser {
|
||||||
|
|
||||||
|
private ListIterator<LexToken> iterator;
|
||||||
|
|
||||||
|
private LexToken currentToken = null;
|
||||||
|
private LexToken prevToken = null;
|
||||||
|
private LexToken nextToken = null;
|
||||||
|
|
||||||
|
private ParseTreeNode prevNode;
|
||||||
|
|
||||||
|
public ArrayList<ParseTreeNode> parse(ArrayList<LexToken> tokens) throws ParseException {
|
||||||
|
System.out.println(ConsoleColors.GREEN_BACKGROUND + ConsoleColors.BLACK_BOLD + "------START PARSER------" + ConsoleColors.RESET);
|
||||||
|
|
||||||
|
ArrayList<ParseTreeNode> statements = new ArrayList<>();
|
||||||
|
|
||||||
|
iterator = tokens.listIterator();
|
||||||
|
|
||||||
|
currentToken = iterator.next();
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
nextToken = iterator.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
//goes through each statement. On pass -> one statement
|
||||||
|
do {
|
||||||
|
System.out.println(ConsoleColors.GREEN_BRIGHT + "NEXT STATEMENT");
|
||||||
|
|
||||||
|
prevNode = new ParseTreeNode();
|
||||||
|
|
||||||
|
//start with first token
|
||||||
|
ParseTreeNode startNode = currentToken.toNode();
|
||||||
|
|
||||||
|
//if it wants a pre argument theres an error
|
||||||
|
if (currentToken.expectsPreArg()) {
|
||||||
|
throw new ParseException("previous expression expected, doesn't exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate the arguments of the start node, parsing the whole statement
|
||||||
|
getArguments(startNode, true);
|
||||||
|
System.out.println(prevNode);
|
||||||
|
statements.add(prevNode);
|
||||||
|
} while (iterator.hasNext());
|
||||||
|
|
||||||
|
System.out.println(ConsoleColors.GREEN_BACKGROUND + ConsoleColors.BLACK_BOLD + "------STOP PARSER------" + ConsoleColors.RESET);
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getArguments(ParseTreeNode node, boolean isParent) throws ParseException {
|
||||||
|
if (node.getKey() == WordType.MINUS && prevNode.getKey() != WordType.NUMBER) {
|
||||||
|
node.setKey(WordType.NEGATIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.expectsPreArg()) {
|
||||||
|
node.addChild(prevNode, true);
|
||||||
|
}
|
||||||
|
int expectedArg = node.expectsPostArgCount();
|
||||||
|
if (expectedArg == -1) {
|
||||||
|
if (node.getKey() == WordType.FUNCCALL) {
|
||||||
|
//a function. will only support lib functions
|
||||||
|
System.out.println(currentToken);
|
||||||
|
expectedArg = FunctionArgLookup.argLookup(prevToken.getValue(), currentToken.getValue());
|
||||||
|
} else {
|
||||||
|
ParseTreeBodyNode bNode = new ParseTreeBodyNode(node);
|
||||||
|
node = bNode;
|
||||||
|
fillBody(bNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isParent) {
|
||||||
|
prevNode = node;
|
||||||
|
}
|
||||||
|
if (expectedArg == 0) {
|
||||||
|
nextToken();
|
||||||
|
} else {
|
||||||
|
nextToken();
|
||||||
|
for (int i = 0; i < expectedArg; i++) {
|
||||||
|
ParseTreeNode child = currentToken.toNode();
|
||||||
|
getArguments(child, false);
|
||||||
|
node.addChild(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentToken != null && currentToken.expectsPreArg()) {
|
||||||
|
getArguments(currentToken.toNode(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillBody(ParseTreeBodyNode node) throws ParseException {
|
||||||
|
int level = 0;
|
||||||
|
nextToken();
|
||||||
|
while (currentToken.getKey() != WordType.BCLOSE || level != 0) {
|
||||||
|
if (currentToken.getKey() == WordType.BOPEN) {
|
||||||
|
level++;
|
||||||
|
} else if (currentToken.getKey() == WordType.BCLOSE) {
|
||||||
|
level--;
|
||||||
|
}
|
||||||
|
node.addToken(currentToken);
|
||||||
|
nextToken();
|
||||||
|
}
|
||||||
|
node.parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void nextToken() {
|
||||||
|
prevToken = currentToken;
|
||||||
|
currentToken = nextToken;
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
nextToken = iterator.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue