diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-10-22 22:23:01 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-10-22 22:23:01 +0100 |
| commit | d1d0984bc8a157a2f001d3c991dae5c9498cd790 (patch) | |
| tree | 89056dc50059c60c4ce1bf9aa18a8045fb282036 /src/main/java/org/shedlang/compiler/parser | |
| parent | bc94a020433c8b7dc0adaa2a6adf235da9c9b4e9 (diff) | |
Parse function types
Diffstat (limited to 'src/main/java/org/shedlang/compiler/parser')
| -rw-r--r-- | src/main/java/org/shedlang/compiler/parser/Parser.java | 92 |
1 files changed, 84 insertions, 8 deletions
diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java index abd5316e..763d0a01 100644 --- a/src/main/java/org/shedlang/compiler/parser/Parser.java +++ b/src/main/java/org/shedlang/compiler/parser/Parser.java @@ -289,12 +289,7 @@ public class Parser { var params = parseParams(tokens); tokens.skip(TokenType.SYMBOL_PAREN_CLOSE); - Optional<UntypedTypeLevelExpressionNode> effect; - if (tokens.trySkip(TokenType.SYMBOL_BANG)) { - effect = Optional.of(parseTopLevelTypeLevelExpression(tokens)); - } else { - effect = Optional.empty(); - } + var effect = parseFunctionTypeEffect(tokens); tokens.skip(TokenType.SYMBOL_THIN_ARROW); var returnType = parseTopLevelTypeLevelExpression(tokens); @@ -373,6 +368,42 @@ public class Parser { } } + private static UntypedTypeLevelExpressionNode parseFunctionType( + TokenIterator<TokenType> tokens + ) { + var start = tokens.position(); + + tokens.skip(TokenType.KEYWORD_FN); + + tokens.skip(TokenType.SYMBOL_PAREN_OPEN); + var params = parseParamTypes(tokens); + tokens.skip(TokenType.SYMBOL_PAREN_CLOSE); + + var effect = parseFunctionTypeEffect(tokens); + + tokens.skip(TokenType.SYMBOL_THIN_ARROW); + + var returnType = parseTopLevelTypeLevelExpression(tokens); + + var end = tokens.position(); + var source = start.to(end); + + return new UntypedFunctionTypeNode( + params, + effect, + returnType, + source + ); + } + + private static Optional<UntypedTypeLevelExpressionNode> parseFunctionTypeEffect(TokenIterator<TokenType> tokens) { + if (tokens.trySkip(TokenType.SYMBOL_BANG)) { + return Optional.of(parseTopLevelTypeLevelExpression(tokens)); + } else { + return Optional.empty(); + } + } + private static UntypedExpressionNode parseIf(TokenIterator<TokenType> tokens) { var start = tokens.position(); @@ -545,10 +576,10 @@ public class Parser { parseMany( () -> tokens.isNext(TokenType.SYMBOL_PAREN_CLOSE), () -> { - var isNamed = tokens.trySkip(TokenType.SYMBOL_DOT); - var paramStart = tokens.position(); + var isNamed = tokens.trySkip(TokenType.SYMBOL_DOT); + var name = tokens.nextValue(TokenType.IDENTIFIER); tokens.skip(TokenType.SYMBOL_COLON); var type = parseTopLevelTypeLevelExpression(tokens); @@ -572,6 +603,48 @@ public class Parser { return new UntypedParamsNode(positional, named, paramsSource); } + private static UntypedParamTypesNode parseParamTypes(TokenIterator<TokenType> tokens) { + var paramsStart = tokens.position(); + + var positional = new ArrayList<UntypedTypeLevelExpressionNode>(); + var named = new ArrayList<UntypedParamNode>(); + + parseMany( + () -> tokens.isNext(TokenType.SYMBOL_PAREN_CLOSE), + () -> { + var paramStart = tokens.position(); + + var isNamed = tokens.trySkip(TokenType.SYMBOL_DOT); + + if (isNamed) { + var name = tokens.nextValue(TokenType.IDENTIFIER); + tokens.skip(TokenType.SYMBOL_COLON); + var type = parseTopLevelTypeLevelExpression(tokens); + + var paramEnd = tokens.position(); + var paramSource = paramStart.to(paramEnd); + + named.add(new UntypedParamNode(name, type, paramSource)); + } else { + var type = parseTopLevelTypeLevelExpression(tokens); + if (!named.isEmpty()) { + throw new PositionalParamAfterNamedParamError(type.source()); + } + + positional.add(type); + } + + return null; + }, + () -> tokens.trySkip(TokenType.SYMBOL_COMMA) + ); + + var paramsEnd = tokens.position(); + var paramsSource = paramsStart.to(paramsEnd); + + return new UntypedParamTypesNode(positional, named, paramsSource); + } + private static UntypedExpressionNode parsePrimaryExpression(TokenIterator<TokenType> tokens) { return switch (tokens.peek().tokenType()) { @@ -713,6 +786,9 @@ public class Parser { case IDENTIFIER -> parseTypeLevelReference(tokens); + case KEYWORD_FN -> + parseFunctionType(tokens); + case SYMBOL_HASH_PAREN_OPEN -> parseTupleType(tokens); |
