aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/shedlang/compiler/parser
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-10-22 22:23:01 +0100
committerMichael Williamson <mike@zwobble.org>2023-10-22 22:23:01 +0100
commitd1d0984bc8a157a2f001d3c991dae5c9498cd790 (patch)
tree89056dc50059c60c4ce1bf9aa18a8045fb282036 /src/main/java/org/shedlang/compiler/parser
parentbc94a020433c8b7dc0adaa2a6adf235da9c9b4e9 (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.java92
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);