diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/parser/PbsExprParser.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/parser/PbsExprParser.java index a42aa961..909d4bb5 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/parser/PbsExprParser.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/parser/PbsExprParser.java @@ -4,16 +4,11 @@ import p.studio.compiler.pbs.ast.PbsAst; import p.studio.compiler.pbs.lexer.PbsToken; import p.studio.compiler.pbs.lexer.PbsTokenKind; import p.studio.compiler.source.Span; -import p.studio.utilities.structures.ReadOnlyList; - -import java.util.ArrayList; /** - * Dedicated expression parser for PBS. + * Dedicated expression parser for PBS precedence and orchestration. */ final class PbsExprParser { - private static final int MAX_TUPLE_LITERAL_ARITY = 6; - @FunctionalInterface interface BlockParserDelegate { PbsAst.Block parse(String message); @@ -33,9 +28,6 @@ final class PbsExprParser { this.primaryParser = new PbsExprPrimaryParser(context, this::parseExpression, controlFlowParser::parseErrorPath); } - /** - * Entry point for expression parsing. - */ PbsAst.Expression parseExpression() { return controlFlowParser.parseHandle(); } @@ -44,32 +36,6 @@ final class PbsExprParser { return parseApply(); } - private PbsAst.Expression parseHandle() { - return controlFlowParser.parseHandle(); - } - - /** - * Parses right-associative else extraction: {@code a else (b else c)}. - */ - private PbsAst.Expression parseElse() { - return controlFlowParser.parseElse(); - } - - private PbsAst.Expression parseIfExpression() { - return controlFlowParser.parseIfExpression(); - } - - private PbsAst.IfExpr parseIfExpressionFromToken(final PbsToken ifToken) { - return controlFlowParser.parseIfExpressionFromToken(ifToken); - } - - private PbsAst.Expression parseSwitchExpression() { - return controlFlowParser.parseSwitchExpression(); - } - - /** - * Parses right-associative apply expressions. - */ private PbsAst.Expression parseApply() { final var left = parseOr(); if (!cursor.match(PbsTokenKind.APPLY)) { @@ -85,7 +51,10 @@ final class PbsExprParser { while (cursor.match(PbsTokenKind.OR_OR, PbsTokenKind.OR)) { final var operator = cursor.previous(); final var right = parseAnd(); - expression = new PbsAst.BinaryExpr(operator.lexeme(), expression, right, + expression = new PbsAst.BinaryExpr( + operator.lexeme(), + expression, + right, span(expression.span().getStart(), right.span().getEnd())); } return expression; @@ -96,7 +65,10 @@ final class PbsExprParser { while (cursor.match(PbsTokenKind.AND_AND, PbsTokenKind.AND)) { final var operator = cursor.previous(); final var right = parseEquality(); - expression = new PbsAst.BinaryExpr(operator.lexeme(), expression, right, + expression = new PbsAst.BinaryExpr( + operator.lexeme(), + expression, + right, span(expression.span().getStart(), right.span().getEnd())); } return expression; @@ -107,10 +79,13 @@ final class PbsExprParser { if (cursor.match(PbsTokenKind.EQUAL_EQUAL, PbsTokenKind.BANG_EQUAL)) { final var operator = cursor.previous(); final var right = parseComparison(); - expression = new PbsAst.BinaryExpr(operator.lexeme(), expression, right, + expression = new PbsAst.BinaryExpr( + operator.lexeme(), + expression, + right, span(expression.span().getStart(), right.span().getEnd())); if (cursor.check(PbsTokenKind.EQUAL_EQUAL) || cursor.check(PbsTokenKind.BANG_EQUAL)) { - report(cursor.peek(), ParseErrors.E_PARSE_NON_ASSOC, "Chained equality is not allowed"); + context.report(cursor.peek(), ParseErrors.E_PARSE_NON_ASSOC, "Chained equality is not allowed"); while (cursor.match(PbsTokenKind.EQUAL_EQUAL, PbsTokenKind.BANG_EQUAL)) { parseComparison(); } @@ -124,11 +99,16 @@ final class PbsExprParser { if (cursor.match(PbsTokenKind.LESS, PbsTokenKind.LESS_EQUAL, PbsTokenKind.GREATER, PbsTokenKind.GREATER_EQUAL)) { final var operator = cursor.previous(); final var right = parseAs(); - expression = new PbsAst.BinaryExpr(operator.lexeme(), expression, right, + expression = new PbsAst.BinaryExpr( + operator.lexeme(), + expression, + right, span(expression.span().getStart(), right.span().getEnd())); - if (cursor.check(PbsTokenKind.LESS) || cursor.check(PbsTokenKind.LESS_EQUAL) - || cursor.check(PbsTokenKind.GREATER) || cursor.check(PbsTokenKind.GREATER_EQUAL)) { - report(cursor.peek(), ParseErrors.E_PARSE_NON_ASSOC, "Chained comparison is not allowed"); + if (cursor.check(PbsTokenKind.LESS) + || cursor.check(PbsTokenKind.LESS_EQUAL) + || cursor.check(PbsTokenKind.GREATER) + || cursor.check(PbsTokenKind.GREATER_EQUAL)) { + context.report(cursor.peek(), ParseErrors.E_PARSE_NON_ASSOC, "Chained comparison is not allowed"); while (cursor.match(PbsTokenKind.LESS, PbsTokenKind.LESS_EQUAL, PbsTokenKind.GREATER, PbsTokenKind.GREATER_EQUAL)) { parseAs(); } @@ -140,8 +120,11 @@ final class PbsExprParser { private PbsAst.Expression parseAs() { var expression = parseTerm(); if (cursor.match(PbsTokenKind.AS)) { - final var contract = consume(PbsTokenKind.IDENTIFIER, "Expected contract identifier after 'as'"); - expression = new PbsAst.AsExpr(expression, contract.lexeme(), span(expression.span().getStart(), contract.end())); + final var contract = context.consume(PbsTokenKind.IDENTIFIER, "Expected contract identifier after 'as'"); + expression = new PbsAst.AsExpr( + expression, + contract.lexeme(), + span(expression.span().getStart(), contract.end())); } return expression; } @@ -151,7 +134,10 @@ final class PbsExprParser { while (cursor.match(PbsTokenKind.PLUS, PbsTokenKind.MINUS)) { final var operator = cursor.previous(); final var right = parseFactor(); - expression = new PbsAst.BinaryExpr(operator.lexeme(), expression, right, + expression = new PbsAst.BinaryExpr( + operator.lexeme(), + expression, + right, span(expression.span().getStart(), right.span().getEnd())); } return expression; @@ -162,7 +148,10 @@ final class PbsExprParser { while (cursor.match(PbsTokenKind.STAR, PbsTokenKind.SLASH, PbsTokenKind.PERCENT)) { final var operator = cursor.previous(); final var right = parseUnary(); - expression = new PbsAst.BinaryExpr(operator.lexeme(), expression, right, + expression = new PbsAst.BinaryExpr( + operator.lexeme(), + expression, + right, span(expression.span().getStart(), right.span().getEnd())); } return expression; @@ -177,100 +166,7 @@ final class PbsExprParser { return primaryParser.parsePostfix(); } - private PbsAst.Expression parsePostfix() { - return primaryParser.parsePostfix(); - } - - private PbsAst.Expression parsePrimary() { - return primaryParser.parsePrimary(); - } - - private PbsAst.Expression parseParenthesizedPrimary(final PbsToken open) { - return primaryParser.parseParenthesizedPrimary(open); - } - - private PbsAst.SwitchPattern parseSwitchPattern() { - return controlFlowParser.parseSwitchPattern(); - } - - private PbsAst.Expression parseLiteralPatternExpression() { - return controlFlowParser.parseLiteralPatternExpression(); - } - - private PbsAst.HandlePattern parseHandlePattern() { - return controlFlowParser.parseHandlePattern(); - } - - private PbsAst.ErrorPath parseErrorPath() { - return controlFlowParser.parseErrorPath(); - } - - private PbsAst.Block parseSurfaceBlock(final String message) { - return context.parseSurfaceBlock(message); - } - - private PbsToken consume(final PbsTokenKind kind, final String message) { - return context.consume(kind, message); - } - - private PbsToken consumeMemberName(final String message) { - return context.consumeMemberName(message); - } - private Span span(final long start, final long end) { return context.span(start, end); } - - private void report(final PbsToken token, final ParseErrors parseErrors, final String message) { - context.report(token, parseErrors, message); - } - - private long parseLongOrDefault(final String text) { - try { - return Long.parseLong(text); - } catch (NumberFormatException ignored) { - return 0L; - } - } - - private int parseIntOrDefault(final String text) { - try { - return Integer.parseInt(text); - } catch (NumberFormatException ignored) { - return 0; - } - } - - private double parseDoubleOrDefault(final String text) { - try { - return Double.parseDouble(text); - } catch (NumberFormatException ignored) { - return 0.0; - } - } - - private String unescapeString(final String lexeme) { - if (lexeme.length() < 2) { - return ""; - } - final var raw = lexeme.substring(1, lexeme.length() - 1); - final var sb = new StringBuilder(raw.length()); - for (int i = 0; i < raw.length(); i++) { - final char c = raw.charAt(i); - if (c != '\\' || i + 1 >= raw.length()) { - sb.append(c); - continue; - } - final char next = raw.charAt(++i); - switch (next) { - case 'n' -> sb.append('\n'); - case 'r' -> sb.append('\r'); - case 't' -> sb.append('\t'); - case '"' -> sb.append('"'); - case '\\' -> sb.append('\\'); - default -> sb.append('\\').append(next); - } - } - return sb.toString(); - } }