implements PR-11.5
This commit is contained in:
parent
eb5cecc573
commit
852ff351ed
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user