From b9c7fbf5e06630076b93cace17863a6d36125e0d Mon Sep 17 00:00:00 2001 From: Uko Kokņevičs Date: Sun, 18 Aug 2024 23:45:38 +0800 Subject: Added explicit ignored/"underscore" arguments & top-level defs --- ast/src/main/java/lv/enes/orang/ast/ArgSpec.java | 8 ++++++++ grammar.bnf | 5 +++-- lexer/src/main/java/lv/enes/orang/lexer/Lexer.java | 1 + lexer/src/main/java/lv/enes/orang/lexer/Token.java | 1 + .../src/main/java/lv/enes/orang/parser/Parser.java | 21 +++++++++++++++------ 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; public class ArgSpec { public final Type type; + + // non-null if NAMED public final String name; private static final ArgSpec NOTHING = new ArgSpec(Type.NOTHING, null); + private static final ArgSpec IGNORED = new ArgSpec(Type.IGNORED, null); + + public static ArgSpec ignored() { + return IGNORED; + } public static ArgSpec nothing() { return NOTHING; @@ -20,6 +27,7 @@ public class ArgSpec { } public enum Type { + IGNORED, NOTHING, NAMED, } diff --git a/grammar.bnf b/grammar.bnf index 9ddaffc..0ac58f9 100644 --- a/grammar.bnf +++ b/grammar.bnf @@ -2,9 +2,10 @@ program ::= (statement ';'?)*; statement ::= definition | expression; -definition ::= 'def' def-spec '=' expression; +definition ::= 'def' def-spec '=' expression + | 'def' '_' '=' expression; def-spec ::= IDENTIFIER arg-spec*; -arg-spec ::= IDENTIFIER | '(' ')'; +arg-spec ::= IDENTIFIER | '(' ')' | '_'; expression ::= binary-expression | unary-expression; unary-expression ::= unop+ simple-expression; binary-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 { if (isIdentInitial(input.peek())) { var ident = readIdentifier(); var type = switch (ident) { + case "_" -> Token.Type.UNDERSCORE; case "and" -> Token.Type.AND; case "def" -> Token.Type.DEF; 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) { LET, THEN, TRUE, + UNDERSCORE, // Special chars 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 { return new Program(Collections.unmodifiableList(statements)); } - private static boolean isBinaryOp(Token token) { + private static boolean isNotBinaryOp(Token token) { return switch (token.type()) { case ASTERISK, SLASH, PLUS, MINUS, QUESTION_EQUAL, SLASH_EQUAL, GREATER, GREATER_EQUAL, LESS, LESS_EQUAL - -> true; - default -> false; + -> false; + default -> true; }; } @@ -143,6 +143,9 @@ public class Parser { consumeToken(Token.Type.PAREN_LEFT); consumeToken(Token.Type.PAREN_RIGHT); argSpecs.add(ArgSpec.nothing()); + } else if (input.peek().type() == Token.Type.UNDERSCORE) { + consumeToken(Token.Type.UNDERSCORE); + argSpecs.add(ArgSpec.ignored()); } else { break; } @@ -152,7 +155,7 @@ public class Parser { private Expression parseBinaryExpression() throws ParserException { var lhs = parseCallExpression(); - if (!isBinaryOp(input.peek())) { + if (isNotBinaryOp(input.peek())) { return lhs; } @@ -161,7 +164,7 @@ public class Parser { private Expression parseBinaryExpressionRhs(Expression lhs, BinaryExpression.Operator op) throws ParserException { var rhs = parseCallExpression(); - if (!isBinaryOp(input.peek())) { + if (isNotBinaryOp(input.peek())) { return new BinaryExpression(op, lhs, rhs); } @@ -187,11 +190,17 @@ public class Parser { return callee; } - private Definition parseDefinition() throws ParserException { + private Statement parseDefinition() throws ParserException { consumeToken(Token.Type.DEF); + if (maybeConsumeToken(Token.Type.UNDERSCORE)) { + consumeToken(Token.Type.EQUAL); + return new ExpressionStatement(parseExpression()); + } + var defSpec = parseDefSpec(); consumeToken(Token.Type.EQUAL); var value = parseExpression(); + if (defSpec.args().isEmpty()) { return new Definition(defSpec.name(), value); } else { -- cgit v1.2.3