From 1886fc2b214bb2c5bfc4cb1ca3d49975c76da0d6 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 23 Dec 2023 12:05:34 +0000 Subject: Parse constructed types --- .../shedlang/compiler/parser/OperationParser.java | 7 +- .../java/org/shedlang/compiler/parser/Parser.java | 111 +++++++++++++++++---- .../parser/TypeLevelOperatorPrecedence.java | 15 +++ 3 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/parser/TypeLevelOperatorPrecedence.java (limited to 'src/main/java/org/shedlang/compiler/parser') diff --git a/src/main/java/org/shedlang/compiler/parser/OperationParser.java b/src/main/java/org/shedlang/compiler/parser/OperationParser.java index 6f3e170e..9a4a25ea 100644 --- a/src/main/java/org/shedlang/compiler/parser/OperationParser.java +++ b/src/main/java/org/shedlang/compiler/parser/OperationParser.java @@ -1,12 +1,11 @@ package org.shedlang.compiler.parser; -import org.shedlang.compiler.ast.untyped.UntypedExpressionNode; import org.shedlang.compiler.tokeniser.TokenIterator; import java.util.stream.Stream; -public interface OperationParser { - OperatorPrecedence precedence(); +public interface OperationParser { + TOperatorPrecedence precedence(); Stream operatorTokenTypes(); - UntypedExpressionNode parse(UntypedExpressionNode left, TokenIterator tokens); + TUntypedExpressionNode parse(TUntypedExpressionNode left, TokenIterator tokens); } diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java index 753a6d75..3c91c561 100644 --- a/src/main/java/org/shedlang/compiler/parser/Parser.java +++ b/src/main/java/org/shedlang/compiler/parser/Parser.java @@ -24,7 +24,10 @@ public class Parser { private Parser() { } - private static class BinaryOperationParser implements OperationParser { + private static class BinaryOperationParser implements OperationParser< + OperatorPrecedence, + UntypedExpressionNode + > { private final TokenType operatorTokenType; private final OperatorPrecedence precedence; private final UntypedBinaryOperator operator; @@ -188,7 +191,10 @@ public class Parser { return new UntypedBreakNode(expression, source); } - private static class CallParser implements OperationParser { + private static class CallParser implements OperationParser< + OperatorPrecedence, + UntypedExpressionNode + > { @Override public OperatorPrecedence precedence() { return OperatorPrecedence.CALL; @@ -216,6 +222,39 @@ public class Parser { } } + private static class ConstructedTypeParser implements OperationParser< + TypeLevelOperatorPrecedence, + UntypedTypeLevelExpressionNode + > { + @Override + public TypeLevelOperatorPrecedence precedence() { + return TypeLevelOperatorPrecedence.CONSTRUCTED_TYPE; + } + + @Override + public Stream operatorTokenTypes() { + return Stream.of(TokenType.SYMBOL_SQUARE_OPEN); + } + + @Override + public UntypedTypeLevelExpressionNode parse(UntypedTypeLevelExpressionNode left, TokenIterator tokens) { + var start = left.source().start(); + + tokens.skip(TokenType.SYMBOL_SQUARE_OPEN); + var args = parseMany( + () -> tokens.isNext(TokenType.SYMBOL_SQUARE_CLOSE), + () -> parseTopLevelTypeLevelExpression(tokens), + () -> tokens.trySkip(TokenType.SYMBOL_COMMA) + ); + tokens.skip(TokenType.SYMBOL_SQUARE_CLOSE); + + var end = tokens.position(); + var source = start.to(end); + + return new UntypedConstructedTypeNode(left, args, source); + } + } + private static UntypedEffectDefinitionNode parseEffectDefinition( TokenIterator tokens ) { @@ -281,7 +320,7 @@ public class Parser { return new UntypedFunctionTypeNode(params, Optional.empty(), returnType, source); } - private static final Map OPERATION_PARSERS = Stream.of( + private static final Map> OPERATION_PARSERS = Stream.of( new FieldAccessParser(), new BinaryOperationParser(TokenType.SYMBOL_EQUALS_EQUALS, OperatorPrecedence.EQUALS, UntypedBinaryOperator.EQUALS), new BinaryOperationParser(TokenType.SYMBOL_BANG_EQUALS, OperatorPrecedence.EQUALS, UntypedBinaryOperator.NOT_EQUAL), @@ -354,7 +393,10 @@ public class Parser { ); } - private static class FieldAccessParser implements OperationParser { + private static class FieldAccessParser implements OperationParser< + OperatorPrecedence, + UntypedExpressionNode + > { @Override public OperatorPrecedence precedence() { return OperatorPrecedence.CALL; @@ -848,6 +890,22 @@ public class Parser { }; } + static UntypedTypeLevelExpressionNode parsePrimaryTypeLevelExpression(TokenIterator tokens) { + return switch (tokens.peek().tokenType()) { + case IDENTIFIER -> + parseTypeLevelReference(tokens); + + case KEYWORD_FN -> + parseFunctionType(tokens); + + case SYMBOL_HASH_PAREN_OPEN -> + parseTupleType(tokens); + + default -> + throw new UnexpectedTokenException("type-level expression", tokens.peek()); + }; + } + private static UntypedFunctionStatementNode parseResume(TokenIterator tokens) { var start = tokens.position(); @@ -996,19 +1054,7 @@ public class Parser { } static UntypedTypeLevelExpressionNode parseTopLevelTypeLevelExpression(TokenIterator tokens) { - return switch (tokens.peek().tokenType()) { - case IDENTIFIER -> - parseTypeLevelReference(tokens); - - case KEYWORD_FN -> - parseFunctionType(tokens); - - case SYMBOL_HASH_PAREN_OPEN -> - parseTupleType(tokens); - - default -> - throw new UnexpectedTokenException("type-level expression", tokens.peek()); - }; + return parseTypeLevelExpression(tokens, Optional.empty()); } public static UntypedNamespaceNode parseNamespace( @@ -1212,6 +1258,37 @@ public class Parser { return new UntypedTupleTypeNode(elements, source); } + private static final Map> TYPE_LEVEL_OPERATION_PARSERS = Stream.of( + new ConstructedTypeParser() + ) + .flatMap(parser -> + parser.operatorTokenTypes().map(tokenType -> Map.entry(tokenType, parser)) + ) + .collect(Collectors.toMap( + x -> x.getKey(), + x -> x.getValue() + )); + + private static UntypedTypeLevelExpressionNode parseTypeLevelExpression( + TokenIterator tokens, + Optional parentPrecedence + ) { + var left = parsePrimaryTypeLevelExpression(tokens); + + while (true) { + var operationParser = TYPE_LEVEL_OPERATION_PARSERS.get(tokens.peek().tokenType()); + if ( + operationParser == null || ( + parentPrecedence.isPresent() && + operationParser.precedence().precedence() <= parentPrecedence.get().precedence() + ) + ) { + return left; + } + left = operationParser.parse(left, tokens); + } + } + private static Optional> parseTypeLevelParamsOptional( TokenIterator tokens ) { diff --git a/src/main/java/org/shedlang/compiler/parser/TypeLevelOperatorPrecedence.java b/src/main/java/org/shedlang/compiler/parser/TypeLevelOperatorPrecedence.java new file mode 100644 index 00000000..2068b2ad --- /dev/null +++ b/src/main/java/org/shedlang/compiler/parser/TypeLevelOperatorPrecedence.java @@ -0,0 +1,15 @@ +package org.shedlang.compiler.parser; + +public enum TypeLevelOperatorPrecedence { + CONSTRUCTED_TYPE(1); + + private final int precedence; + + TypeLevelOperatorPrecedence(int precedence) { + this.precedence = precedence; + } + + public int precedence() { + return precedence; + } +} -- cgit v1.2.3