Parser for function parameters

This commit is contained in:
Yura Dupyn 2026-02-07 16:37:15 +01:00
parent 5dfa31f27f
commit 24c09c8fbe
2 changed files with 31 additions and 2 deletions

View file

@ -3,6 +3,8 @@ import { ExprScanError, exprStart, ExprStartToken, IdentifierKind, identifierSca
import { char, CodePoint, SourceText, Span } from './source_text';
import { Result } from '../result';
import { Expr, ExprBinding, FieldAssignment, FieldPattern, MatchBranch, Pattern, ProductPattern } from '../expr';
import { UserFunctionDefinition } from '../program';
import { Product } from 'electron';
// CONVENTION: Every parser is responsible to consume whitespace/comments at the end.
// Every parser is not responsible for cleaning up whitespace/comments at the start - only the final `parse` that's exposed to the public.
@ -83,7 +85,7 @@ function tryConsume(cursor: Cursor, expected: CodePoint): boolean {
// TODO: Perhaps when it comes to terminators, we should allow the user of this function to create better contextual errors?
// Parses a delimited sequence of `p` that's terminated by a special character.
function delimitedTerminalSequence<A>(cursor: Cursor, delimiter: CodePoint, terminator: CodePoint, p: Parser<A>): A[] {
function delimitedTerminalSequence<A>(cursor: Cursor, delimiter: CodePoint, terminator: CodePoint | undefined, p: Parser<A>): A[] {
// Let's say the terminator is `.` and delimiter is `,`. This is the grammar for valid sequences
// list(p) :=
// | p
@ -473,3 +475,30 @@ export function parse(source: SourceText): Result<Expr, ParseError> {
}
}
function functionParameters(cursor: Cursor): ProductPattern[] {
const parameters = delimitedTerminalSequence(cursor, DELIMITER_COMMA, undefined, productPattern);
return parameters;
}
export function parseFunctionParameters(source: SourceText): Result<ProductPattern[], ParseError> {
const cursor = new Cursor(source);
try {
skipWhitespaceAndComments(cursor);
const parameters = functionParameters(cursor);
if (!cursor.eof()) {
return Result.error({
tag: "UnexpectedToken",
expected: "EndOfFile",
span: cursor.makeSpan(cursor.currentLocation())
} as ParseError);
}
return Result.ok(parameters);
} catch (e) {
// TODO: This is a bit sketchy. We maybe forced to have "checked" Exceptions for `ParseError` by wrapping it in something that has a proper tag.
return Result.error(e as ParseError);
}
}

View file

@ -110,7 +110,7 @@ export class SourceText {
}
}
export function sourceText(s: string) {
export function sourceText(s: string): SourceText {
return new SourceText(s);
}