Skip to content

Commit ec77c8b

Browse files
committed
Basic expression parsing
1 parent ed9f84d commit ec77c8b

14 files changed

Lines changed: 686 additions & 162 deletions

File tree

.idea/workspace.xml

Lines changed: 70 additions & 65 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/ko/carbonel/compiler/ParserAssistant.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public void parse() {
7777
matchToken_program();
7878
match(eofToken); // Assert EOF
7979
} catch (StackOverflowError e) {
80-
throw new CompilerError(lexer.peek().location(), "Stack overflow error. You probably gave me code that is too large :c.");
80+
throw new CompilerError(lexer.peek().location(), "Stack overflow error. You probably gave me code that is too large :c.", e);
8181
}
8282
}
8383
}

src/main/java/ko/carbonel/compiler/exception/CompilerError.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ public CompilerError(String message) {
3030
super(message);
3131
}
3232

33+
public CompilerError(FileLocation location, String s, Throwable cause) {
34+
super(buildMessage(location, s), cause);
35+
}
36+
3337
private static String buildMessage(FileLocation start, String message) {
3438
if (start == null || start.isInternal()) return message;
3539
String out = generateLocation(start, message)

src/main/java/ko/carbonel/compiler/generated/AttrTinyRustParser.java

Lines changed: 91 additions & 86 deletions
Large diffs are not rendered by default.

src/main/java/ko/carbonel/compiler/intermediate/tinyRust/TinyRustSymbolTable.java

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import ko.carbonel.json.SerializeClass;
1010

1111
import java.util.*;
12+
import java.util.function.BiConsumer;
13+
import java.util.function.Predicate;
1214

1315
import static ko.carbonel.json.SerializeClass.AST;
1416
import static ko.carbonel.json.SerializeClass.TS;
@@ -64,6 +66,7 @@ public void addClass() {
6466

6567
@CalledByParser
6668
public void addMethod() {
69+
endBlock();
6770
Logger.output("Adding method " + activeMethod.name.lexeme() + " to class " + activeClass.name.lexeme());
6871
activeMethod.setParentScope(activeClass);
6972
activeMethod.block = (BlockStatementEntry) statementStack.pop();
@@ -273,12 +276,34 @@ public void newBlock() {
273276

274277
@CalledByParser
275278
public void endBlock() {
276-
List<StatementEntry> statementList = new ArrayList<>();
277-
while (!(statementStack.peek() instanceof BlockStatementEntry block)) {
278-
statementList.add(statementStack.pop());
279-
}
280-
block.setStatements(statementList);
281-
Logger.output("Block: " + block);
279+
popStatementUntil(BlockStatementEntry.class, (block, statements) -> {
280+
block.setStatements(statements);
281+
Logger.output("Block: " + block);
282+
});
283+
}
284+
285+
private <T extends StatementEntry> void popStatementUntil(Class<T> clazz, BiConsumer<T, List<StatementEntry>> callback) {
286+
popUntil(clazz, callback, statementStack, it->false);
287+
}
288+
289+
/**
290+
* Pop until the top of the stack is an instance of clazz, then call callback with the top of the stack cast to clazz and the popped statements
291+
*
292+
* @param <T> The class to pop until
293+
* @param <S> The type of the stack
294+
* @param clazz The class to pop until
295+
* @param callback The callback to call
296+
* @param stack The stack to pop from
297+
* @param predicate A predicate to test the popped statements - if true, the popped statements are added to the list anyway
298+
*/
299+
private <T extends S, S> void popUntil(Class<T> clazz, BiConsumer<T, List<S>> callback, Stack<S> stack, Predicate<T> predicate) {
300+
List<S> statementList = new ArrayList<>();
301+
while (!(clazz.isInstance(stack.peek())) || predicate.test(clazz.cast(stack.peek()))) statementList.add(0, stack.pop());
302+
callback.accept(clazz.cast(stack.peek()), statementList);
303+
}
304+
305+
private <T extends ExpressionEntry> void popExpressionUntil(Class<T> clazz, BiConsumer<T, List<ExpressionEntry>> callback, Predicate<T> predicate) {
306+
popUntil(clazz, callback, expressionStack, predicate);
282307
}
283308

284309
@CalledByParser
@@ -303,4 +328,24 @@ public void endMain() {
303328
Logger.output("Main end");
304329
activeMethod.block = (BlockStatementEntry) statementStack.pop();
305330
}
331+
332+
@CalledByParser
333+
public void expMethodCall() {
334+
LiteralExpressionEntry id = (LiteralExpressionEntry) expressionStack.pop();
335+
MethodCallExpressionEntry exp = new MethodCallExpressionEntry();
336+
exp.setMethodName(id.literal);
337+
expressionStack.push(exp);
338+
Logger.output("Method call: " + exp);
339+
}
340+
341+
@CalledByParser
342+
public void endMethodCall(){
343+
popExpressionUntil(MethodCallExpressionEntry.class, (methodCall, expressions) -> {
344+
methodCall.setArguments(expressions);
345+
ExpressionEntry pop = expressionStack.pop();
346+
if (pop != methodCall) throw new RuntimeException("Method call not on top of stack");
347+
expressionStack.push(methodCall);
348+
Logger.output("Method call: " + methodCall);
349+
}, it->it.arguments!=null);
350+
}
306351
}

src/main/java/ko/carbonel/compiler/intermediate/tinyRust/ast/BinaryExpressionEntry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
public class BinaryExpressionEntry extends ExpressionEntry {
1111
@SerializeClass(AST) public ExpressionEntry left;
12-
@SerializeClass(AST) public ExpressionEntry right;
1312
@SerializeClass(AST) public TinyRustLexerToken operator;
13+
@SerializeClass(AST) public ExpressionEntry right;
1414
public ExpressionEntry getLeft() {
1515
return left;
1616
}

src/main/java/ko/carbonel/compiler/intermediate/tinyRust/ast/BlockStatementEntry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ public void setStatements(List<StatementEntry> statements) {
1919

2020
@Override
2121
public String toString() {
22-
return "BlockStatementEntry<" + statements.size() + " statements>";
22+
return "BlockStatementEntry<" + (statements == null ? 0 : statements.size()) + " statements>";
2323
}
2424
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package ko.carbonel.compiler.intermediate.tinyRust.ast;
2+
3+
import ko.carbonel.compiler.stream.lexer.tinyRust.model.TinyRustLexerToken;
4+
import ko.carbonel.json.SerializeClass;
5+
6+
import java.util.List;
7+
8+
public class MethodCallExpressionEntry extends ExpressionEntry {
9+
@SerializeClass("ast") public TinyRustLexerToken methodName;
10+
@SerializeClass("ast") public List<ExpressionEntry> arguments;
11+
12+
public TinyRustLexerToken methodName() {
13+
return methodName;
14+
}
15+
16+
public void setMethodName(TinyRustLexerToken methodName) {
17+
this.methodName = methodName;
18+
}
19+
20+
public List<ExpressionEntry> arguments() {
21+
return arguments;
22+
}
23+
24+
public void setArguments(List<ExpressionEntry> arguments) {
25+
this.arguments = arguments;
26+
}
27+
28+
@Override
29+
public String toString() {
30+
return "MethodCall<%s %s>".formatted(methodName, arguments);
31+
}
32+
}

src/main/resources/grammar/main_attr.bnf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ AssignF ::= SimpleChain_star {st.assignLHS()} "=" ExpOr {st.assignRHS()} | {st.a
55
Assign ::= "SELF" {st.expLit(v_0)} AssignF | SimpleVar {st.assignLHS()} "=" ExpOr {st.assignRHS()}
66
Attr ::= Type ":" Vars ";" {st.activeClass.addVariables(false, v_0, v_2)} | "PUBLIC" Type ":" Vars ";" {st.activeClass.addVariables(true, v_1, v_3)}
77
BraceExp ::= "(" ExpOr ")" StaticMethodCallF
8-
ChainFF ::= Args StaticMethodCallF | VarF
8+
ChainFF ::= {st.expMethodCall()} Args {st.endMethodCall()} StaticMethodCallF | VarF
99
Chain ::= "." "ATTR_ID" {st.expChainWith(v_1)} ChainFF
1010
ClassFFF ::= ":" Type { st.activeClass.setSuperClass(v_1) } "{" ClassFF | "{" ClassFF
1111
ClassFF ::= Member_star "}" | "}"
@@ -38,7 +38,7 @@ LocalVars_star ::= Type ":" Vars ";" { st.activeMethod.addVariables(v_0, v_2) }
3838
Member_starF ::= Member_star | "λ"
3939
Member_star ::= Member Member_starF
4040
Member ::= "CREATE" {st.setConstructorActive(v_0)} Params "{" {st.newBlock()} programFFFF {st.addMethod()} | Attr | Method
41-
MethodCall ::= "ATTR_ID" Args StaticMethodCallF
41+
MethodCall ::= "ATTR_ID" {st.expLit(v_0)} {st.expMethodCall()} Args {st.endMethodCall()} StaticMethodCallF
4242
MethodF ::= Stmt_star {st.endBlock()} "}" | {st.endBlock()} "}"
4343
Method ::= "STATIC" "FN" "ATTR_ID" { st.newMethod(true, v_2) } Params "-" ">" ReturnType {st.activeMethod.setReturn(v_7)} "{" {st.newBlock()} programFFFF { st.addMethod() } | "FN" "ATTR_ID" { st.newMethod(false, v_1) } Params "-" ">" ReturnType { st.activeMethod.setReturn(v_6)} "{" {st.newBlock()} programFFFF { st.addMethod() }
4444
NewCallFF ::= "CLASS_ID" Args StaticMethodCallF | PrimType "[" ExpOr "]"

src/test/resources/ast/02.ast.json

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"classEntries": [
3+
{
4+
"name": {"lexeme": "I32"},
5+
"methods": []
6+
},
7+
{
8+
"name": {"lexeme": "Bool"},
9+
"methods": []
10+
},
11+
{
12+
"name": {"lexeme": "Char"},
13+
"methods": []
14+
},
15+
{
16+
"name": {"lexeme": "Str"},
17+
"methods": []
18+
},
19+
{
20+
"name": {"lexeme": "Object"},
21+
"methods": []
22+
},
23+
{
24+
"name": {"lexeme": "IO"},
25+
"methods": []
26+
}
27+
],
28+
"main": {
29+
"block": {"statements": [
30+
{"expression": {
31+
"left": {
32+
"left": {
33+
"left": {"literal": {"lexeme": "a"}},
34+
"right": {
35+
"operator": {"lexeme": "!"},
36+
"expression": {"literal": {"lexeme": "b"}}
37+
},
38+
"operator": {"lexeme": "*"}
39+
},
40+
"right": {"literal": {"lexeme": "c"}},
41+
"operator": {"lexeme": "+"}
42+
},
43+
"right": {"literal": {"lexeme": "d"}},
44+
"operator": {"lexeme": "+"}
45+
}},
46+
{
47+
"lhs": {"literal": {"lexeme": "b"}},
48+
"rhs": {"literal": {"lexeme": "2"}}
49+
},
50+
{
51+
"lhs": {"literal": {"lexeme": "a"}},
52+
"rhs": {"literal": {"lexeme": "1"}}
53+
}
54+
]},
55+
"name": {"lexeme": "main"}
56+
}
57+
}

0 commit comments

Comments
 (0)