implements PR-10.1
This commit is contained in:
parent
ba69a64832
commit
e56fe2b9b7
@ -4,8 +4,6 @@ import p.studio.compiler.pbs.ast.PbsAst;
|
|||||||
import p.studio.compiler.pbs.lexer.PbsToken;
|
import p.studio.compiler.pbs.lexer.PbsToken;
|
||||||
import p.studio.compiler.pbs.lexer.PbsTokenKind;
|
import p.studio.compiler.pbs.lexer.PbsTokenKind;
|
||||||
import p.studio.compiler.source.Span;
|
import p.studio.compiler.source.Span;
|
||||||
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
|
||||||
import p.studio.compiler.source.identifiers.FileId;
|
|
||||||
import p.studio.utilities.structures.ReadOnlyList;
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -21,19 +19,15 @@ final class PbsExprParser {
|
|||||||
PbsAst.Block parse(String message);
|
PbsAst.Block parse(String message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final PbsParserContext context;
|
||||||
private final PbsTokenCursor cursor;
|
private final PbsTokenCursor cursor;
|
||||||
private final FileId fileId;
|
|
||||||
private final DiagnosticSink diagnostics;
|
|
||||||
private final BlockParserDelegate blockParserDelegate;
|
private final BlockParserDelegate blockParserDelegate;
|
||||||
|
|
||||||
PbsExprParser(
|
PbsExprParser(
|
||||||
final PbsTokenCursor cursor,
|
final PbsParserContext context,
|
||||||
final FileId fileId,
|
|
||||||
final DiagnosticSink diagnostics,
|
|
||||||
final BlockParserDelegate blockParserDelegate) {
|
final BlockParserDelegate blockParserDelegate) {
|
||||||
this.cursor = cursor;
|
this.context = context;
|
||||||
this.fileId = fileId;
|
this.cursor = context.cursor();
|
||||||
this.diagnostics = diagnostics;
|
|
||||||
this.blockParserDelegate = blockParserDelegate;
|
this.blockParserDelegate = blockParserDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,11 +638,11 @@ final class PbsExprParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Span span(final long start, final long end) {
|
private Span span(final long start, final long end) {
|
||||||
return new Span(fileId, start, end);
|
return context.span(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void report(final PbsToken token, final ParseErrors parseErrors, final String message) {
|
private void report(final PbsToken token, final ParseErrors parseErrors, final String message) {
|
||||||
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics, parseErrors.name(), message, new Span(fileId, token.start(), token.end()));
|
context.report(token, parseErrors, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long parseLongOrDefault(final String text) {
|
private long parseLongOrDefault(final String text) {
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import p.studio.compiler.pbs.ast.PbsAst;
|
|||||||
import p.studio.compiler.pbs.lexer.PbsToken;
|
import p.studio.compiler.pbs.lexer.PbsToken;
|
||||||
import p.studio.compiler.pbs.lexer.PbsTokenKind;
|
import p.studio.compiler.pbs.lexer.PbsTokenKind;
|
||||||
import p.studio.compiler.source.Span;
|
import p.studio.compiler.source.Span;
|
||||||
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
|
||||||
import p.studio.compiler.source.diagnostics.RelatedSpan;
|
import p.studio.compiler.source.diagnostics.RelatedSpan;
|
||||||
import p.studio.compiler.source.identifiers.FileId;
|
import p.studio.compiler.source.identifiers.FileId;
|
||||||
import p.studio.utilities.structures.ReadOnlyList;
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
@ -30,23 +29,18 @@ public final class PbsParser {
|
|||||||
INTERFACE_MODULE
|
INTERFACE_MODULE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final PbsParserContext context;
|
||||||
private final PbsTokenCursor cursor;
|
private final PbsTokenCursor cursor;
|
||||||
private final PbsExprParser exprParser;
|
private final PbsExprParser exprParser;
|
||||||
private final FileId fileId;
|
|
||||||
private final DiagnosticSink diagnostics;
|
|
||||||
private final ParseMode parseMode;
|
|
||||||
private int loopDepth;
|
|
||||||
|
|
||||||
private PbsParser(
|
private PbsParser(
|
||||||
final ReadOnlyList<PbsToken> tokens,
|
final ReadOnlyList<PbsToken> tokens,
|
||||||
final FileId fileId,
|
final FileId fileId,
|
||||||
final DiagnosticSink diagnostics,
|
final p.studio.compiler.source.diagnostics.DiagnosticSink diagnostics,
|
||||||
final ParseMode parseMode) {
|
final ParseMode parseMode) {
|
||||||
this.cursor = new PbsTokenCursor(tokens);
|
this.context = new PbsParserContext(new PbsTokenCursor(tokens), fileId, diagnostics, parseMode);
|
||||||
this.exprParser = new PbsExprParser(cursor, fileId, diagnostics, this::parseExpressionSurfaceBlock);
|
this.cursor = context.cursor();
|
||||||
this.fileId = fileId;
|
this.exprParser = new PbsExprParser(context, this::parseExpressionSurfaceBlock);
|
||||||
this.diagnostics = diagnostics;
|
|
||||||
this.parseMode = parseMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,14 +49,14 @@ public final class PbsParser {
|
|||||||
public static PbsAst.File parse(
|
public static PbsAst.File parse(
|
||||||
final ReadOnlyList<PbsToken> tokens,
|
final ReadOnlyList<PbsToken> tokens,
|
||||||
final FileId fileId,
|
final FileId fileId,
|
||||||
final DiagnosticSink diagnostics) {
|
final p.studio.compiler.source.diagnostics.DiagnosticSink diagnostics) {
|
||||||
return parse(tokens, fileId, diagnostics, ParseMode.ORDINARY);
|
return parse(tokens, fileId, diagnostics, ParseMode.ORDINARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PbsAst.File parse(
|
public static PbsAst.File parse(
|
||||||
final ReadOnlyList<PbsToken> tokens,
|
final ReadOnlyList<PbsToken> tokens,
|
||||||
final FileId fileId,
|
final FileId fileId,
|
||||||
final DiagnosticSink diagnostics,
|
final p.studio.compiler.source.diagnostics.DiagnosticSink diagnostics,
|
||||||
final ParseMode parseMode) {
|
final ParseMode parseMode) {
|
||||||
return new PbsParser(tokens, fileId, diagnostics, parseMode).parseFile();
|
return new PbsParser(tokens, fileId, diagnostics, parseMode).parseFile();
|
||||||
}
|
}
|
||||||
@ -374,7 +368,7 @@ public final class PbsParser {
|
|||||||
final ReadOnlyList<PbsAst.Attribute> attributes,
|
final ReadOnlyList<PbsAst.Attribute> attributes,
|
||||||
final String message) {
|
final String message) {
|
||||||
for (final var attribute : attributes) {
|
for (final var attribute : attributes) {
|
||||||
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
p.studio.compiler.source.diagnostics.Diagnostics.error(context.diagnostics(),
|
||||||
ParseErrors.E_PARSE_ATTRIBUTES_NOT_ALLOWED.name(),
|
ParseErrors.E_PARSE_ATTRIBUTES_NOT_ALLOWED.name(),
|
||||||
message,
|
message,
|
||||||
attribute.span());
|
attribute.span());
|
||||||
@ -382,11 +376,11 @@ public final class PbsParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNotInterfaceMode() {
|
private boolean isNotInterfaceMode() {
|
||||||
return parseMode != ParseMode.INTERFACE_MODULE;
|
return context.parseMode() != ParseMode.INTERFACE_MODULE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOrdinaryMode() {
|
private boolean isOrdinaryMode() {
|
||||||
return parseMode == ParseMode.ORDINARY;
|
return context.parseMode() == ParseMode.ORDINARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.StructDecl parseStructDeclaration(final PbsToken declareToken) {
|
private PbsAst.StructDecl parseStructDeclaration(final PbsToken declareToken) {
|
||||||
@ -690,7 +684,7 @@ public final class PbsParser {
|
|||||||
} else {
|
} else {
|
||||||
final var firstIdSpan = explicitCaseIds.putIfAbsent(explicitValue, intTokenSpan);
|
final var firstIdSpan = explicitCaseIds.putIfAbsent(explicitValue, intTokenSpan);
|
||||||
if (firstIdSpan != null) {
|
if (firstIdSpan != null) {
|
||||||
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
p.studio.compiler.source.diagnostics.Diagnostics.error(context.diagnostics(),
|
||||||
ParseErrors.E_PARSE_DUPLICATE_ENUM_CASE_ID.name(),
|
ParseErrors.E_PARSE_DUPLICATE_ENUM_CASE_ID.name(),
|
||||||
"Duplicate explicit enum identifier '%s'".formatted(explicitValue),
|
"Duplicate explicit enum identifier '%s'".formatted(explicitValue),
|
||||||
intTokenSpan,
|
intTokenSpan,
|
||||||
@ -703,7 +697,7 @@ public final class PbsParser {
|
|||||||
|
|
||||||
final var firstLabelSpan = caseLabels.putIfAbsent(caseName.lexeme(), caseNameSpan);
|
final var firstLabelSpan = caseLabels.putIfAbsent(caseName.lexeme(), caseNameSpan);
|
||||||
if (firstLabelSpan != null) {
|
if (firstLabelSpan != null) {
|
||||||
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics,
|
p.studio.compiler.source.diagnostics.Diagnostics.error(context.diagnostics(),
|
||||||
ParseErrors.E_PARSE_DUPLICATE_ENUM_CASE_LABEL.name(),
|
ParseErrors.E_PARSE_DUPLICATE_ENUM_CASE_LABEL.name(),
|
||||||
"Duplicate enum case label '%s'".formatted(caseName.lexeme()),
|
"Duplicate enum case label '%s'".formatted(caseName.lexeme()),
|
||||||
caseNameSpan,
|
caseNameSpan,
|
||||||
@ -1226,9 +1220,9 @@ public final class PbsParser {
|
|||||||
stepExpression = exprParser.parseExpression();
|
stepExpression = exprParser.parseExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
loopDepth++;
|
context.enterLoop();
|
||||||
final var body = parseBlock();
|
final var body = parseBlock();
|
||||||
loopDepth--;
|
context.exitLoop();
|
||||||
|
|
||||||
return new PbsAst.ForStatement(
|
return new PbsAst.ForStatement(
|
||||||
iterator.lexeme(),
|
iterator.lexeme(),
|
||||||
@ -1254,15 +1248,15 @@ public final class PbsParser {
|
|||||||
|
|
||||||
private PbsAst.Statement parseWhileStatement(final PbsToken whileToken) {
|
private PbsAst.Statement parseWhileStatement(final PbsToken whileToken) {
|
||||||
final var condition = exprParser.parseExpression();
|
final var condition = exprParser.parseExpression();
|
||||||
loopDepth++;
|
context.enterLoop();
|
||||||
final var body = parseBlock();
|
final var body = parseBlock();
|
||||||
loopDepth--;
|
context.exitLoop();
|
||||||
return new PbsAst.WhileStatement(condition, body, span(whileToken.start(), body.span().getEnd()));
|
return new PbsAst.WhileStatement(condition, body, span(whileToken.start(), body.span().getEnd()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PbsAst.Statement parseBreakStatement(final PbsToken breakToken) {
|
private PbsAst.Statement parseBreakStatement(final PbsToken breakToken) {
|
||||||
final var semicolon = consume(PbsTokenKind.SEMICOLON, "Expected ';' after 'break'");
|
final var semicolon = consume(PbsTokenKind.SEMICOLON, "Expected ';' after 'break'");
|
||||||
if (loopDepth <= 0) {
|
if (!context.isInsideLoop()) {
|
||||||
report(breakToken, ParseErrors.E_PARSE_LOOP_CONTROL_OUTSIDE_LOOP,
|
report(breakToken, ParseErrors.E_PARSE_LOOP_CONTROL_OUTSIDE_LOOP,
|
||||||
"'break' is only valid inside loop contexts");
|
"'break' is only valid inside loop contexts");
|
||||||
}
|
}
|
||||||
@ -1271,7 +1265,7 @@ public final class PbsParser {
|
|||||||
|
|
||||||
private PbsAst.Statement parseContinueStatement(final PbsToken continueToken) {
|
private PbsAst.Statement parseContinueStatement(final PbsToken continueToken) {
|
||||||
final var semicolon = consume(PbsTokenKind.SEMICOLON, "Expected ';' after 'continue'");
|
final var semicolon = consume(PbsTokenKind.SEMICOLON, "Expected ';' after 'continue'");
|
||||||
if (loopDepth <= 0) {
|
if (!context.isInsideLoop()) {
|
||||||
report(continueToken, ParseErrors.E_PARSE_LOOP_CONTROL_OUTSIDE_LOOP,
|
report(continueToken, ParseErrors.E_PARSE_LOOP_CONTROL_OUTSIDE_LOOP,
|
||||||
"'continue' is only valid inside loop contexts");
|
"'continue' is only valid inside loop contexts");
|
||||||
}
|
}
|
||||||
@ -1412,14 +1406,14 @@ public final class PbsParser {
|
|||||||
* Builds a source span for the current file.
|
* Builds a source span for the current file.
|
||||||
*/
|
*/
|
||||||
private Span span(final long start, final long end) {
|
private Span span(final long start, final long end) {
|
||||||
return new Span(fileId, start, end);
|
return context.span(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports a parser diagnostic at the given token span.
|
* Reports a parser diagnostic at the given token span.
|
||||||
*/
|
*/
|
||||||
private void report(final PbsToken token, final ParseErrors parseErrors, final String message) {
|
private void report(final PbsToken token, final ParseErrors parseErrors, final String message) {
|
||||||
p.studio.compiler.source.diagnostics.Diagnostics.error(diagnostics, parseErrors.name(), message, new Span(fileId, token.start(), token.end()));
|
context.report(token, parseErrors, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private record ParsedReturnSpec(
|
private record ParsedReturnSpec(
|
||||||
|
|||||||
@ -0,0 +1,61 @@
|
|||||||
|
package p.studio.compiler.pbs.parser;
|
||||||
|
|
||||||
|
import p.studio.compiler.pbs.lexer.PbsToken;
|
||||||
|
import p.studio.compiler.source.Span;
|
||||||
|
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||||
|
import p.studio.compiler.source.identifiers.FileId;
|
||||||
|
|
||||||
|
final class PbsParserContext {
|
||||||
|
private final PbsTokenCursor cursor;
|
||||||
|
private final FileId fileId;
|
||||||
|
private final DiagnosticSink diagnostics;
|
||||||
|
private final PbsParser.ParseMode parseMode;
|
||||||
|
private int loopDepth;
|
||||||
|
|
||||||
|
PbsParserContext(
|
||||||
|
final PbsTokenCursor cursor,
|
||||||
|
final FileId fileId,
|
||||||
|
final DiagnosticSink diagnostics,
|
||||||
|
final PbsParser.ParseMode parseMode) {
|
||||||
|
this.cursor = cursor;
|
||||||
|
this.fileId = fileId;
|
||||||
|
this.diagnostics = diagnostics;
|
||||||
|
this.parseMode = parseMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
PbsTokenCursor cursor() {
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiagnosticSink diagnostics() {
|
||||||
|
return diagnostics;
|
||||||
|
}
|
||||||
|
|
||||||
|
PbsParser.ParseMode parseMode() {
|
||||||
|
return parseMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enterLoop() {
|
||||||
|
loopDepth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void exitLoop() {
|
||||||
|
loopDepth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isInsideLoop() {
|
||||||
|
return loopDepth > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Span span(final long start, final long end) {
|
||||||
|
return new Span(fileId, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void report(final PbsToken token, final ParseErrors parseErrors, final String message) {
|
||||||
|
p.studio.compiler.source.diagnostics.Diagnostics.error(
|
||||||
|
diagnostics,
|
||||||
|
parseErrors.name(),
|
||||||
|
message,
|
||||||
|
span(token.start(), token.end()));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user