From f497e7f884856ca91f3697886db559af070a92ba Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Wed, 5 Jul 2023 21:30:56 +0100 Subject: Parse function definition params --- .../java/org/shedlang/compiler/parser/Parser.java | 35 +++++++++++++++++++--- .../PositionalParamAfterNamedParamError.java | 11 +++++++ .../org/shedlang/compiler/parser/TokenType.java | 1 + .../org/shedlang/compiler/parser/Tokeniser.java | 1 + 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/parser/PositionalParamAfterNamedParamError.java (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java index 69d02075..b1794c6c 100644 --- a/src/main/java/org/shedlang/compiler/parser/Parser.java +++ b/src/main/java/org/shedlang/compiler/parser/Parser.java @@ -178,12 +178,39 @@ public class Parser { } private static UntypedParamsNode parseParams(TokenIterator tokens) { - var start = tokens.position(); + var paramsStart = tokens.position(); - var end = tokens.position(); - var source = start.to(end); + var positional = new ArrayList(); + var named = new ArrayList(); + + parseMany( + () -> tokens.isNext(TokenType.SYMBOL_PAREN_CLOSE), + () -> { + var isNamed = tokens.trySkip(TokenType.SYMBOL_DOT); + + var paramStart = tokens.position(); + + var name = tokens.nextValue(TokenType.IDENTIFIER); + tokens.skip(TokenType.SYMBOL_COLON); + var type = parseTopLevelTypeLevelExpression(tokens); + if (!isNamed && !named.isEmpty()) { + throw new PositionalParamAfterNamedParamError(type.source()); + } + + var paramEnd = tokens.position(); + var paramSource = paramStart.to(paramEnd); + + (isNamed ? named : positional).add(new UntypedParamNode(name, type, paramSource)); + + return null; + }, + () -> tokens.trySkip(TokenType.SYMBOL_COMMA) + ); + + var paramsEnd = tokens.position(); + var paramsSource = paramsStart.to(paramsEnd); - return new UntypedParamsNode(List.of(), List.of(), source); + return new UntypedParamsNode(positional, named, paramsSource); } private static UntypedExpressionNode parsePrimaryExpression(TokenIterator tokens) { diff --git a/src/main/java/org/shedlang/compiler/parser/PositionalParamAfterNamedParamError.java b/src/main/java/org/shedlang/compiler/parser/PositionalParamAfterNamedParamError.java new file mode 100644 index 00000000..e32865f6 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/parser/PositionalParamAfterNamedParamError.java @@ -0,0 +1,11 @@ +package org.shedlang.compiler.parser; + +import org.shedlang.compiler.errors.SourceError; +import org.shedlang.compiler.sources.Source; + +public class PositionalParamAfterNamedParamError extends SourceError { + public PositionalParamAfterNamedParamError(Source source) { + super("Positional param cannot follow named param", source); + } +} + diff --git a/src/main/java/org/shedlang/compiler/parser/TokenType.java b/src/main/java/org/shedlang/compiler/parser/TokenType.java index 21e830f0..2972ce59 100644 --- a/src/main/java/org/shedlang/compiler/parser/TokenType.java +++ b/src/main/java/org/shedlang/compiler/parser/TokenType.java @@ -16,6 +16,7 @@ public enum TokenType { SYMBOL_BANG, SYMBOL_BRACE_OPEN, SYMBOL_BRACE_CLOSE, + SYMBOL_COLON, SYMBOL_COMMA, SYMBOL_DOT, SYMBOL_EQUALS, diff --git a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java index 131462f7..4c06a20a 100644 --- a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java +++ b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java @@ -27,6 +27,7 @@ public class Tokeniser { RegexTokeniser.rule(TokenType.SYMBOL_BANG, "!"), RegexTokeniser.rule(TokenType.SYMBOL_BRACE_OPEN, "\\{"), RegexTokeniser.rule(TokenType.SYMBOL_BRACE_CLOSE, "\\}"), + RegexTokeniser.rule(TokenType.SYMBOL_COLON, ":"), RegexTokeniser.rule(TokenType.SYMBOL_COMMA, ","), RegexTokeniser.rule(TokenType.SYMBOL_DOT, "\\."), RegexTokeniser.rule(TokenType.SYMBOL_EQUALS, "="), -- cgit v1.2.3