summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Uko Kokņevičs2024-08-18 23:45:38 +0800
committerGravatar Uko Kokņevičs2024-08-18 23:45:38 +0800
commitb9c7fbf5e06630076b93cace17863a6d36125e0d (patch)
treee23114ae41cab50d12a51f035f5bacdd239e19ed
parentSome more modularisation (diff)
downloadorang-b9c7fbf5e06630076b93cace17863a6d36125e0d.tar.gz
orang-b9c7fbf5e06630076b93cace17863a6d36125e0d.tar.xz
orang-b9c7fbf5e06630076b93cace17863a6d36125e0d.zip
Added explicit ignored/"underscore" arguments & top-level defs
-rw-r--r--ast/src/main/java/lv/enes/orang/ast/ArgSpec.java8
-rw-r--r--grammar.bnf5
-rw-r--r--lexer/src/main/java/lv/enes/orang/lexer/Lexer.java1
-rw-r--r--lexer/src/main/java/lv/enes/orang/lexer/Token.java1
-rw-r--r--parser/src/main/java/lv/enes/orang/parser/Parser.java21
5 files changed, 28 insertions, 8 deletions
diff --git a/ast/src/main/java/lv/enes/orang/ast/ArgSpec.java b/ast/src/main/java/lv/enes/orang/ast/ArgSpec.java
index e167e8f..7fea2f4 100644
--- a/ast/src/main/java/lv/enes/orang/ast/ArgSpec.java
+++ b/ast/src/main/java/lv/enes/orang/ast/ArgSpec.java
@@ -2,9 +2,16 @@ package lv.enes.orang.ast;
2 2
3public class ArgSpec { 3public class ArgSpec {
4 public final Type type; 4 public final Type type;
5
6 // non-null if NAMED
5 public final String name; 7 public final String name;
6 8
7 private static final ArgSpec NOTHING = new ArgSpec(Type.NOTHING, null); 9 private static final ArgSpec NOTHING = new ArgSpec(Type.NOTHING, null);
10 private static final ArgSpec IGNORED = new ArgSpec(Type.IGNORED, null);
11
12 public static ArgSpec ignored() {
13 return IGNORED;
14 }
8 15
9 public static ArgSpec nothing() { 16 public static ArgSpec nothing() {
10 return NOTHING; 17 return NOTHING;
@@ -20,6 +27,7 @@ public class ArgSpec {
20 } 27 }
21 28
22 public enum Type { 29 public enum Type {
30 IGNORED,
23 NOTHING, 31 NOTHING,
24 NAMED, 32 NAMED,
25 } 33 }
diff --git a/grammar.bnf b/grammar.bnf
index 9ddaffc..0ac58f9 100644
--- a/grammar.bnf
+++ b/grammar.bnf
@@ -2,9 +2,10 @@
2 2
3program ::= (statement ';'?)*; 3program ::= (statement ';'?)*;
4statement ::= definition | expression; 4statement ::= definition | expression;
5definition ::= 'def' def-spec '=' expression; 5definition ::= 'def' def-spec '=' expression
6 | 'def' '_' '=' expression;
6def-spec ::= IDENTIFIER arg-spec*; 7def-spec ::= IDENTIFIER arg-spec*;
7arg-spec ::= IDENTIFIER | '(' ')'; 8arg-spec ::= IDENTIFIER | '(' ')' | '_';
8expression ::= binary-expression | unary-expression; 9expression ::= binary-expression | unary-expression;
9unary-expression ::= unop+ simple-expression; 10unary-expression ::= unop+ simple-expression;
10binary-expression ::= call-expression (binop call-expression)*; 11binary-expression ::= call-expression (binop call-expression)*;
diff --git a/lexer/src/main/java/lv/enes/orang/lexer/Lexer.java b/lexer/src/main/java/lv/enes/orang/lexer/Lexer.java
index 8fec98e..50f4d22 100644
--- a/lexer/src/main/java/lv/enes/orang/lexer/Lexer.java
+++ b/lexer/src/main/java/lv/enes/orang/lexer/Lexer.java
@@ -128,6 +128,7 @@ public class Lexer implements Iterator<Token> {
128 if (isIdentInitial(input.peek())) { 128 if (isIdentInitial(input.peek())) {
129 var ident = readIdentifier(); 129 var ident = readIdentifier();
130 var type = switch (ident) { 130 var type = switch (ident) {
131 case "_" -> Token.Type.UNDERSCORE;
131 case "and" -> Token.Type.AND; 132 case "and" -> Token.Type.AND;
132 case "def" -> Token.Type.DEF; 133 case "def" -> Token.Type.DEF;
133 case "do" -> Token.Type.DO; 134 case "do" -> Token.Type.DO;
diff --git a/lexer/src/main/java/lv/enes/orang/lexer/Token.java b/lexer/src/main/java/lv/enes/orang/lexer/Token.java
index 59626c7..13236dd 100644
--- a/lexer/src/main/java/lv/enes/orang/lexer/Token.java
+++ b/lexer/src/main/java/lv/enes/orang/lexer/Token.java
@@ -37,6 +37,7 @@ public record Token(Type type, String literal) {
37 LET, 37 LET,
38 THEN, 38 THEN,
39 TRUE, 39 TRUE,
40 UNDERSCORE,
40 41
41 // Special chars 42 // Special chars
42 ASTERISK, 43 ASTERISK,
diff --git a/parser/src/main/java/lv/enes/orang/parser/Parser.java b/parser/src/main/java/lv/enes/orang/parser/Parser.java
index 6c86e85..3a2e931 100644
--- a/parser/src/main/java/lv/enes/orang/parser/Parser.java
+++ b/parser/src/main/java/lv/enes/orang/parser/Parser.java
@@ -59,11 +59,11 @@ public class Parser {
59 return new Program(Collections.unmodifiableList(statements)); 59 return new Program(Collections.unmodifiableList(statements));
60 } 60 }
61 61
62 private static boolean isBinaryOp(Token token) { 62 private static boolean isNotBinaryOp(Token token) {
63 return switch (token.type()) { 63 return switch (token.type()) {
64 case ASTERISK, SLASH, PLUS, MINUS, QUESTION_EQUAL, SLASH_EQUAL, GREATER, GREATER_EQUAL, LESS, LESS_EQUAL 64 case ASTERISK, SLASH, PLUS, MINUS, QUESTION_EQUAL, SLASH_EQUAL, GREATER, GREATER_EQUAL, LESS, LESS_EQUAL
65 -> true; 65 -> false;
66 default -> false; 66 default -> true;
67 }; 67 };
68 } 68 }
69 69
@@ -143,6 +143,9 @@ public class Parser {
143 consumeToken(Token.Type.PAREN_LEFT); 143 consumeToken(Token.Type.PAREN_LEFT);
144 consumeToken(Token.Type.PAREN_RIGHT); 144 consumeToken(Token.Type.PAREN_RIGHT);
145 argSpecs.add(ArgSpec.nothing()); 145 argSpecs.add(ArgSpec.nothing());
146 } else if (input.peek().type() == Token.Type.UNDERSCORE) {
147 consumeToken(Token.Type.UNDERSCORE);
148 argSpecs.add(ArgSpec.ignored());
146 } else { 149 } else {
147 break; 150 break;
148 } 151 }
@@ -152,7 +155,7 @@ public class Parser {
152 155
153 private Expression parseBinaryExpression() throws ParserException { 156 private Expression parseBinaryExpression() throws ParserException {
154 var lhs = parseCallExpression(); 157 var lhs = parseCallExpression();
155 if (!isBinaryOp(input.peek())) { 158 if (isNotBinaryOp(input.peek())) {
156 return lhs; 159 return lhs;
157 } 160 }
158 161
@@ -161,7 +164,7 @@ public class Parser {
161 164
162 private Expression parseBinaryExpressionRhs(Expression lhs, BinaryExpression.Operator op) throws ParserException { 165 private Expression parseBinaryExpressionRhs(Expression lhs, BinaryExpression.Operator op) throws ParserException {
163 var rhs = parseCallExpression(); 166 var rhs = parseCallExpression();
164 if (!isBinaryOp(input.peek())) { 167 if (isNotBinaryOp(input.peek())) {
165 return new BinaryExpression(op, lhs, rhs); 168 return new BinaryExpression(op, lhs, rhs);
166 } 169 }
167 170
@@ -187,11 +190,17 @@ public class Parser {
187 return callee; 190 return callee;
188 } 191 }
189 192
190 private Definition parseDefinition() throws ParserException { 193 private Statement parseDefinition() throws ParserException {
191 consumeToken(Token.Type.DEF); 194 consumeToken(Token.Type.DEF);
195 if (maybeConsumeToken(Token.Type.UNDERSCORE)) {
196 consumeToken(Token.Type.EQUAL);
197 return new ExpressionStatement(parseExpression());
198 }
199
192 var defSpec = parseDefSpec(); 200 var defSpec = parseDefSpec();
193 consumeToken(Token.Type.EQUAL); 201 consumeToken(Token.Type.EQUAL);
194 var value = parseExpression(); 202 var value = parseExpression();
203
195 if (defSpec.args().isEmpty()) { 204 if (defSpec.args().isEmpty()) {
196 return new Definition(defSpec.name(), value); 205 return new Definition(defSpec.name(), value);
197 } else { 206 } else {