aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/shedlang/compiler/parser
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2025-01-08 19:14:03 +0000
committerMichael Williamson <mike@zwobble.org>2025-01-09 20:36:42 +0000
commit3666a4af2eb35177eecd557d2a75f4bac9da75b9 (patch)
treea85230de832bc7f970dd89aaa6bb2da6ea5875f4 /src/main/java/org/shedlang/compiler/parser
parent1e6e1f7bb8776fc013f76828ed8df3f9297d095b (diff)
Use source text to implement FileFragmentSource
Diffstat (limited to 'src/main/java/org/shedlang/compiler/parser')
-rw-r--r--src/main/java/org/shedlang/compiler/parser/OperationParser.java7
-rw-r--r--src/main/java/org/shedlang/compiler/parser/Parser.java358
-rw-r--r--src/main/java/org/shedlang/compiler/parser/SourceParser.java10
-rw-r--r--src/main/java/org/shedlang/compiler/parser/Tokeniser.java14
4 files changed, 210 insertions, 179 deletions
diff --git a/src/main/java/org/shedlang/compiler/parser/OperationParser.java b/src/main/java/org/shedlang/compiler/parser/OperationParser.java
index 9a4a25ea..e56b3ffe 100644
--- a/src/main/java/org/shedlang/compiler/parser/OperationParser.java
+++ b/src/main/java/org/shedlang/compiler/parser/OperationParser.java
@@ -1,11 +1,16 @@
package org.shedlang.compiler.parser;
import org.shedlang.compiler.tokeniser.TokenIterator;
+import org.zwobble.sourcetext.SourcePosition;
import java.util.stream.Stream;
public interface OperationParser<TOperatorPrecedence, TUntypedExpressionNode> {
TOperatorPrecedence precedence();
Stream<TokenType> operatorTokenTypes();
- TUntypedExpressionNode parse(TUntypedExpressionNode left, TokenIterator<TokenType> tokens);
+ TUntypedExpressionNode parse(
+ SourcePosition start,
+ TUntypedExpressionNode left,
+ TokenIterator<TokenType> tokens
+ );
}
diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java
index 680ead15..cda360e3 100644
--- a/src/main/java/org/shedlang/compiler/parser/Parser.java
+++ b/src/main/java/org/shedlang/compiler/parser/Parser.java
@@ -2,12 +2,15 @@ package org.shedlang.compiler.parser;
import org.shedlang.compiler.ast.untyped.*;
import org.shedlang.compiler.parser.errors.*;
+import org.shedlang.compiler.sources.FileFragmentSource;
import org.shedlang.compiler.sources.Source;
import org.shedlang.compiler.tokeniser.TokenIterator;
import org.shedlang.compiler.tokeniser.UnexpectedTokenException;
import org.shedlang.compiler.types.NamespaceName;
import org.shedlang.compiler.types.Visibility;
import org.shedlang.compiler.util.Iterables;
+import org.zwobble.sourcetext.SourcePosition;
+import org.zwobble.sourcetext.SourceRange;
import java.math.BigInteger;
import java.util.ArrayList;
@@ -53,27 +56,29 @@ public class Parser {
}
@Override
- public UntypedExpressionNode parse(UntypedExpressionNode left, TokenIterator<TokenType> tokens) {
- var start = left.source().start();
-
+ public UntypedExpressionNode parse(
+ SourcePosition start,
+ UntypedExpressionNode left,
+ TokenIterator<TokenType> tokens
+ ) {
tokens.skip(operatorTokenType);
var right = parseSubExpression(tokens, precedence);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var sourceRange = new FileFragmentSource(start.to(end));
return new UntypedBinaryOperationNode(
operator,
left,
right,
- source
+ sourceRange
);
}
}
private static UntypedArgsNode parseArgs(TokenIterator<TokenType> tokens) {
- var argsStart = tokens.position();
+ var argsStart = tokens.startPosition();
var positional = new ArrayList<UntypedExpressionNode>();
var named = new ArrayList<UntypedNamedArgNode>();
@@ -82,14 +87,14 @@ public class Parser {
() -> tokens.isNext(TokenType.SYMBOL_PAREN_CLOSE),
() -> {
if (tokens.trySkip(TokenType.SYMBOL_DOT)) {
- var argStart = tokens.position();
+ var argStart = tokens.startPosition();
var argName = tokens.nextValue(TokenType.IDENTIFIER);
tokens.skip(TokenType.SYMBOL_EQUALS);
var expression = parseTopLevelExpression(tokens);
- var argEnd = tokens.position();
- var argSource = argStart.to(argEnd);
+ var argEnd = tokens.endPosition();
+ var argSource = new FileFragmentSource(argStart.to(argEnd));
named.add(new UntypedNamedArgNode(argName, expression, argSource));
} else {
@@ -104,14 +109,14 @@ public class Parser {
() -> tokens.trySkip(TokenType.SYMBOL_COMMA)
);
- var argsEnd = tokens.position();
- var argsSource = argsStart.to(argsEnd);
+ var argsEnd = tokens.endPosition();
+ var argsSource = new FileFragmentSource(argsStart.to(argsEnd));
return new UntypedArgsNode(positional, named, argsSource);
}
private static UntypedAssignNode parseAssign(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var target = parseTarget(tokens);
@@ -121,20 +126,20 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_SEMICOLON);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedAssignNode(target, expression, source);
}
private static UntypedBlockNode parseBlock(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.SYMBOL_BRACE_OPEN);
if (tokens.trySkip(TokenType.SYMBOL_BRACE_CLOSE)) {
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedBlockNode(List.of(), source);
}
@@ -152,30 +157,30 @@ public class Parser {
) {
tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
- var end = tokens.position();
+ var end = tokens.endPosition();
var source = start.to(end);
- return new UntypedBlockNode(body, source);
+ return new UntypedBlockNode(body, new FileFragmentSource(source));
}
}
}
private static UntypedExpressionNode parseBoolLiteral(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var value = tokens.trySkip(TokenType.KEYWORD_TRUE);
if (!value) {
tokens.skip(TokenType.KEYWORD_FALSE);
}
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedBoolLiteralNode(value, source);
}
private static UntypedFunctionStatementNode parseBreak(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_BREAK);
@@ -185,8 +190,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_SEMICOLON);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedBreakNode(expression, source);
}
@@ -210,9 +215,11 @@ public class Parser {
}
@Override
- public UntypedExpressionNode parse(UntypedExpressionNode left, TokenIterator<TokenType> tokens) {
- var start = left.source().start();
-
+ public UntypedExpressionNode parse(
+ SourcePosition start,
+ UntypedExpressionNode left,
+ TokenIterator<TokenType> tokens
+ ) {
var hasEffects = tokens.trySkip(TokenType.SYMBOL_BANG);
var typeLevelArgs = parseTypeLevelArgsOptional(tokens);
@@ -221,8 +228,8 @@ public class Parser {
var args = parseArgs(tokens);
tokens.skip(TokenType.SYMBOL_PAREN_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedCallNode(
left,
@@ -249,9 +256,11 @@ public class Parser {
}
@Override
- public UntypedTypeLevelExpressionNode parse(UntypedTypeLevelExpressionNode left, TokenIterator<TokenType> tokens) {
- var start = left.source().start();
-
+ public UntypedTypeLevelExpressionNode parse(
+ SourcePosition start,
+ UntypedTypeLevelExpressionNode left,
+ TokenIterator<TokenType> tokens
+ ) {
tokens.skip(TokenType.SYMBOL_SQUARE_OPEN);
var args = parseMany(
() -> tokens.isNext(TokenType.SYMBOL_SQUARE_CLOSE),
@@ -260,8 +269,8 @@ public class Parser {
);
tokens.skip(TokenType.SYMBOL_SQUARE_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedConstructedTypeNode(left, args, source);
}
@@ -270,7 +279,7 @@ public class Parser {
private static UntypedEffectDefinitionNode parseEffectDefinition(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var visibility = parseVisibility(tokens);
@@ -288,8 +297,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedEffectDefinitionNode(name, visibility, functions, source);
}
@@ -297,7 +306,7 @@ public class Parser {
private static UntypedEffectDefinitionMethodNode parseEffectDefinitionField(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_FUN);
@@ -307,8 +316,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_SEMICOLON);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedEffectDefinitionMethodNode(name, type, source);
}
@@ -316,7 +325,7 @@ public class Parser {
private static UntypedFunctionTypeNode parseEffectDefinitionFieldType(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.SYMBOL_PAREN_OPEN);
var params = parseParamTypes(tokens);
@@ -326,8 +335,8 @@ public class Parser {
var returnType = parseTopLevelTypeLevelExpression(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedFunctionTypeNode(params, Optional.empty(), returnType, source);
}
@@ -352,6 +361,7 @@ public class Parser {
TokenIterator<TokenType> tokens,
Optional<OperatorPrecedence> parentPrecedence
) {
+ var start = tokens.startPosition();
var left = parsePrimaryExpression(tokens);
while (true) {
@@ -364,12 +374,12 @@ public class Parser {
) {
return left;
}
- left = operationParser.parse(left, tokens);
+ left = operationParser.parse(start, left, tokens);
}
}
private static UntypedFunctionStatementNode parseExpressionStatement(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var expression = parseTopLevelExpression(tokens);
@@ -377,8 +387,8 @@ public class Parser {
? expressionStatementBehaviour(branchingExpression.exhaustiveChildBlocks()) == UntypedFunctionStatementBehaviour.BLOCK_RETURN
: !tokens.trySkip(TokenType.SYMBOL_SEMICOLON);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return isReturn
? new UntypedBlockReturnNode(expression, source)
@@ -406,7 +416,7 @@ public class Parser {
}
private static UntypedFunctionDefinitionNode parseFunctionDefinition(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var visibility = parseVisibility(tokens);
@@ -417,8 +427,8 @@ public class Parser {
var body = parseBlock(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedFunctionDefinitionNode(
name,
@@ -432,7 +442,7 @@ public class Parser {
private static UntypedExpressionNode parseFunctionExpression(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_FN);
@@ -440,8 +450,8 @@ public class Parser {
var body = parseBlock(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedFunctionExpressionNode(
signature,
@@ -451,7 +461,7 @@ public class Parser {
}
private static UntypedFunctionStatementNode parseFunctionReturn(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_RETURN);
@@ -461,8 +471,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_SEMICOLON);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedFunctionReturnNode(expression, source);
}
@@ -470,7 +480,7 @@ public class Parser {
static UntypedFunctionSignatureNode parseFunctionSignature(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var typeLevelParams = parseTypeLevelParamsOptional(tokens);
@@ -482,8 +492,8 @@ public class Parser {
var returnType = parseFunctionSignatureReturnType(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedFunctionSignatureNode(
typeLevelParams,
@@ -555,7 +565,7 @@ public class Parser {
private static UntypedTypeLevelExpressionNode parseFunctionType(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_FN);
@@ -569,8 +579,8 @@ public class Parser {
var returnType = parseTopLevelTypeLevelExpression(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedFunctionTypeNode(
params,
@@ -589,7 +599,7 @@ public class Parser {
}
private static UntypedExpressionNode parseIf(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var conditionalBranches = new ArrayList<UntypedConditionalBranchNode>();
var elseBody = Optional.<UntypedBlockNode>empty();
@@ -609,18 +619,21 @@ public class Parser {
}
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedIfNode(
conditionalBranches,
- elseBody.orElseGet(() -> new UntypedBlockNode(List.of(), end)),
+ elseBody.orElseGet(() -> new UntypedBlockNode(
+ List.of(),
+ new FileFragmentSource(end.to(end))
+ )),
source
);
}
private static UntypedConditionalBranchNode parseConditionalBranch(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_IF);
@@ -630,14 +643,14 @@ public class Parser {
var body = parseBlock(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedConditionalBranchNode(condition, body, source);
}
private static UntypedImportNode parseImport(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_IMPORT);
@@ -645,21 +658,21 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_SEMICOLON);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedImportNode(namespaceName, source);
}
private static UntypedExpressionNode parseInt(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var string = tokens.nextValue(TokenType.INT);
var value = new BigInteger(string);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
if (string.length() > 1 && string.startsWith("0")) {
throw new IntLiteralCannotHaveLeadingZeroesError(source);
@@ -731,15 +744,17 @@ public class Parser {
}
@Override
- public UntypedExpressionNode parse(UntypedExpressionNode left, TokenIterator<TokenType> tokens) {
- var start = left.source().start();
-
+ public UntypedExpressionNode parse(
+ SourcePosition start,
+ UntypedExpressionNode left,
+ TokenIterator<TokenType> tokens
+ ) {
tokens.skip(TokenType.SYMBOL_DOT);
var memberName = tokens.nextValue(TokenType.IDENTIFIER);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedMemberAccessNode(left, memberName, source);
}
@@ -797,7 +812,7 @@ public class Parser {
}
private static UntypedParamsNode parseParams(TokenIterator<TokenType> tokens) {
- var paramsStart = tokens.position();
+ var paramsStart = tokens.startPosition();
var positional = new ArrayList<UntypedParamNode>();
var named = new ArrayList<UntypedParamNode>();
@@ -805,7 +820,7 @@ public class Parser {
parseMany(
() -> tokens.isNext(TokenType.SYMBOL_PAREN_CLOSE),
() -> {
- var paramStart = tokens.position();
+ var paramStart = tokens.startPosition();
var isNamed = tokens.trySkip(TokenType.SYMBOL_DOT);
@@ -815,8 +830,8 @@ public class Parser {
? Optional.of(parseTopLevelTypeLevelExpression(tokens))
: Optional.<UntypedTypeLevelExpressionNode>empty();
- var paramEnd = tokens.position();
- var paramSource = paramStart.to(paramEnd);
+ var paramEnd = tokens.endPosition();
+ var paramSource = new FileFragmentSource(paramStart.to(paramEnd));
if (!isNamed && !named.isEmpty()) {
throw new PositionalParamAfterNamedParamError(paramSource);
@@ -829,14 +844,14 @@ public class Parser {
() -> tokens.trySkip(TokenType.SYMBOL_COMMA)
);
- var paramsEnd = tokens.position();
- var paramsSource = paramsStart.to(paramsEnd);
+ var paramsEnd = tokens.endPosition();
+ var paramsSource = new FileFragmentSource(paramsStart.to(paramsEnd));
return new UntypedParamsNode(positional, named, paramsSource);
}
private static UntypedFunctionTypeParamsNode parseParamTypes(TokenIterator<TokenType> tokens) {
- var paramsStart = tokens.position();
+ var paramsStart = tokens.startPosition();
var positional = new ArrayList<UntypedTypeLevelExpressionNode>();
var named = new ArrayList<UntypedFunctionTypeNamedParamNode>();
@@ -844,7 +859,7 @@ public class Parser {
parseMany(
() -> tokens.isNext(TokenType.SYMBOL_PAREN_CLOSE),
() -> {
- var paramStart = tokens.position();
+ var paramStart = tokens.startPosition();
var isNamed = tokens.trySkip(TokenType.SYMBOL_DOT);
@@ -853,8 +868,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_COLON);
var type = parseTopLevelTypeLevelExpression(tokens);
- var paramEnd = tokens.position();
- var paramSource = paramStart.to(paramEnd);
+ var paramEnd = tokens.endPosition();
+ var paramSource = new FileFragmentSource(paramStart.to(paramEnd));
named.add(new UntypedFunctionTypeNamedParamNode(name, type, paramSource));
} else {
@@ -871,10 +886,10 @@ public class Parser {
() -> tokens.trySkip(TokenType.SYMBOL_COMMA)
);
- var paramsEnd = tokens.position();
+ var paramsEnd = tokens.endPosition();
var paramsSource = paramsStart.to(paramsEnd);
- return new UntypedFunctionTypeParamsNode(positional, named, paramsSource);
+ return new UntypedFunctionTypeParamsNode(positional, named, new FileFragmentSource(paramsSource));
}
private static UntypedExpressionNode parsePrimaryExpression(TokenIterator<TokenType> tokens) {
@@ -922,7 +937,7 @@ public class Parser {
}
private static UntypedFunctionStatementNode parseResume(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_RESUME);
@@ -932,38 +947,44 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_SEMICOLON);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedResumeNode(expression, source);
}
private static UntypedExpressionNode parseStringLiteral(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
- var tokenValue = tokens.nextValue(TokenType.STRING);
- var escapedValue = tokenValue.substring(1, tokenValue.length() - 1);
- var unescapedValue = unescape(escapedValue, start);
+ var token = tokens.next(TokenType.STRING);
+ var stringContentsStart = token.sourceRange().characterPosition(1);
+ var stringContentsEnd = token.sourceRange()
+ .characterPosition(token.sourceRange().characterLength() - 1);
+ var stringContents = stringContentsStart.to(stringContentsEnd);
+ var unescapedValue = unescape(stringContents);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedStringLiteralNode(unescapedValue, source);
}
private static final Pattern STRING_ESCAPE_PATTERN = Pattern.compile("\\\\(.)");
- private static String unescape(String value, Source source) {
- var matcher = STRING_ESCAPE_PATTERN.matcher(value);
+ private static String unescape(SourceRange sourceRange) {
+ var stringContents = sourceRange.charSequence();
+ var matcher = STRING_ESCAPE_PATTERN.matcher(stringContents);
var result = new StringBuilder();
var lastIndex = 0;
while (matcher.find()) {
- result.append(value.subSequence(lastIndex, matcher.start()));
+ result.append(stringContents.subSequence(lastIndex, matcher.start()));
var code = matcher.group(1);
- result.append(unescapeCharacter(code, source.at(matcher.start(), matcher.end())));
+ var escapeSequenceSourceRange = sourceRange.characterPosition(matcher.start())
+ .to(sourceRange.characterPosition(matcher.end()));
+ result.append(unescapeCharacter(code, new FileFragmentSource(escapeSequenceSourceRange)));
lastIndex = matcher.end();
}
- result.append(value.subSequence(lastIndex, value.length()));
+ result.append(stringContents.subSequence(lastIndex, stringContents.length()));
return result.toString();
}
@@ -979,7 +1000,7 @@ public class Parser {
}
private static UntypedNamespaceStatementNode parseStructDefinition(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var visibility = parseVisibility(tokens);
@@ -1008,8 +1029,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedStructDefinitionNode(
name,
@@ -1026,7 +1047,7 @@ public class Parser {
TokenIterator<TokenType> tokens,
boolean structHasPositionalFields
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var fieldIsPositional = !tokens.trySkip(TokenType.SYMBOL_DOT);
var name = tokens.nextValue(TokenType.IDENTIFIER);
@@ -1035,8 +1056,8 @@ public class Parser {
var type = parseTopLevelTypeLevelExpression(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
if (structHasPositionalFields ^ fieldIsPositional) {
throw new InconsistentStructFieldsError(source);
@@ -1050,7 +1071,7 @@ public class Parser {
}
private static UntypedNamespaceStatementNode parseSumTypeDefinition(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var visibility = parseVisibility(tokens);
@@ -1069,8 +1090,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_SEMICOLON);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedSumTypeDefinitionNode(
name,
@@ -1093,7 +1114,7 @@ public class Parser {
TokenIterator<TokenType> tokens,
NamespaceName namespaceName
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var imports = parseMany(
() -> !tokens.isNext(TokenType.KEYWORD_IMPORT),
@@ -1107,25 +1128,25 @@ public class Parser {
() -> true
);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedNamespaceNode(namespaceName, imports, body, source);
}
private static UntypedExpressionNode parseReference(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var name = tokens.nextValue(TokenType.IDENTIFIER);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedReferenceNode(name, source);
}
private static UntypedTargetNode parseTarget(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
return switch (tokens.peek().tokenType()) {
case KEYWORD_ASSIGN -> {
@@ -1133,8 +1154,8 @@ public class Parser {
var name = tokens.nextValue(TokenType.IDENTIFIER);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
yield new UntypedTargetNode.Reassign(name, source);
}
@@ -1146,8 +1167,8 @@ public class Parser {
var name = tokens.nextValue(TokenType.IDENTIFIER);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
yield new UntypedTargetNode.Val(name, visibility, source);
}
@@ -1157,8 +1178,8 @@ public class Parser {
var name = tokens.nextValue(TokenType.IDENTIFIER);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
yield new UntypedTargetNode.Var(name, source);
}
@@ -1174,8 +1195,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_PAREN_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
yield new UntypedTargetNode.Tuple(elements, source);
}
@@ -1183,8 +1204,8 @@ public class Parser {
case SYMBOL_UNDERSCORE -> {
tokens.skip(TokenType.SYMBOL_UNDERSCORE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
yield new UntypedTargetNode.Ignore(source);
}
@@ -1197,7 +1218,7 @@ public class Parser {
private static UntypedExpressionNode parseTry(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_TRY);
@@ -1217,14 +1238,14 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedTryNode(body, handledEffect, handlerMethods, source);
}
private static UntypedTryHandlerMethodNode parseTryHandlerMethod(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_FUN);
var name = tokens.nextValue(TokenType.IDENTIFIER);
@@ -1235,8 +1256,8 @@ public class Parser {
var body = parseBlock(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedTryHandlerMethodNode(
name,
@@ -1251,7 +1272,7 @@ public class Parser {
private static UntypedExpressionNode parseTuple(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.SYMBOL_HASH_PAREN_OPEN);
@@ -1263,8 +1284,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_PAREN_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedTupleNode(elements, source);
}
@@ -1272,7 +1293,7 @@ public class Parser {
private static UntypedTypeLevelExpressionNode parseTupleType(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.SYMBOL_HASH_PAREN_OPEN);
@@ -1284,8 +1305,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_PAREN_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedTupleTypeNode(elements, source);
}
@@ -1293,7 +1314,7 @@ public class Parser {
private static Optional<UntypedTypeLevelArgsNode> parseTypeLevelArgsOptional(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
if (tokens.trySkip(TokenType.SYMBOL_SQUARE_OPEN)) {
var params = parseMany(
@@ -1304,8 +1325,8 @@ public class Parser {
tokens.skip(TokenType.SYMBOL_SQUARE_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return Optional.of(new UntypedTypeLevelArgsNode(params, source));
} else {
@@ -1328,6 +1349,7 @@ public class Parser {
TokenIterator<TokenType> tokens,
Optional<OperatorPrecedence> parentPrecedence
) {
+ var start = tokens.startPosition();
var left = parsePrimaryTypeLevelExpression(tokens);
while (true) {
@@ -1340,7 +1362,7 @@ public class Parser {
) {
return left;
}
- left = operationParser.parse(left, tokens);
+ left = operationParser.parse(start, left, tokens);
}
}
@@ -1363,14 +1385,14 @@ public class Parser {
}
static UntypedTypeLevelParamNode parseTypeLevelParam(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var isEffectParam = tokens.trySkip(TokenType.SYMBOL_BANG);
var name = tokens.nextValue(TokenType.IDENTIFIER);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return isEffectParam
? new UntypedEffectParamNode(name, source)
@@ -1378,23 +1400,23 @@ public class Parser {
}
private static UntypedTypeLevelReferenceNode parseTypeLevelReference(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
var name = tokens.nextValue(TokenType.IDENTIFIER);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedTypeLevelReferenceNode(name, source);
}
private static UntypedExpressionNode parseUnitLiteral(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_UNIT);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedUnitLiteralNode(source);
}
@@ -1405,7 +1427,7 @@ public class Parser {
}
private static UntypedExpressionNode parseWhen(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_WHEN);
@@ -1421,14 +1443,14 @@ public class Parser {
);
tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedWhenNode(expression, cases, source);
}
private static UntypedWhenCaseNode parseWhenCase(TokenIterator<TokenType> tokens) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_IS);
@@ -1436,8 +1458,8 @@ public class Parser {
var body = parseBlock(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedWhenCaseNode(caseType, body, source);
}
@@ -1445,7 +1467,7 @@ public class Parser {
private static UntypedFunctionStatementNode parseWhile(
TokenIterator<TokenType> tokens
) {
- var start = tokens.position();
+ var start = tokens.startPosition();
tokens.skip(TokenType.KEYWORD_WHILE);
tokens.skip(TokenType.SYMBOL_PAREN_OPEN);
@@ -1454,8 +1476,8 @@ public class Parser {
var body = parseBlock(tokens);
- var end = tokens.position();
- var source = start.to(end);
+ var end = tokens.endPosition();
+ var source = new FileFragmentSource(start.to(end));
return new UntypedWhileNode(condition, body, source);
}
diff --git a/src/main/java/org/shedlang/compiler/parser/SourceParser.java b/src/main/java/org/shedlang/compiler/parser/SourceParser.java
index 19be58d4..8144f11a 100644
--- a/src/main/java/org/shedlang/compiler/parser/SourceParser.java
+++ b/src/main/java/org/shedlang/compiler/parser/SourceParser.java
@@ -1,8 +1,8 @@
package org.shedlang.compiler.parser;
-import org.shedlang.compiler.sources.Source;
import org.shedlang.compiler.tokeniser.TokenIterator;
import org.shedlang.compiler.types.NamespaceName;
+import org.zwobble.sourcetext.SourceText;
import java.util.function.Function;
@@ -12,15 +12,15 @@ public class SourceParser {
private SourceParser() {
}
- public static NamespaceName parseNamespaceName(Source source) {
- return parseSource(source, tokens -> Parser.parseNamespaceName(tokens));
+ public static NamespaceName parseNamespaceName(SourceText sourceText) {
+ return parseSource(sourceText, tokens -> Parser.parseNamespaceName(tokens));
}
private static <T> T parseSource(
- Source source,
+ SourceText sourceText,
Function<TokenIterator<TokenType>, T> parseTokens
) {
- var tokens = tokenise(source);
+ var tokens = tokenise(sourceText);
var result = parseTokens.apply(tokens);
tokens.skip(TokenType.END);
return result;
diff --git a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java
index 1fdd584b..85172578 100644
--- a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java
+++ b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java
@@ -1,9 +1,9 @@
package org.shedlang.compiler.parser;
-import org.shedlang.compiler.sources.Source;
import org.shedlang.compiler.tokeniser.RegexTokeniser;
import org.shedlang.compiler.tokeniser.Token;
import org.shedlang.compiler.tokeniser.TokenIterator;
+import org.zwobble.sourcetext.SourceText;
import java.util.List;
import java.util.Map;
@@ -74,19 +74,23 @@ public class Tokeniser {
)
);
- public static TokenIterator<TokenType> tokenise(Source source) {
- var tokens = tokeniser.tokenise(source).stream()
+ public static TokenIterator<TokenType> tokenise(SourceText sourceText) {
+ var tokens = tokeniser.tokenise(sourceText).stream()
.filter(token ->
token.tokenType() != TokenType.WHITESPACE &&
token.tokenType() != TokenType.COMMENT_SINGLE_LINE
)
.map(token ->
token.tokenType() == TokenType.IDENTIFIER
- ? new Token<>(token.source(), KEYWORDS.getOrDefault(token.value(), token.tokenType()), token.value())
+ ? new Token<>(token.sourceRange(), KEYWORDS.getOrDefault(token.value(), token.tokenType()), token.value())
: token
)
.collect(Collectors.toList());
- return new TokenIterator<>(tokens, token(source.end(), TokenType.END, ""));
+ var endPosition = sourceText.characterPosition(sourceText.characterLength());
+ var endSourceRange = endPosition.to(endPosition);
+ var endToken = token(endSourceRange, TokenType.END, "");
+
+ return new TokenIterator<>(tokens, endToken);
}
}