mirror of
https://github.com/apple/pkl.git
synced 2026-04-25 01:38:34 +02:00
move parser out of pkl-core (#1024)
This commit is contained in:
@@ -3,13 +3,7 @@
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2=compileClasspath,compileOnlyDependenciesMetadata
|
||||
com.palantir.javapoet:javapoet:0.6.0=generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath
|
||||
com.tunnelvisionlabs:antlr4-annotations:4.9.0=antlr
|
||||
com.tunnelvisionlabs:antlr4-runtime:4.9.0=antlr,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
com.tunnelvisionlabs:antlr4:4.9.0=antlr
|
||||
net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.abego.treelayout:org.abego.treelayout.core:1.0.1=antlr
|
||||
org.antlr:ST4:4.3=antlr
|
||||
org.antlr:antlr-runtime:3.5.2=antlr
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
|
||||
org.assertj:assertj-core:3.27.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.graalvm.polyglot:polyglot:24.1.2=compileClasspath,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
|
||||
@@ -21,42 +21,30 @@ plugins {
|
||||
pklJavaLibrary
|
||||
pklPublishLibrary
|
||||
pklNativeBuild
|
||||
antlr
|
||||
idea
|
||||
}
|
||||
|
||||
val generatorSourceSet = sourceSets.register("generator")
|
||||
|
||||
sourceSets { test { java { srcDir(file("testgenerated/antlr")) } } }
|
||||
|
||||
idea {
|
||||
module {
|
||||
// mark src/test/antlr as source dir
|
||||
// mark generated/antlr as generated source dir
|
||||
// mark generated/truffle as generated source dir
|
||||
sourceDirs = sourceDirs + files("generated/truffle")
|
||||
generatedSourceDirs = generatedSourceDirs + files("testgenerated/antlr", "generated/truffle")
|
||||
testSources.from(files("src/test/antlr", "testgenerated/antlr"))
|
||||
generatedSourceDirs = generatedSourceDirs + files("generated/truffle")
|
||||
}
|
||||
}
|
||||
|
||||
val javaExecutableConfiguration: Configuration = configurations.create("javaExecutable")
|
||||
|
||||
// workaround for https://github.com/gradle/gradle/issues/820
|
||||
configurations.api.get().let { apiConfig ->
|
||||
apiConfig.setExtendsFrom(apiConfig.extendsFrom.filter { it.name != "antlr" })
|
||||
}
|
||||
|
||||
dependencies {
|
||||
annotationProcessor(libs.truffleDslProcessor)
|
||||
annotationProcessor(generatorSourceSet.get().runtimeClasspath)
|
||||
|
||||
antlr(libs.antlr)
|
||||
|
||||
compileOnly(libs.jsr305)
|
||||
// pkl-core implements pkl-executor's ExecutorSpi, but the SPI doesn't ship with pkl-core
|
||||
compileOnly(projects.pklExecutor)
|
||||
|
||||
implementation(projects.pklParser)
|
||||
implementation(libs.msgpack)
|
||||
implementation(libs.truffleApi)
|
||||
implementation(libs.graalSdk)
|
||||
@@ -65,7 +53,6 @@ dependencies {
|
||||
|
||||
implementation(libs.snakeYaml)
|
||||
|
||||
testImplementation(libs.antlrRuntime)
|
||||
testImplementation(projects.pklCommonsTest)
|
||||
|
||||
add("generatorImplementation", libs.javaPoet)
|
||||
@@ -93,35 +80,6 @@ publishing {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.generateTestGrammarSource {
|
||||
maxHeapSize = "64m"
|
||||
|
||||
// generate only visitor
|
||||
arguments = arguments + listOf("-visitor", "-no-listener")
|
||||
|
||||
// Due to https://github.com/antlr/antlr4/issues/2260,
|
||||
// we can't put .g4 files into src/test/antlr/org/pkl/core/parser/antlr.
|
||||
// Instead, we put .g4 files into src/test/antlr, adapt output dir below,
|
||||
// and use @header directives in .g4 files (instead of setting `-package` argument here)
|
||||
// and task makeIntelliJAntlrPluginHappy to fix up the IDE story.
|
||||
outputDirectory = file("testgenerated/antlr/org/pkl/core/parser/antlr")
|
||||
}
|
||||
|
||||
tasks.generateGrammarSource { enabled = false }
|
||||
|
||||
tasks.named("generateGeneratorGrammarSource") { enabled = false }
|
||||
|
||||
tasks.compileTestKotlin { dependsOn(tasks.generateTestGrammarSource) }
|
||||
|
||||
// Satisfy expectations of IntelliJ ANTLR plugin,
|
||||
// which can't otherwise cope with our ANTLR setup.
|
||||
val makeIntelliJAntlrPluginHappy by
|
||||
tasks.registering(Copy::class) {
|
||||
dependsOn(tasks.generateGrammarSource)
|
||||
into("test/antlr")
|
||||
from("testgenerated/antlr/org/pkl/core/parser/antlr") { include("PklLexer.tokens") }
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
inputs.property("version", buildInfo.pklVersion)
|
||||
inputs.property("commitId", buildInfo.commitId)
|
||||
@@ -245,13 +203,6 @@ tasks.clean {
|
||||
delete(layout.buildDirectory.dir("test-packages"))
|
||||
}
|
||||
|
||||
spotless {
|
||||
antlr4 {
|
||||
licenseHeaderFile(rootProject.file("buildSrc/src/main/resources/license-header.star-block.txt"))
|
||||
target(files("src/test/antlr/PklParser.g4", "src/test/antlr/PklLexer.g4"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun Test.configureTest() {
|
||||
inputs
|
||||
.dir("src/test/files/LanguageSnippetTests/input")
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import org.pkl.core.parser.Lexer;
|
||||
import org.pkl.parser.Lexer;
|
||||
|
||||
// To instantiate this class, use ValueRenderers.pcf().
|
||||
final class PcfRenderer implements ValueRenderer {
|
||||
|
||||
@@ -18,14 +18,14 @@ package org.pkl.core.ast.builder;
|
||||
import com.oracle.truffle.api.source.Source;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.BaseParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.parser.syntax.DocComment;
|
||||
import org.pkl.core.parser.syntax.Modifier;
|
||||
import org.pkl.core.parser.syntax.Modifier.ModifierValue;
|
||||
import org.pkl.core.parser.syntax.Node;
|
||||
import org.pkl.core.runtime.VmExceptionBuilder;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.parser.BaseParserVisitor;
|
||||
import org.pkl.parser.Span;
|
||||
import org.pkl.parser.syntax.DocComment;
|
||||
import org.pkl.parser.syntax.Modifier;
|
||||
import org.pkl.parser.syntax.Modifier.ModifierValue;
|
||||
import org.pkl.parser.syntax.Node;
|
||||
|
||||
public abstract class AbstractAstBuilder<T> extends BaseParserVisitor<T> {
|
||||
|
||||
|
||||
@@ -157,81 +157,6 @@ import org.pkl.core.module.ModuleKey;
|
||||
import org.pkl.core.module.ModuleKeys;
|
||||
import org.pkl.core.module.ResolvedModuleKey;
|
||||
import org.pkl.core.packages.PackageLoadError;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.parser.syntax.Annotation;
|
||||
import org.pkl.core.parser.syntax.ArgumentList;
|
||||
import org.pkl.core.parser.syntax.Class;
|
||||
import org.pkl.core.parser.syntax.ClassMethod;
|
||||
import org.pkl.core.parser.syntax.ClassProperty;
|
||||
import org.pkl.core.parser.syntax.Expr;
|
||||
import org.pkl.core.parser.syntax.Expr.AmendsExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.BinaryOperatorExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.BoolLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.FloatLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.FunctionLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.IfExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ImportExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.IntLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.LetExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.LogicalNotExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ModuleExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.MultiLineStringLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NewExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NonNullExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NullLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.OuterExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ParenthesizedExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.QualifiedAccessExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ReadExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SingleLineStringLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SubscriptExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SuperAccessExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SuperSubscriptExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ThisExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ThrowExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TraceExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCastExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCheckExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.UnaryMinusExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.UnqualifiedAccessExpr;
|
||||
import org.pkl.core.parser.syntax.ExtendsOrAmendsClause;
|
||||
import org.pkl.core.parser.syntax.Identifier;
|
||||
import org.pkl.core.parser.syntax.ImportClause;
|
||||
import org.pkl.core.parser.syntax.Modifier;
|
||||
import org.pkl.core.parser.syntax.Modifier.ModifierValue;
|
||||
import org.pkl.core.parser.syntax.Module;
|
||||
import org.pkl.core.parser.syntax.Node;
|
||||
import org.pkl.core.parser.syntax.ObjectBody;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ForGenerator;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.MemberPredicate;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectElement;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectEntry;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectMethod;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectProperty;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectSpread;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.WhenGenerator;
|
||||
import org.pkl.core.parser.syntax.Parameter;
|
||||
import org.pkl.core.parser.syntax.Parameter.TypedIdentifier;
|
||||
import org.pkl.core.parser.syntax.ParameterList;
|
||||
import org.pkl.core.parser.syntax.QualifiedIdentifier;
|
||||
import org.pkl.core.parser.syntax.StringConstant;
|
||||
import org.pkl.core.parser.syntax.StringPart;
|
||||
import org.pkl.core.parser.syntax.StringPart.StringChars;
|
||||
import org.pkl.core.parser.syntax.StringPart.StringInterpolation;
|
||||
import org.pkl.core.parser.syntax.Type;
|
||||
import org.pkl.core.parser.syntax.Type.ConstrainedType;
|
||||
import org.pkl.core.parser.syntax.Type.DeclaredType;
|
||||
import org.pkl.core.parser.syntax.Type.FunctionType;
|
||||
import org.pkl.core.parser.syntax.Type.ModuleType;
|
||||
import org.pkl.core.parser.syntax.Type.NothingType;
|
||||
import org.pkl.core.parser.syntax.Type.NullableType;
|
||||
import org.pkl.core.parser.syntax.Type.ParenthesizedType;
|
||||
import org.pkl.core.parser.syntax.Type.StringConstantType;
|
||||
import org.pkl.core.parser.syntax.Type.UnionType;
|
||||
import org.pkl.core.parser.syntax.Type.UnknownType;
|
||||
import org.pkl.core.parser.syntax.TypeAlias;
|
||||
import org.pkl.core.parser.syntax.TypeAnnotation;
|
||||
import org.pkl.core.parser.syntax.TypeParameterList;
|
||||
import org.pkl.core.runtime.BaseModule;
|
||||
import org.pkl.core.runtime.ModuleInfo;
|
||||
import org.pkl.core.runtime.ModuleResolver;
|
||||
@@ -256,6 +181,81 @@ import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.core.util.Pair;
|
||||
import org.pkl.parser.Span;
|
||||
import org.pkl.parser.syntax.Annotation;
|
||||
import org.pkl.parser.syntax.ArgumentList;
|
||||
import org.pkl.parser.syntax.Class;
|
||||
import org.pkl.parser.syntax.ClassMethod;
|
||||
import org.pkl.parser.syntax.ClassProperty;
|
||||
import org.pkl.parser.syntax.Expr;
|
||||
import org.pkl.parser.syntax.Expr.AmendsExpr;
|
||||
import org.pkl.parser.syntax.Expr.BinaryOperatorExpr;
|
||||
import org.pkl.parser.syntax.Expr.BoolLiteralExpr;
|
||||
import org.pkl.parser.syntax.Expr.FloatLiteralExpr;
|
||||
import org.pkl.parser.syntax.Expr.FunctionLiteralExpr;
|
||||
import org.pkl.parser.syntax.Expr.IfExpr;
|
||||
import org.pkl.parser.syntax.Expr.ImportExpr;
|
||||
import org.pkl.parser.syntax.Expr.IntLiteralExpr;
|
||||
import org.pkl.parser.syntax.Expr.LetExpr;
|
||||
import org.pkl.parser.syntax.Expr.LogicalNotExpr;
|
||||
import org.pkl.parser.syntax.Expr.ModuleExpr;
|
||||
import org.pkl.parser.syntax.Expr.MultiLineStringLiteralExpr;
|
||||
import org.pkl.parser.syntax.Expr.NewExpr;
|
||||
import org.pkl.parser.syntax.Expr.NonNullExpr;
|
||||
import org.pkl.parser.syntax.Expr.NullLiteralExpr;
|
||||
import org.pkl.parser.syntax.Expr.OuterExpr;
|
||||
import org.pkl.parser.syntax.Expr.ParenthesizedExpr;
|
||||
import org.pkl.parser.syntax.Expr.QualifiedAccessExpr;
|
||||
import org.pkl.parser.syntax.Expr.ReadExpr;
|
||||
import org.pkl.parser.syntax.Expr.SingleLineStringLiteralExpr;
|
||||
import org.pkl.parser.syntax.Expr.SubscriptExpr;
|
||||
import org.pkl.parser.syntax.Expr.SuperAccessExpr;
|
||||
import org.pkl.parser.syntax.Expr.SuperSubscriptExpr;
|
||||
import org.pkl.parser.syntax.Expr.ThisExpr;
|
||||
import org.pkl.parser.syntax.Expr.ThrowExpr;
|
||||
import org.pkl.parser.syntax.Expr.TraceExpr;
|
||||
import org.pkl.parser.syntax.Expr.TypeCastExpr;
|
||||
import org.pkl.parser.syntax.Expr.TypeCheckExpr;
|
||||
import org.pkl.parser.syntax.Expr.UnaryMinusExpr;
|
||||
import org.pkl.parser.syntax.Expr.UnqualifiedAccessExpr;
|
||||
import org.pkl.parser.syntax.ExtendsOrAmendsClause;
|
||||
import org.pkl.parser.syntax.Identifier;
|
||||
import org.pkl.parser.syntax.ImportClause;
|
||||
import org.pkl.parser.syntax.Modifier;
|
||||
import org.pkl.parser.syntax.Modifier.ModifierValue;
|
||||
import org.pkl.parser.syntax.Module;
|
||||
import org.pkl.parser.syntax.Node;
|
||||
import org.pkl.parser.syntax.ObjectBody;
|
||||
import org.pkl.parser.syntax.ObjectMember.ForGenerator;
|
||||
import org.pkl.parser.syntax.ObjectMember.MemberPredicate;
|
||||
import org.pkl.parser.syntax.ObjectMember.ObjectElement;
|
||||
import org.pkl.parser.syntax.ObjectMember.ObjectEntry;
|
||||
import org.pkl.parser.syntax.ObjectMember.ObjectMethod;
|
||||
import org.pkl.parser.syntax.ObjectMember.ObjectProperty;
|
||||
import org.pkl.parser.syntax.ObjectMember.ObjectSpread;
|
||||
import org.pkl.parser.syntax.ObjectMember.WhenGenerator;
|
||||
import org.pkl.parser.syntax.Parameter;
|
||||
import org.pkl.parser.syntax.Parameter.TypedIdentifier;
|
||||
import org.pkl.parser.syntax.ParameterList;
|
||||
import org.pkl.parser.syntax.QualifiedIdentifier;
|
||||
import org.pkl.parser.syntax.StringConstant;
|
||||
import org.pkl.parser.syntax.StringPart;
|
||||
import org.pkl.parser.syntax.StringPart.StringChars;
|
||||
import org.pkl.parser.syntax.StringPart.StringInterpolation;
|
||||
import org.pkl.parser.syntax.Type;
|
||||
import org.pkl.parser.syntax.Type.ConstrainedType;
|
||||
import org.pkl.parser.syntax.Type.DeclaredType;
|
||||
import org.pkl.parser.syntax.Type.FunctionType;
|
||||
import org.pkl.parser.syntax.Type.ModuleType;
|
||||
import org.pkl.parser.syntax.Type.NothingType;
|
||||
import org.pkl.parser.syntax.Type.NullableType;
|
||||
import org.pkl.parser.syntax.Type.ParenthesizedType;
|
||||
import org.pkl.parser.syntax.Type.StringConstantType;
|
||||
import org.pkl.parser.syntax.Type.UnionType;
|
||||
import org.pkl.parser.syntax.Type.UnknownType;
|
||||
import org.pkl.parser.syntax.TypeAlias;
|
||||
import org.pkl.parser.syntax.TypeAnnotation;
|
||||
import org.pkl.parser.syntax.TypeParameterList;
|
||||
|
||||
public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
private final VmLanguage language;
|
||||
@@ -1097,7 +1097,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
return Pair.of(elementNodes, isConstantNodes);
|
||||
}
|
||||
|
||||
public GeneratorMemberNode visitObjectMember(org.pkl.core.parser.syntax.ObjectMember member) {
|
||||
public GeneratorMemberNode visitObjectMember(org.pkl.parser.syntax.ObjectMember member) {
|
||||
return (GeneratorMemberNode) member.accept(this);
|
||||
}
|
||||
|
||||
@@ -2375,7 +2375,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
}
|
||||
|
||||
private GeneratorMemberNode[] doVisitGeneratorMemberNodes(
|
||||
List<? extends org.pkl.core.parser.syntax.ObjectMember> members) {
|
||||
List<? extends org.pkl.parser.syntax.ObjectMember> members) {
|
||||
var result = new GeneratorMemberNode[members.size()];
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
result[i] = visitObjectMember(members.get(i));
|
||||
@@ -2666,7 +2666,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
}
|
||||
var forExprCtx = ctx.parent();
|
||||
while (forExprCtx != null
|
||||
&& forExprCtx.getClass() != org.pkl.core.parser.syntax.ObjectMember.ForGenerator.class) {
|
||||
&& forExprCtx.getClass() != org.pkl.parser.syntax.ObjectMember.ForGenerator.class) {
|
||||
forExprCtx = forExprCtx.parent();
|
||||
}
|
||||
assert forExprCtx != null;
|
||||
@@ -2674,7 +2674,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
.evalError(errorMessageKey)
|
||||
.withSourceSection(
|
||||
createSourceSection(
|
||||
((org.pkl.core.parser.syntax.ObjectMember.ForGenerator) forExprCtx).forSpan()))
|
||||
((org.pkl.parser.syntax.ObjectMember.ForGenerator) forExprCtx).forSpan()))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,21 +24,21 @@ import java.util.List;
|
||||
import org.pkl.core.ast.builder.ImportsAndReadsParser.Entry;
|
||||
import org.pkl.core.module.ModuleKey;
|
||||
import org.pkl.core.module.ResolvedModuleKey;
|
||||
import org.pkl.core.parser.Parser;
|
||||
import org.pkl.core.parser.ParserError;
|
||||
import org.pkl.core.parser.syntax.Expr;
|
||||
import org.pkl.core.parser.syntax.Expr.ImportExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ReadExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ReadType;
|
||||
import org.pkl.core.parser.syntax.Expr.SingleLineStringLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.ExtendsOrAmendsClause;
|
||||
import org.pkl.core.parser.syntax.ExtendsOrAmendsClause.Type;
|
||||
import org.pkl.core.parser.syntax.ImportClause;
|
||||
import org.pkl.core.parser.syntax.StringPart.StringChars;
|
||||
import org.pkl.core.runtime.VmExceptionBuilder;
|
||||
import org.pkl.core.runtime.VmUtils;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.parser.Parser;
|
||||
import org.pkl.parser.ParserError;
|
||||
import org.pkl.parser.syntax.Expr;
|
||||
import org.pkl.parser.syntax.Expr.ImportExpr;
|
||||
import org.pkl.parser.syntax.Expr.ReadExpr;
|
||||
import org.pkl.parser.syntax.Expr.ReadType;
|
||||
import org.pkl.parser.syntax.Expr.SingleLineStringLiteralExpr;
|
||||
import org.pkl.parser.syntax.ExtendsOrAmendsClause;
|
||||
import org.pkl.parser.syntax.ExtendsOrAmendsClause.Type;
|
||||
import org.pkl.parser.syntax.ImportClause;
|
||||
import org.pkl.parser.syntax.StringPart.StringChars;
|
||||
|
||||
/**
|
||||
* Collects module uris and resource uris imported within a module.
|
||||
|
||||
@@ -24,12 +24,12 @@ import org.pkl.core.ast.ConstantNode;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.expression.generator.GeneratorMemberNode;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
import org.pkl.core.parser.Lexer;
|
||||
import org.pkl.core.runtime.Identifier;
|
||||
import org.pkl.core.runtime.ModuleInfo;
|
||||
import org.pkl.core.runtime.VmDataSize;
|
||||
import org.pkl.core.runtime.VmDuration;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.parser.Lexer;
|
||||
|
||||
public final class SymbolTable {
|
||||
private Scope currentScope;
|
||||
|
||||
@@ -1,482 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser;
|
||||
|
||||
import org.pkl.core.parser.syntax.Annotation;
|
||||
import org.pkl.core.parser.syntax.ArgumentList;
|
||||
import org.pkl.core.parser.syntax.Class;
|
||||
import org.pkl.core.parser.syntax.ClassBody;
|
||||
import org.pkl.core.parser.syntax.ClassMethod;
|
||||
import org.pkl.core.parser.syntax.ClassProperty;
|
||||
import org.pkl.core.parser.syntax.DocComment;
|
||||
import org.pkl.core.parser.syntax.Expr.AmendsExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.BinaryOperatorExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.BoolLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.FloatLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.FunctionLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.IfExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ImportExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.IntLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.LetExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.LogicalNotExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ModuleExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.MultiLineStringLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NewExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NonNullExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NullLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.OuterExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ParenthesizedExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.QualifiedAccessExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ReadExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SingleLineStringLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SubscriptExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SuperAccessExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SuperSubscriptExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ThisExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ThrowExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TraceExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCastExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCheckExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.UnaryMinusExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.UnqualifiedAccessExpr;
|
||||
import org.pkl.core.parser.syntax.ExtendsOrAmendsClause;
|
||||
import org.pkl.core.parser.syntax.Identifier;
|
||||
import org.pkl.core.parser.syntax.ImportClause;
|
||||
import org.pkl.core.parser.syntax.Keyword;
|
||||
import org.pkl.core.parser.syntax.Modifier;
|
||||
import org.pkl.core.parser.syntax.ModuleDecl;
|
||||
import org.pkl.core.parser.syntax.Node;
|
||||
import org.pkl.core.parser.syntax.ObjectBody;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ForGenerator;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.MemberPredicate;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectElement;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectEntry;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectMethod;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectProperty;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectSpread;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.WhenGenerator;
|
||||
import org.pkl.core.parser.syntax.Parameter;
|
||||
import org.pkl.core.parser.syntax.ParameterList;
|
||||
import org.pkl.core.parser.syntax.QualifiedIdentifier;
|
||||
import org.pkl.core.parser.syntax.ReplInput;
|
||||
import org.pkl.core.parser.syntax.StringConstant;
|
||||
import org.pkl.core.parser.syntax.StringPart;
|
||||
import org.pkl.core.parser.syntax.Type.ConstrainedType;
|
||||
import org.pkl.core.parser.syntax.Type.DeclaredType;
|
||||
import org.pkl.core.parser.syntax.Type.FunctionType;
|
||||
import org.pkl.core.parser.syntax.Type.ModuleType;
|
||||
import org.pkl.core.parser.syntax.Type.NothingType;
|
||||
import org.pkl.core.parser.syntax.Type.NullableType;
|
||||
import org.pkl.core.parser.syntax.Type.ParenthesizedType;
|
||||
import org.pkl.core.parser.syntax.Type.StringConstantType;
|
||||
import org.pkl.core.parser.syntax.Type.UnionType;
|
||||
import org.pkl.core.parser.syntax.Type.UnknownType;
|
||||
import org.pkl.core.parser.syntax.TypeAlias;
|
||||
import org.pkl.core.parser.syntax.TypeAnnotation;
|
||||
import org.pkl.core.parser.syntax.TypeArgumentList;
|
||||
import org.pkl.core.parser.syntax.TypeParameter;
|
||||
import org.pkl.core.parser.syntax.TypeParameterList;
|
||||
|
||||
public abstract class BaseParserVisitor<T> implements ParserVisitor<T> {
|
||||
|
||||
@Override
|
||||
public T visitUnknownType(UnknownType type) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitNothingType(NothingType type) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitModuleType(ModuleType type) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitStringConstantType(StringConstantType type) {
|
||||
return visitChildren(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitDeclaredType(DeclaredType type) {
|
||||
return visitChildren(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitParenthesizedType(ParenthesizedType type) {
|
||||
return visitChildren(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitNullableType(NullableType type) {
|
||||
return visitChildren(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitConstrainedType(ConstrainedType type) {
|
||||
return visitChildren(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitUnionType(UnionType type) {
|
||||
return visitChildren(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitFunctionType(FunctionType type) {
|
||||
return visitChildren(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitThisExpr(ThisExpr expr) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitOuterExpr(OuterExpr expr) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitModuleExpr(ModuleExpr expr) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitNullLiteralExpr(NullLiteralExpr expr) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitBoolLiteralExpr(BoolLiteralExpr expr) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitIntLiteralExpr(IntLiteralExpr expr) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitFloatLiteralExpr(FloatLiteralExpr expr) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitThrowExpr(ThrowExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitTraceExpr(TraceExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitImportExpr(ImportExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitReadExpr(ReadExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitUnqualifiedAccessExpr(UnqualifiedAccessExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitStringConstant(StringConstant expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitSingleLineStringLiteralExpr(SingleLineStringLiteralExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitMultiLineStringLiteralExpr(MultiLineStringLiteralExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitNewExpr(NewExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitAmendsExpr(AmendsExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitSuperAccessExpr(SuperAccessExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitSuperSubscriptExpr(SuperSubscriptExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitQualifiedAccessExpr(QualifiedAccessExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitSubscriptExpr(SubscriptExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitNonNullExpr(NonNullExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitUnaryMinusExpr(UnaryMinusExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitLogicalNotExpr(LogicalNotExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitBinaryOperatorExpr(BinaryOperatorExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitTypeCheckExpr(TypeCheckExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitTypeCastExpr(TypeCastExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitIfExpr(IfExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitLetExpr(LetExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitFunctionLiteralExpr(FunctionLiteralExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitParenthesizedExpr(ParenthesizedExpr expr) {
|
||||
return visitChildren(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitObjectProperty(ObjectProperty member) {
|
||||
return visitChildren(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitObjectMethod(ObjectMethod member) {
|
||||
return visitChildren(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitMemberPredicate(MemberPredicate member) {
|
||||
return visitChildren(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitObjectElement(ObjectElement member) {
|
||||
return visitChildren(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitObjectEntry(ObjectEntry member) {
|
||||
return visitChildren(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitObjectSpread(ObjectSpread member) {
|
||||
return visitChildren(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitWhenGenerator(WhenGenerator member) {
|
||||
return visitChildren(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitForGenerator(ForGenerator member) {
|
||||
return visitChildren(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitModule(org.pkl.core.parser.syntax.Module module) {
|
||||
return visitChildren(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitModuleDecl(ModuleDecl decl) {
|
||||
return visitChildren(decl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitExtendsOrAmendsClause(ExtendsOrAmendsClause decl) {
|
||||
return visitChildren(decl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitImportClause(ImportClause imp) {
|
||||
return visitChildren(imp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitClass(Class clazz) {
|
||||
return visitChildren(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitModifier(Modifier modifier) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitClassProperty(ClassProperty prop) {
|
||||
return visitChildren(prop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitClassMethod(ClassMethod method) {
|
||||
return visitChildren(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitTypeAlias(TypeAlias typeAlias) {
|
||||
return visitChildren(typeAlias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitAnnotation(Annotation annotation) {
|
||||
return visitChildren(annotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitParameter(Parameter param) {
|
||||
return visitChildren(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitParameterList(ParameterList paramList) {
|
||||
return visitChildren(paramList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitTypeParameterList(TypeParameterList typeParameterList) {
|
||||
return visitChildren(typeParameterList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitTypeAnnotation(TypeAnnotation typeAnnotation) {
|
||||
return visitChildren(typeAnnotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitArgumentList(ArgumentList argumentList) {
|
||||
return visitChildren(argumentList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitStringPart(StringPart part) {
|
||||
return visitChildren(part);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitClassBody(ClassBody classBody) {
|
||||
return visitChildren(classBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitDocComment(DocComment docComment) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitIdentifier(Identifier identifier) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitQualifiedIdentifier(QualifiedIdentifier qualifiedIdentifier) {
|
||||
return visitChildren(qualifiedIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitObjectBody(ObjectBody objectBody) {
|
||||
return visitChildren(objectBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitTypeParameter(TypeParameter typeParameter) {
|
||||
return visitChildren(typeParameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitReplInput(ReplInput replInput) {
|
||||
return visitChildren(replInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitKeyword(Keyword keyword) {
|
||||
return defaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visitTypeArgumentList(TypeArgumentList typeArgumentList) {
|
||||
return visitChildren(typeArgumentList);
|
||||
}
|
||||
|
||||
private T visitChildren(Node node) {
|
||||
T result = defaultValue();
|
||||
var children = node.children();
|
||||
if (children == null) return result;
|
||||
for (var child : children) {
|
||||
if (child != null) {
|
||||
result = aggregateResult(result, child.accept(this));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract T defaultValue();
|
||||
|
||||
protected T aggregateResult(T result, T nextResult) {
|
||||
return nextResult;
|
||||
}
|
||||
}
|
||||
@@ -1,818 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Deque;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
|
||||
public class Lexer {
|
||||
|
||||
private final char[] source;
|
||||
private final int size;
|
||||
protected int cursor = 0;
|
||||
protected int sCursor = 0;
|
||||
private char lookahead;
|
||||
private State state = State.DEFAULT;
|
||||
private final Deque<InterpolationScope> interpolationStack = new ArrayDeque<>();
|
||||
private boolean stringEnded = false;
|
||||
private boolean isEscape = false;
|
||||
// how many newlines exist between two subsequent tokens
|
||||
protected int newLinesBetween = 0;
|
||||
|
||||
private static final char EOF = Short.MAX_VALUE;
|
||||
|
||||
public Lexer(String input) {
|
||||
source = input.toCharArray();
|
||||
size = source.length;
|
||||
if (size > 0) {
|
||||
lookahead = source[cursor];
|
||||
} else {
|
||||
lookahead = EOF;
|
||||
}
|
||||
}
|
||||
|
||||
// The span of the last lexed token
|
||||
public Span span() {
|
||||
return new Span(sCursor, cursor - sCursor);
|
||||
}
|
||||
|
||||
// The text of the last lexed token
|
||||
public String text() {
|
||||
return new String(source, sCursor, cursor - sCursor);
|
||||
}
|
||||
|
||||
public char[] getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public String textFor(int offset, int size) {
|
||||
return new String(source, offset, size);
|
||||
}
|
||||
|
||||
public Token next() {
|
||||
sCursor = cursor;
|
||||
newLinesBetween = 0;
|
||||
return switch (state) {
|
||||
case DEFAULT -> nextDefault();
|
||||
case STRING -> nextString();
|
||||
};
|
||||
}
|
||||
|
||||
private Token nextDefault() {
|
||||
var ch = nextChar();
|
||||
// ignore spaces
|
||||
while (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\f' || ch == '\r') {
|
||||
sCursor = cursor;
|
||||
if (ch == '\n') {
|
||||
newLinesBetween++;
|
||||
}
|
||||
ch = nextChar();
|
||||
}
|
||||
return switch (ch) {
|
||||
case EOF -> {
|
||||
// when EOF is reached we overshot the span
|
||||
cursor--;
|
||||
yield Token.EOF;
|
||||
}
|
||||
case ';' -> Token.SEMICOLON;
|
||||
case '(' -> {
|
||||
var scope = interpolationStack.peek();
|
||||
if (scope != null) {
|
||||
scope.parens++;
|
||||
}
|
||||
yield Token.LPAREN;
|
||||
}
|
||||
case ')' -> {
|
||||
var scope = interpolationStack.peek();
|
||||
if (scope != null) {
|
||||
scope.parens--;
|
||||
if (scope.parens <= 0) {
|
||||
// interpolation is over. Back to string
|
||||
state = State.STRING;
|
||||
}
|
||||
}
|
||||
yield Token.RPAREN;
|
||||
}
|
||||
case '{' -> Token.LBRACE;
|
||||
case '}' -> Token.RBRACE;
|
||||
case ',' -> Token.COMMA;
|
||||
case '@' -> Token.AT;
|
||||
case ':' -> Token.COLON;
|
||||
case '+' -> Token.PLUS;
|
||||
case '%' -> Token.MOD;
|
||||
case '[' -> {
|
||||
if (lookahead == '[') {
|
||||
nextChar();
|
||||
yield Token.LPRED;
|
||||
} else yield Token.LBRACK;
|
||||
}
|
||||
case ']' -> Token.RBRACK;
|
||||
case '=' -> {
|
||||
if (lookahead == '=') {
|
||||
nextChar();
|
||||
yield Token.EQUAL;
|
||||
} else yield Token.ASSIGN;
|
||||
}
|
||||
case '>' -> {
|
||||
if (lookahead == '=') {
|
||||
nextChar();
|
||||
yield Token.GTE;
|
||||
} else yield Token.GT;
|
||||
}
|
||||
case '<' -> {
|
||||
if (lookahead == '=') {
|
||||
nextChar();
|
||||
yield Token.LTE;
|
||||
} else yield Token.LT;
|
||||
}
|
||||
case '-' -> {
|
||||
if (lookahead == '>') {
|
||||
nextChar();
|
||||
yield Token.ARROW;
|
||||
} else yield Token.MINUS;
|
||||
}
|
||||
case '!' -> {
|
||||
if (lookahead == '!') {
|
||||
nextChar();
|
||||
yield Token.NON_NULL;
|
||||
} else if (lookahead == '=') {
|
||||
nextChar();
|
||||
yield Token.NOT_EQUAL;
|
||||
} else yield Token.NOT;
|
||||
}
|
||||
case '?' -> {
|
||||
if (lookahead == '.') {
|
||||
nextChar();
|
||||
yield Token.QDOT;
|
||||
} else if (lookahead == '?') {
|
||||
nextChar();
|
||||
yield Token.COALESCE;
|
||||
} else yield Token.QUESTION;
|
||||
}
|
||||
case '&' -> {
|
||||
if (lookahead == '&') {
|
||||
nextChar();
|
||||
yield Token.AND;
|
||||
} else {
|
||||
throw unexpectedChar(ch, "&&");
|
||||
}
|
||||
}
|
||||
case '|' -> {
|
||||
if (lookahead == '>') {
|
||||
nextChar();
|
||||
yield Token.PIPE;
|
||||
} else if (lookahead == '|') {
|
||||
nextChar();
|
||||
yield Token.OR;
|
||||
} else {
|
||||
yield Token.UNION;
|
||||
}
|
||||
}
|
||||
case '*' -> {
|
||||
if (lookahead == '*') {
|
||||
nextChar();
|
||||
yield Token.POW;
|
||||
} else yield Token.STAR;
|
||||
}
|
||||
case '~' -> {
|
||||
if (lookahead == '/') {
|
||||
nextChar();
|
||||
yield Token.INT_DIV;
|
||||
} else {
|
||||
throw unexpectedChar(ch, "~/");
|
||||
}
|
||||
}
|
||||
case '.' -> {
|
||||
if (lookahead == '.') {
|
||||
nextChar();
|
||||
if (lookahead == '.') {
|
||||
nextChar();
|
||||
if (lookahead == '?') {
|
||||
nextChar();
|
||||
yield Token.QSPREAD;
|
||||
} else {
|
||||
yield Token.SPREAD;
|
||||
}
|
||||
} else {
|
||||
throw unexpectedChar("..", ".", "...", "...?");
|
||||
}
|
||||
} else if (lookahead >= 48 && lookahead <= 57) {
|
||||
yield lexNumber(ch);
|
||||
} else {
|
||||
yield Token.DOT;
|
||||
}
|
||||
}
|
||||
case '`' -> {
|
||||
lexQuotedIdentifier();
|
||||
yield Token.IDENTIFIER;
|
||||
}
|
||||
case '/' -> lexSlash();
|
||||
case '"' -> lexStringStart(0);
|
||||
case '#' -> {
|
||||
if (lookahead == '!') {
|
||||
yield lexShebang();
|
||||
} else {
|
||||
yield lexStringStartPounds();
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
if (Character.isDigit(ch)) {
|
||||
yield lexNumber(ch);
|
||||
} else if (isIdentifierStart(ch)) {
|
||||
yield lexIdentifier();
|
||||
} else throw lexError(ErrorMessages.create("invalidCharacter", ch), cursor - 1, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Token nextString() {
|
||||
var scope = interpolationStack.getFirst();
|
||||
if (stringEnded) {
|
||||
lexStringEnd(scope);
|
||||
stringEnded = false;
|
||||
interpolationStack.pop();
|
||||
state = State.DEFAULT;
|
||||
return Token.STRING_END;
|
||||
}
|
||||
if (lookahead == EOF) return Token.EOF;
|
||||
if (isEscape) {
|
||||
isEscape = false;
|
||||
// consume the `\#*`
|
||||
for (var i = 0; i < scope.pounds + 1; i++) {
|
||||
nextChar();
|
||||
}
|
||||
return lexEscape();
|
||||
}
|
||||
if (scope.quotes == 1) {
|
||||
lexString(scope.pounds);
|
||||
} else {
|
||||
if (lookahead == '\r') {
|
||||
nextChar();
|
||||
if (lookahead == '\n') {
|
||||
nextChar();
|
||||
}
|
||||
return Token.STRING_NEWLINE;
|
||||
}
|
||||
if (lookahead == '\n') {
|
||||
nextChar();
|
||||
return Token.STRING_NEWLINE;
|
||||
}
|
||||
lexMultiString(scope.pounds);
|
||||
}
|
||||
return Token.STRING_PART;
|
||||
}
|
||||
|
||||
private Token lexStringStartPounds() {
|
||||
int pounds = 1;
|
||||
while (lookahead == '#') {
|
||||
nextChar();
|
||||
pounds++;
|
||||
}
|
||||
if (lookahead == EOF) {
|
||||
throw lexError(ErrorMessages.create("unexpectedEndOfFile"), span());
|
||||
}
|
||||
if (lookahead != '"') {
|
||||
throw unexpectedChar(lookahead, "\"");
|
||||
}
|
||||
nextChar();
|
||||
return lexStringStart(pounds);
|
||||
}
|
||||
|
||||
private Token lexStringStart(int pounds) {
|
||||
var quotes = 1;
|
||||
if (lookahead == '"') {
|
||||
nextChar();
|
||||
if (lookahead == '"') {
|
||||
nextChar();
|
||||
quotes = 3;
|
||||
} else {
|
||||
backup();
|
||||
}
|
||||
}
|
||||
state = State.STRING;
|
||||
interpolationStack.push(new InterpolationScope(quotes, pounds));
|
||||
stringEnded = false;
|
||||
if (quotes == 1) return Token.STRING_START;
|
||||
return Token.STRING_MULTI_START;
|
||||
}
|
||||
|
||||
private void lexStringEnd(InterpolationScope scope) {
|
||||
// don't actually need to check it here
|
||||
for (var i = 0; i < scope.quotes + scope.pounds; i++) {
|
||||
nextChar();
|
||||
}
|
||||
}
|
||||
|
||||
private void lexString(int pounds) {
|
||||
var poundsInARow = 0;
|
||||
var foundQuote = false;
|
||||
var foundBackslash = false;
|
||||
while (lookahead != EOF) {
|
||||
var ch = nextChar();
|
||||
switch (ch) {
|
||||
case '\n', '\r' ->
|
||||
throw lexError(
|
||||
ErrorMessages.create("missingDelimiter", "\"" + "#".repeat(pounds)), cursor - 1, 1);
|
||||
case '"' -> {
|
||||
if (pounds == 0) {
|
||||
backup();
|
||||
stringEnded = true;
|
||||
return;
|
||||
}
|
||||
foundQuote = true;
|
||||
foundBackslash = false;
|
||||
poundsInARow = 0;
|
||||
}
|
||||
case '\\' -> {
|
||||
foundQuote = false;
|
||||
foundBackslash = true;
|
||||
poundsInARow = 0;
|
||||
if (pounds == poundsInARow) {
|
||||
backup(pounds + 1);
|
||||
isEscape = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case '#' -> {
|
||||
poundsInARow++;
|
||||
if (foundQuote && (pounds == poundsInARow)) {
|
||||
backup(pounds + 1);
|
||||
stringEnded = true;
|
||||
return;
|
||||
}
|
||||
if (foundBackslash && pounds == poundsInARow) {
|
||||
backup(pounds + 1);
|
||||
isEscape = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
foundQuote = false;
|
||||
foundBackslash = false;
|
||||
poundsInARow = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void lexMultiString(int pounds) {
|
||||
var poundsInARow = 0;
|
||||
var quotesInARow = 0;
|
||||
var foundBackslash = false;
|
||||
while (lookahead != EOF && lookahead != '\n' && lookahead != '\r') {
|
||||
var ch = nextChar();
|
||||
switch (ch) {
|
||||
case '"' -> {
|
||||
quotesInARow++;
|
||||
if (quotesInARow == 3 && pounds == 0) {
|
||||
backup(3);
|
||||
stringEnded = true;
|
||||
return;
|
||||
}
|
||||
poundsInARow = 0;
|
||||
foundBackslash = false;
|
||||
}
|
||||
case '\\' -> {
|
||||
quotesInARow = 0;
|
||||
poundsInARow = 0;
|
||||
foundBackslash = true;
|
||||
if (pounds == poundsInARow) {
|
||||
backup(pounds + 1);
|
||||
isEscape = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case '#' -> {
|
||||
poundsInARow++;
|
||||
if (quotesInARow == 3 && pounds == poundsInARow) {
|
||||
backup(pounds + 3);
|
||||
stringEnded = true;
|
||||
return;
|
||||
}
|
||||
if (foundBackslash && pounds == poundsInARow) {
|
||||
backup(pounds + 1);
|
||||
isEscape = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
quotesInARow = 0;
|
||||
poundsInARow = 0;
|
||||
foundBackslash = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Token lexEscape() {
|
||||
if (lookahead == EOF) throw unexpectedEndOfFile();
|
||||
var ch = nextChar();
|
||||
return switch (ch) {
|
||||
case 'n' -> Token.STRING_ESCAPE_NEWLINE;
|
||||
case '"' -> Token.STRING_ESCAPE_QUOTE;
|
||||
case '\\' -> Token.STRING_ESCAPE_BACKSLASH;
|
||||
case 't' -> Token.STRING_ESCAPE_TAB;
|
||||
case 'r' -> Token.STRING_ESCAPE_RETURN;
|
||||
case '(' -> {
|
||||
var scope = interpolationStack.getFirst();
|
||||
scope.parens++;
|
||||
state = State.DEFAULT;
|
||||
yield Token.INTERPOLATION_START;
|
||||
}
|
||||
case 'u' -> lexUnicodeEscape();
|
||||
default ->
|
||||
throw lexError(
|
||||
ErrorMessages.create("invalidCharacterEscapeSequence", "\\" + ch, "\\"),
|
||||
cursor - 2,
|
||||
2);
|
||||
};
|
||||
}
|
||||
|
||||
private Token lexUnicodeEscape() {
|
||||
if (lookahead != '{') {
|
||||
throw unexpectedChar(lookahead, "{");
|
||||
}
|
||||
do {
|
||||
nextChar();
|
||||
} while (lookahead != '}' && lookahead != EOF && Character.isLetterOrDigit(lookahead));
|
||||
if (lookahead == '}') {
|
||||
// consume the close bracket
|
||||
nextChar();
|
||||
} else {
|
||||
throw lexError(ErrorMessages.create("unterminatedUnicodeEscapeSequence", text()), span());
|
||||
}
|
||||
return Token.STRING_ESCAPE_UNICODE;
|
||||
}
|
||||
|
||||
private Token lexIdentifier() {
|
||||
while (isIdentifierPart(lookahead)) {
|
||||
nextChar();
|
||||
}
|
||||
|
||||
var identifierStr = text();
|
||||
var identifier = getKeywordOrIdentifier(identifierStr);
|
||||
return switch (identifier) {
|
||||
case IMPORT -> {
|
||||
if (lookahead == '*') {
|
||||
nextChar();
|
||||
yield Token.IMPORT_STAR;
|
||||
} else yield Token.IMPORT;
|
||||
}
|
||||
case READ ->
|
||||
switch (lookahead) {
|
||||
case '*' -> {
|
||||
nextChar();
|
||||
yield Token.READ_STAR;
|
||||
}
|
||||
case '?' -> {
|
||||
nextChar();
|
||||
yield Token.READ_QUESTION;
|
||||
}
|
||||
default -> Token.READ;
|
||||
};
|
||||
default -> identifier;
|
||||
};
|
||||
}
|
||||
|
||||
private void lexQuotedIdentifier() {
|
||||
while (lookahead != '`' && lookahead != '\n' && lookahead != '\r') {
|
||||
nextChar();
|
||||
}
|
||||
if (lookahead == '`') {
|
||||
nextChar();
|
||||
} else {
|
||||
throw unexpectedChar(lookahead, "backquote");
|
||||
}
|
||||
}
|
||||
|
||||
private Token lexNumber(char start) {
|
||||
if (start == '0') {
|
||||
if (lookahead == 'x' || lookahead == 'X') {
|
||||
nextChar();
|
||||
lexHexNumber();
|
||||
return Token.HEX;
|
||||
}
|
||||
if (lookahead == 'b' || lookahead == 'B') {
|
||||
nextChar();
|
||||
lexBinNumber();
|
||||
return Token.BIN;
|
||||
}
|
||||
if (lookahead == 'o' || lookahead == 'O') {
|
||||
nextChar();
|
||||
lexOctNumber();
|
||||
return Token.OCT;
|
||||
}
|
||||
if (lookahead == 'e' || lookahead == 'E') {
|
||||
nextChar();
|
||||
lexExponent();
|
||||
return Token.FLOAT;
|
||||
}
|
||||
} else if (start == '.') {
|
||||
lexDotNumber();
|
||||
return Token.FLOAT;
|
||||
}
|
||||
|
||||
while ((lookahead >= 48 && lookahead <= 57) || lookahead == '_') {
|
||||
nextChar();
|
||||
}
|
||||
|
||||
if (lookahead == 'e' || lookahead == 'E') {
|
||||
nextChar();
|
||||
lexExponent();
|
||||
return Token.FLOAT;
|
||||
} else if (lookahead == '.') {
|
||||
nextChar();
|
||||
if (lookahead == '_') {
|
||||
throw lexError("invalidSeparatorPosition");
|
||||
}
|
||||
if (lookahead < 48 || lookahead > 57) {
|
||||
backup();
|
||||
return Token.INT;
|
||||
}
|
||||
lexDotNumber();
|
||||
return Token.FLOAT;
|
||||
}
|
||||
return Token.INT;
|
||||
}
|
||||
|
||||
private Token lexSlash() {
|
||||
switch (lookahead) {
|
||||
case '/':
|
||||
{
|
||||
nextChar();
|
||||
var token = lookahead == '/' ? Token.DOC_COMMENT : Token.LINE_COMMENT;
|
||||
while (lookahead != '\n' && lookahead != '\r' && lookahead != EOF) {
|
||||
nextChar();
|
||||
}
|
||||
return token;
|
||||
}
|
||||
case '*':
|
||||
{
|
||||
nextChar();
|
||||
lexBlockComment();
|
||||
return Token.BLOCK_COMMENT;
|
||||
}
|
||||
default:
|
||||
return Token.DIV;
|
||||
}
|
||||
}
|
||||
|
||||
private void lexBlockComment() {
|
||||
if (lookahead == EOF) throw unexpectedEndOfFile();
|
||||
var prev = nextChar();
|
||||
while (lookahead != EOF) {
|
||||
if (prev == '*' && lookahead == '/') {
|
||||
nextChar();
|
||||
break;
|
||||
}
|
||||
prev = nextChar();
|
||||
}
|
||||
if (lookahead == EOF) throw unexpectedEndOfFile();
|
||||
}
|
||||
|
||||
private void lexHexNumber() {
|
||||
if (lookahead == '_') {
|
||||
throw lexError("invalidSeparatorPosition");
|
||||
}
|
||||
if (!isHex(lookahead)) {
|
||||
throw unexpectedChar(lookahead, "hexadecimal number");
|
||||
}
|
||||
while (isHex(lookahead) || lookahead == '_') {
|
||||
nextChar();
|
||||
}
|
||||
}
|
||||
|
||||
private void lexBinNumber() {
|
||||
if (lookahead == '_') {
|
||||
throw lexError("invalidSeparatorPosition");
|
||||
}
|
||||
if (!(lookahead == '0' || lookahead == '1')) {
|
||||
throw unexpectedChar(lookahead, "binary number");
|
||||
}
|
||||
while (lookahead == '0' || lookahead == '1' || lookahead == '_') {
|
||||
nextChar();
|
||||
}
|
||||
}
|
||||
|
||||
private void lexOctNumber() {
|
||||
if (lookahead == '_') {
|
||||
throw lexError("invalidSeparatorPosition");
|
||||
}
|
||||
var ch = (int) lookahead;
|
||||
if (!(ch >= 48 && ch <= 55)) {
|
||||
throw unexpectedChar((char) ch, "octal number");
|
||||
}
|
||||
while ((ch >= 48 && ch <= 55) || ch == '_') {
|
||||
nextChar();
|
||||
ch = lookahead;
|
||||
}
|
||||
}
|
||||
|
||||
private void lexExponent() {
|
||||
if (lookahead == '+' || lookahead == '-') {
|
||||
nextChar();
|
||||
}
|
||||
if (lookahead == '_') {
|
||||
throw lexError("invalidSeparatorPosition");
|
||||
}
|
||||
if (lookahead < 48 || lookahead > 57) {
|
||||
throw unexpectedChar(lookahead, "number");
|
||||
}
|
||||
while ((lookahead >= 48 && lookahead <= 57) || lookahead == '_') {
|
||||
nextChar();
|
||||
}
|
||||
}
|
||||
|
||||
private void lexDotNumber() {
|
||||
if (lookahead == '_') {
|
||||
throw lexError("invalidSeparatorPosition");
|
||||
}
|
||||
while ((lookahead >= 48 && lookahead <= 57) || lookahead == '_') {
|
||||
nextChar();
|
||||
}
|
||||
if (lookahead == 'e' || lookahead == 'E') {
|
||||
nextChar();
|
||||
lexExponent();
|
||||
}
|
||||
}
|
||||
|
||||
private Token lexShebang() {
|
||||
do {
|
||||
nextChar();
|
||||
} while (lookahead != '\n' && lookahead != '\r' && lookahead != EOF);
|
||||
return Token.SHEBANG;
|
||||
}
|
||||
|
||||
private boolean isHex(char ch) {
|
||||
var code = (int) ch;
|
||||
return (code >= 48 && code <= 57) || (code >= 97 && code <= 102) || (code >= 65 && code <= 70);
|
||||
}
|
||||
|
||||
private static boolean isIdentifierStart(char c) {
|
||||
return c == '_' || c == '$' || Character.isUnicodeIdentifierStart(c);
|
||||
}
|
||||
|
||||
private static boolean isIdentifierPart(char c) {
|
||||
return c != EOF && (c == '$' || Character.isUnicodeIdentifierPart(c));
|
||||
}
|
||||
|
||||
private char nextChar() {
|
||||
var tmp = lookahead;
|
||||
cursor++;
|
||||
if (cursor >= size) {
|
||||
lookahead = EOF;
|
||||
} else {
|
||||
lookahead = source[cursor];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private void backup() {
|
||||
lookahead = source[--cursor];
|
||||
}
|
||||
|
||||
private void backup(int amount) {
|
||||
cursor -= amount;
|
||||
lookahead = source[cursor];
|
||||
}
|
||||
|
||||
private ParserError lexError(String msg, Object... args) {
|
||||
var length = lookahead == EOF ? 0 : 1;
|
||||
var index = lookahead == EOF ? cursor - 1 : cursor;
|
||||
return new ParserError(ErrorMessages.create(msg, args), new Span(index, length));
|
||||
}
|
||||
|
||||
private ParserError lexError(String msg, int charIndex, int length) {
|
||||
return new ParserError(msg, new Span(charIndex, length));
|
||||
}
|
||||
|
||||
private ParserError lexError(String msg, Span span) {
|
||||
return new ParserError(msg, span);
|
||||
}
|
||||
|
||||
private ParserError unexpectedChar(char got, String didYouMean) {
|
||||
return lexError("unexpectedCharacter", got, didYouMean);
|
||||
}
|
||||
|
||||
private ParserError unexpectedChar(String got, String option1, String option2, String option3) {
|
||||
return lexError("unexpectedCharacter3", got, option1, option2, option3);
|
||||
}
|
||||
|
||||
private ParserError unexpectedEndOfFile() {
|
||||
return lexError(ErrorMessages.create("unexpectedEndOfFile"), cursor, 0);
|
||||
}
|
||||
|
||||
public static boolean isRegularIdentifier(String identifier) {
|
||||
if (identifier.isEmpty()) return false;
|
||||
|
||||
if (isKeyword(identifier)) return false;
|
||||
|
||||
var firstCp = identifier.codePointAt(0);
|
||||
return (firstCp == '$' || firstCp == '_' || Character.isUnicodeIdentifierStart(firstCp))
|
||||
&& identifier
|
||||
.codePoints()
|
||||
.skip(1)
|
||||
.allMatch(cp -> cp == '$' || Character.isUnicodeIdentifierPart(cp));
|
||||
}
|
||||
|
||||
public static String maybeQuoteIdentifier(String identifier) {
|
||||
return isRegularIdentifier(identifier) ? identifier : "`" + identifier + "`";
|
||||
}
|
||||
|
||||
@SuppressWarnings("SuspiciousArrayMethodCall")
|
||||
private static boolean isKeyword(String text) {
|
||||
var index = Arrays.binarySearch(KEYWORDS, text);
|
||||
return index >= 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SuspiciousArrayMethodCall")
|
||||
private static Token getKeywordOrIdentifier(String text) {
|
||||
var index = Arrays.binarySearch(KEYWORDS, text);
|
||||
if (index < 0) return Token.IDENTIFIER;
|
||||
return KEYWORDS[index].token;
|
||||
}
|
||||
|
||||
protected static final KeywordEntry[] KEYWORDS = {
|
||||
new KeywordEntry("_", Token.UNDERSCORE),
|
||||
new KeywordEntry("abstract", Token.ABSTRACT),
|
||||
new KeywordEntry("amends", Token.AMENDS),
|
||||
new KeywordEntry("as", Token.AS),
|
||||
new KeywordEntry("case", Token.CASE),
|
||||
new KeywordEntry("class", Token.CLASS),
|
||||
new KeywordEntry("const", Token.CONST),
|
||||
new KeywordEntry("delete", Token.DELETE),
|
||||
new KeywordEntry("else", Token.ELSE),
|
||||
new KeywordEntry("extends", Token.EXTENDS),
|
||||
new KeywordEntry("external", Token.EXTERNAL),
|
||||
new KeywordEntry("false", Token.FALSE),
|
||||
new KeywordEntry("fixed", Token.FIXED),
|
||||
new KeywordEntry("for", Token.FOR),
|
||||
new KeywordEntry("function", Token.FUNCTION),
|
||||
new KeywordEntry("hidden", Token.HIDDEN),
|
||||
new KeywordEntry("if", Token.IF),
|
||||
new KeywordEntry("import", Token.IMPORT),
|
||||
new KeywordEntry("in", Token.IN),
|
||||
new KeywordEntry("is", Token.IS),
|
||||
new KeywordEntry("let", Token.LET),
|
||||
new KeywordEntry("local", Token.LOCAL),
|
||||
new KeywordEntry("module", Token.MODULE),
|
||||
new KeywordEntry("new", Token.NEW),
|
||||
new KeywordEntry("nothing", Token.NOTHING),
|
||||
new KeywordEntry("null", Token.NULL),
|
||||
new KeywordEntry("open", Token.OPEN),
|
||||
new KeywordEntry("out", Token.OUT),
|
||||
new KeywordEntry("outer", Token.OUTER),
|
||||
new KeywordEntry("override", Token.OVERRIDE),
|
||||
new KeywordEntry("protected", Token.PROTECTED),
|
||||
new KeywordEntry("read", Token.READ),
|
||||
new KeywordEntry("record", Token.RECORD),
|
||||
new KeywordEntry("super", Token.SUPER),
|
||||
new KeywordEntry("switch", Token.SWITCH),
|
||||
new KeywordEntry("this", Token.THIS),
|
||||
new KeywordEntry("throw", Token.THROW),
|
||||
new KeywordEntry("trace", Token.TRACE),
|
||||
new KeywordEntry("true", Token.TRUE),
|
||||
new KeywordEntry("typealias", Token.TYPE_ALIAS),
|
||||
new KeywordEntry("unknown", Token.UNKNOWN),
|
||||
new KeywordEntry("vararg", Token.VARARG),
|
||||
new KeywordEntry("when", Token.WHEN)
|
||||
};
|
||||
|
||||
protected record KeywordEntry(String name, Token token) implements Comparable<String> {
|
||||
@Override
|
||||
public int compareTo(String o) {
|
||||
return name.compareTo(o);
|
||||
}
|
||||
}
|
||||
|
||||
private static class InterpolationScope {
|
||||
final int quotes;
|
||||
final int pounds;
|
||||
int parens = 0;
|
||||
|
||||
protected InterpolationScope(int quotes, int pounds) {
|
||||
this.quotes = quotes;
|
||||
this.pounds = pounds;
|
||||
}
|
||||
}
|
||||
|
||||
private enum State {
|
||||
DEFAULT,
|
||||
STRING
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.syntax.Expr;
|
||||
import org.pkl.core.parser.syntax.Expr.BinaryOperatorExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.OperatorExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCastExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCheckExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeExpr;
|
||||
import org.pkl.core.parser.syntax.Operator;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
class OperatorResolver {
|
||||
private OperatorResolver() {}
|
||||
|
||||
private enum Associativity {
|
||||
LEFT,
|
||||
RIGHT
|
||||
}
|
||||
|
||||
public static int getPrecedence(Operator op) {
|
||||
return switch (op) {
|
||||
case NULL_COALESCE -> 0;
|
||||
case PIPE -> 1;
|
||||
case OR -> 2;
|
||||
case AND -> 3;
|
||||
case EQ_EQ, NOT_EQ -> 4;
|
||||
case IS, AS -> 5;
|
||||
case LT, LTE, GT, GTE -> 6;
|
||||
case PLUS, MINUS -> 7;
|
||||
case MULT, DIV, INT_DIV, MOD -> 8;
|
||||
case POW -> 9;
|
||||
case DOT, QDOT -> 10;
|
||||
};
|
||||
}
|
||||
|
||||
private static Associativity getAssociativity(Operator op) {
|
||||
return switch (op) {
|
||||
case POW, NULL_COALESCE -> Associativity.RIGHT;
|
||||
default -> Associativity.LEFT;
|
||||
};
|
||||
}
|
||||
|
||||
private static @Nullable Operator getHighestPrecedence(List<Expr> exprs, int min) {
|
||||
var highest = -1;
|
||||
Operator op = null;
|
||||
for (var expr : exprs) {
|
||||
if (expr instanceof OperatorExpr o) {
|
||||
var precedence = getPrecedence(o.getOp());
|
||||
if (precedence > highest && precedence >= min) {
|
||||
highest = precedence;
|
||||
op = o.getOp();
|
||||
}
|
||||
}
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
private static int index(List<Expr> exprs, Associativity associativity, Operator op) {
|
||||
if (associativity == Associativity.LEFT) {
|
||||
for (var i = 0; i < exprs.size(); i++) {
|
||||
if (exprs.get(i) instanceof OperatorExpr operator && operator.getOp() == op) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = exprs.size() - 1; i >= 0; i--) {
|
||||
if (exprs.get(i) instanceof OperatorExpr operator && operator.getOp() == op) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static List<Expr> resolveOperator(
|
||||
List<Expr> exprs, Associativity associativity, Operator op) {
|
||||
var res = new ArrayList<>(exprs);
|
||||
|
||||
var i = index(res, associativity, op);
|
||||
var left = res.get(i - 1);
|
||||
var right = res.get(i + 1);
|
||||
var span = left.span().endWith(right.span());
|
||||
var binOp =
|
||||
switch (op) {
|
||||
case IS -> new TypeCheckExpr(left, ((TypeExpr) right).getType(), span);
|
||||
case AS -> new TypeCastExpr(left, ((TypeExpr) right).getType(), span);
|
||||
default -> new BinaryOperatorExpr(left, right, op, span);
|
||||
};
|
||||
res.remove(i - 1);
|
||||
res.remove(i - 1);
|
||||
res.remove(i - 1);
|
||||
res.add(i - 1, binOp);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve all operators based on their precedence and associativity. This requires that the list
|
||||
* has a valid form: `expr` `op` `expr` ...
|
||||
*/
|
||||
public static Expr resolveOperators(List<Expr> exprs) {
|
||||
if (exprs.size() == 1) return exprs.get(0);
|
||||
|
||||
var res = resolveOperatorsHigherThan(exprs, 0);
|
||||
if (res.size() > 1) {
|
||||
throw new ParserError(
|
||||
"Malformed expression", exprs.get(0).span().endWith(exprs.get(exprs.size() - 1).span()));
|
||||
}
|
||||
|
||||
return res.get(0);
|
||||
}
|
||||
|
||||
public static List<Expr> resolveOperatorsHigherThan(List<Expr> exprs, int minPrecedence) {
|
||||
var res = exprs;
|
||||
var highest = getHighestPrecedence(res, minPrecedence);
|
||||
while (highest != null) {
|
||||
var associativity = getAssociativity(highest);
|
||||
res = resolveOperator(res, associativity, highest);
|
||||
highest = getHighestPrecedence(res, minPrecedence);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser;
|
||||
|
||||
import org.pkl.core.parser.syntax.Module;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class ParserError extends RuntimeException {
|
||||
private final Span span;
|
||||
private @Nullable Module partialParseResult;
|
||||
|
||||
public ParserError(String msg, Span span) {
|
||||
super(msg);
|
||||
this.span = span;
|
||||
}
|
||||
|
||||
public Span span() {
|
||||
return span;
|
||||
}
|
||||
|
||||
public void setPartialParseResult(@Nullable Module partialParseResult) {
|
||||
this.partialParseResult = partialParseResult;
|
||||
}
|
||||
|
||||
public @Nullable Module getPartialParseResult() {
|
||||
return partialParseResult;
|
||||
}
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser;
|
||||
|
||||
import org.pkl.core.parser.syntax.Annotation;
|
||||
import org.pkl.core.parser.syntax.ArgumentList;
|
||||
import org.pkl.core.parser.syntax.Class;
|
||||
import org.pkl.core.parser.syntax.ClassBody;
|
||||
import org.pkl.core.parser.syntax.ClassMethod;
|
||||
import org.pkl.core.parser.syntax.ClassProperty;
|
||||
import org.pkl.core.parser.syntax.DocComment;
|
||||
import org.pkl.core.parser.syntax.Expr;
|
||||
import org.pkl.core.parser.syntax.Expr.AmendsExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.BinaryOperatorExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.BoolLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.FloatLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.FunctionLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.IfExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.IntLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.LetExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.LogicalNotExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ModuleExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.MultiLineStringLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NewExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NonNullExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.NullLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.OuterExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ParenthesizedExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.QualifiedAccessExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ReadExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SingleLineStringLiteralExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SubscriptExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SuperAccessExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.SuperSubscriptExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ThisExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.ThrowExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TraceExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCastExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCheckExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.UnaryMinusExpr;
|
||||
import org.pkl.core.parser.syntax.Expr.UnqualifiedAccessExpr;
|
||||
import org.pkl.core.parser.syntax.ExtendsOrAmendsClause;
|
||||
import org.pkl.core.parser.syntax.Identifier;
|
||||
import org.pkl.core.parser.syntax.ImportClause;
|
||||
import org.pkl.core.parser.syntax.Keyword;
|
||||
import org.pkl.core.parser.syntax.Modifier;
|
||||
import org.pkl.core.parser.syntax.Module;
|
||||
import org.pkl.core.parser.syntax.ModuleDecl;
|
||||
import org.pkl.core.parser.syntax.ObjectBody;
|
||||
import org.pkl.core.parser.syntax.ObjectMember;
|
||||
import org.pkl.core.parser.syntax.Parameter;
|
||||
import org.pkl.core.parser.syntax.ParameterList;
|
||||
import org.pkl.core.parser.syntax.QualifiedIdentifier;
|
||||
import org.pkl.core.parser.syntax.ReplInput;
|
||||
import org.pkl.core.parser.syntax.StringConstant;
|
||||
import org.pkl.core.parser.syntax.StringPart;
|
||||
import org.pkl.core.parser.syntax.Type;
|
||||
import org.pkl.core.parser.syntax.TypeAlias;
|
||||
import org.pkl.core.parser.syntax.TypeAnnotation;
|
||||
import org.pkl.core.parser.syntax.TypeArgumentList;
|
||||
import org.pkl.core.parser.syntax.TypeParameter;
|
||||
import org.pkl.core.parser.syntax.TypeParameterList;
|
||||
|
||||
public interface ParserVisitor<Result> {
|
||||
|
||||
Result visitUnknownType(Type.UnknownType type);
|
||||
|
||||
Result visitNothingType(Type.NothingType type);
|
||||
|
||||
Result visitModuleType(Type.ModuleType type);
|
||||
|
||||
Result visitStringConstantType(Type.StringConstantType type);
|
||||
|
||||
Result visitDeclaredType(Type.DeclaredType type);
|
||||
|
||||
Result visitParenthesizedType(Type.ParenthesizedType type);
|
||||
|
||||
Result visitNullableType(Type.NullableType type);
|
||||
|
||||
Result visitConstrainedType(Type.ConstrainedType type);
|
||||
|
||||
Result visitUnionType(Type.UnionType type);
|
||||
|
||||
Result visitFunctionType(Type.FunctionType type);
|
||||
|
||||
Result visitThisExpr(ThisExpr expr);
|
||||
|
||||
Result visitOuterExpr(OuterExpr expr);
|
||||
|
||||
Result visitModuleExpr(ModuleExpr expr);
|
||||
|
||||
Result visitNullLiteralExpr(NullLiteralExpr expr);
|
||||
|
||||
Result visitBoolLiteralExpr(BoolLiteralExpr expr);
|
||||
|
||||
Result visitIntLiteralExpr(IntLiteralExpr expr);
|
||||
|
||||
Result visitFloatLiteralExpr(FloatLiteralExpr expr);
|
||||
|
||||
Result visitThrowExpr(ThrowExpr expr);
|
||||
|
||||
Result visitTraceExpr(TraceExpr expr);
|
||||
|
||||
Result visitImportExpr(Expr.ImportExpr expr);
|
||||
|
||||
Result visitReadExpr(ReadExpr expr);
|
||||
|
||||
Result visitUnqualifiedAccessExpr(UnqualifiedAccessExpr expr);
|
||||
|
||||
Result visitStringConstant(StringConstant expr);
|
||||
|
||||
Result visitSingleLineStringLiteralExpr(SingleLineStringLiteralExpr expr);
|
||||
|
||||
Result visitMultiLineStringLiteralExpr(MultiLineStringLiteralExpr expr);
|
||||
|
||||
Result visitNewExpr(NewExpr expr);
|
||||
|
||||
Result visitAmendsExpr(AmendsExpr expr);
|
||||
|
||||
Result visitSuperAccessExpr(SuperAccessExpr expr);
|
||||
|
||||
Result visitSuperSubscriptExpr(SuperSubscriptExpr expr);
|
||||
|
||||
Result visitQualifiedAccessExpr(QualifiedAccessExpr expr);
|
||||
|
||||
Result visitSubscriptExpr(SubscriptExpr expr);
|
||||
|
||||
Result visitNonNullExpr(NonNullExpr expr);
|
||||
|
||||
Result visitUnaryMinusExpr(UnaryMinusExpr expr);
|
||||
|
||||
Result visitLogicalNotExpr(LogicalNotExpr expr);
|
||||
|
||||
Result visitBinaryOperatorExpr(BinaryOperatorExpr expr);
|
||||
|
||||
Result visitTypeCheckExpr(TypeCheckExpr expr);
|
||||
|
||||
Result visitTypeCastExpr(TypeCastExpr expr);
|
||||
|
||||
Result visitIfExpr(IfExpr expr);
|
||||
|
||||
Result visitLetExpr(LetExpr expr);
|
||||
|
||||
Result visitFunctionLiteralExpr(FunctionLiteralExpr expr);
|
||||
|
||||
Result visitParenthesizedExpr(ParenthesizedExpr expr);
|
||||
|
||||
Result visitObjectProperty(ObjectMember.ObjectProperty member);
|
||||
|
||||
Result visitObjectMethod(ObjectMember.ObjectMethod member);
|
||||
|
||||
Result visitMemberPredicate(ObjectMember.MemberPredicate member);
|
||||
|
||||
Result visitObjectElement(ObjectMember.ObjectElement member);
|
||||
|
||||
Result visitObjectEntry(ObjectMember.ObjectEntry member);
|
||||
|
||||
Result visitObjectSpread(ObjectMember.ObjectSpread member);
|
||||
|
||||
Result visitWhenGenerator(ObjectMember.WhenGenerator member);
|
||||
|
||||
Result visitForGenerator(ObjectMember.ForGenerator member);
|
||||
|
||||
Result visitModule(Module module);
|
||||
|
||||
Result visitModuleDecl(ModuleDecl decl);
|
||||
|
||||
Result visitExtendsOrAmendsClause(ExtendsOrAmendsClause decl);
|
||||
|
||||
Result visitImportClause(ImportClause imp);
|
||||
|
||||
Result visitClass(Class clazz);
|
||||
|
||||
Result visitModifier(Modifier modifier);
|
||||
|
||||
Result visitClassProperty(ClassProperty entry);
|
||||
|
||||
Result visitClassMethod(ClassMethod entry);
|
||||
|
||||
Result visitClassBody(ClassBody classBody);
|
||||
|
||||
Result visitTypeAlias(TypeAlias typeAlias);
|
||||
|
||||
Result visitAnnotation(Annotation annotation);
|
||||
|
||||
Result visitParameter(Parameter param);
|
||||
|
||||
Result visitParameterList(ParameterList paramList);
|
||||
|
||||
Result visitTypeParameter(TypeParameter typeParameter);
|
||||
|
||||
Result visitTypeParameterList(TypeParameterList typeParameterList);
|
||||
|
||||
Result visitTypeAnnotation(TypeAnnotation typeAnnotation);
|
||||
|
||||
Result visitArgumentList(ArgumentList argumentList);
|
||||
|
||||
Result visitStringPart(StringPart part);
|
||||
|
||||
Result visitDocComment(DocComment docComment);
|
||||
|
||||
Result visitIdentifier(Identifier identifier);
|
||||
|
||||
Result visitQualifiedIdentifier(QualifiedIdentifier qualifiedIdentifier);
|
||||
|
||||
Result visitObjectBody(ObjectBody objectBody);
|
||||
|
||||
Result visitReplInput(ReplInput replInput);
|
||||
|
||||
Result visitKeyword(Keyword keyword);
|
||||
|
||||
Result visitTypeArgumentList(TypeArgumentList typeArgumentList);
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser;
|
||||
|
||||
public record Span(int charIndex, int length) {
|
||||
|
||||
/** Returns a span that starts with this span and ends with {@code end}. */
|
||||
public Span endWith(Span end) {
|
||||
return new Span(charIndex, end.charIndex - charIndex + end.length);
|
||||
}
|
||||
|
||||
/** Checks wheter {@code other} starts directly after this span ends */
|
||||
public boolean adjacent(Span other) {
|
||||
return charIndex + length == other.charIndex;
|
||||
}
|
||||
|
||||
public int stopIndex() {
|
||||
return charIndex + length - 1;
|
||||
}
|
||||
|
||||
public Span stopSpan() {
|
||||
return new Span(charIndex + length - 1, 1);
|
||||
}
|
||||
|
||||
public Span move(int amount) {
|
||||
return new Span(charIndex + amount, length);
|
||||
}
|
||||
|
||||
public Span grow(int amount) {
|
||||
return new Span(charIndex, length + amount);
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser;
|
||||
|
||||
public enum Token {
|
||||
ABSTRACT,
|
||||
AMENDS,
|
||||
AS,
|
||||
CLASS,
|
||||
CONST,
|
||||
ELSE,
|
||||
EXTENDS,
|
||||
EXTERNAL,
|
||||
FALSE,
|
||||
FIXED,
|
||||
FOR,
|
||||
FUNCTION,
|
||||
HIDDEN,
|
||||
IF,
|
||||
IMPORT,
|
||||
IMPORT_STAR,
|
||||
IN,
|
||||
IS,
|
||||
LET,
|
||||
LOCAL,
|
||||
MODULE,
|
||||
NEW,
|
||||
NOTHING,
|
||||
NULL,
|
||||
OPEN,
|
||||
OUT,
|
||||
OUTER,
|
||||
READ,
|
||||
READ_STAR,
|
||||
READ_QUESTION,
|
||||
SUPER,
|
||||
THIS,
|
||||
THROW,
|
||||
TRACE,
|
||||
TRUE,
|
||||
TYPE_ALIAS,
|
||||
UNKNOWN,
|
||||
WHEN,
|
||||
|
||||
// reserved for future use
|
||||
PROTECTED,
|
||||
OVERRIDE,
|
||||
RECORD,
|
||||
DELETE,
|
||||
CASE,
|
||||
SWITCH,
|
||||
VARARG,
|
||||
|
||||
// punctuation
|
||||
LPAREN,
|
||||
RPAREN,
|
||||
LBRACE,
|
||||
RBRACE,
|
||||
LBRACK,
|
||||
RBRACK,
|
||||
LPRED,
|
||||
COMMA,
|
||||
DOT,
|
||||
QDOT,
|
||||
COALESCE,
|
||||
NON_NULL,
|
||||
AT,
|
||||
ASSIGN,
|
||||
GT,
|
||||
LT,
|
||||
|
||||
// rest
|
||||
NOT,
|
||||
QUESTION,
|
||||
COLON,
|
||||
ARROW,
|
||||
EQUAL,
|
||||
NOT_EQUAL,
|
||||
LTE,
|
||||
GTE,
|
||||
AND,
|
||||
OR,
|
||||
PLUS,
|
||||
MINUS,
|
||||
POW,
|
||||
STAR,
|
||||
DIV,
|
||||
INT_DIV,
|
||||
MOD,
|
||||
UNION,
|
||||
PIPE,
|
||||
SPREAD,
|
||||
QSPREAD,
|
||||
UNDERSCORE,
|
||||
EOF,
|
||||
SEMICOLON,
|
||||
|
||||
INT,
|
||||
FLOAT,
|
||||
BIN,
|
||||
OCT,
|
||||
HEX,
|
||||
IDENTIFIER,
|
||||
LINE_COMMENT,
|
||||
BLOCK_COMMENT,
|
||||
DOC_COMMENT,
|
||||
SHEBANG,
|
||||
INTERPOLATION_START,
|
||||
STRING_START,
|
||||
STRING_MULTI_START,
|
||||
STRING_NEWLINE,
|
||||
STRING_ESCAPE_NEWLINE,
|
||||
STRING_ESCAPE_TAB,
|
||||
STRING_ESCAPE_RETURN,
|
||||
STRING_ESCAPE_QUOTE,
|
||||
STRING_ESCAPE_BACKSLASH,
|
||||
STRING_ESCAPE_UNICODE,
|
||||
STRING_END,
|
||||
STRING_PART;
|
||||
|
||||
public boolean isModifier() {
|
||||
return switch (this) {
|
||||
case EXTERNAL, ABSTRACT, OPEN, LOCAL, HIDDEN, FIXED, CONST -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isKeyword() {
|
||||
return switch (this) {
|
||||
case ABSTRACT,
|
||||
AMENDS,
|
||||
AS,
|
||||
CLASS,
|
||||
CONST,
|
||||
ELSE,
|
||||
EXTENDS,
|
||||
EXTERNAL,
|
||||
FALSE,
|
||||
FIXED,
|
||||
FOR,
|
||||
FUNCTION,
|
||||
HIDDEN,
|
||||
IF,
|
||||
IMPORT,
|
||||
IMPORT_STAR,
|
||||
IN,
|
||||
IS,
|
||||
LET,
|
||||
LOCAL,
|
||||
MODULE,
|
||||
NEW,
|
||||
NOTHING,
|
||||
NULL,
|
||||
OPEN,
|
||||
OUT,
|
||||
OUTER,
|
||||
READ,
|
||||
READ_STAR,
|
||||
READ_QUESTION,
|
||||
SUPER,
|
||||
THIS,
|
||||
THROW,
|
||||
TRACE,
|
||||
TRUE,
|
||||
TYPE_ALIAS,
|
||||
UNKNOWN,
|
||||
WHEN,
|
||||
UNDERSCORE,
|
||||
PROTECTED,
|
||||
OVERRIDE,
|
||||
RECORD,
|
||||
DELETE,
|
||||
CASE,
|
||||
SWITCH,
|
||||
VARARG ->
|
||||
true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public String text() {
|
||||
if (this == UNDERSCORE) {
|
||||
return "_";
|
||||
}
|
||||
return name().toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@NonnullByDefault
|
||||
package org.pkl.core.parser;
|
||||
|
||||
import org.pkl.core.util.NonnullByDefault;
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public abstract class AbstractNode implements Node {
|
||||
protected final Span span;
|
||||
protected final @Nullable List<? extends @Nullable Node> children;
|
||||
protected @Nullable Node parent;
|
||||
|
||||
public AbstractNode(Span span, @Nullable List<? extends @Nullable Node> children) {
|
||||
this.span = span;
|
||||
if (children != null) {
|
||||
this.children = Collections.unmodifiableList(children);
|
||||
} else {
|
||||
this.children = null;
|
||||
}
|
||||
|
||||
if (children != null) {
|
||||
for (var node : children) {
|
||||
if (node != null) {
|
||||
node.setParent(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Span span() {
|
||||
return span;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Node parent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParent(Node parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<? extends @Nullable Node> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
AbstractNode that = (AbstractNode) o;
|
||||
return Objects.equals(span, that.span) && Objects.deepEquals(children, that.children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(span, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
var name = getClass().getSimpleName();
|
||||
return name + "{span=" + span + ", children=" + children + '}';
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class Annotation extends AbstractNode {
|
||||
public Annotation(List<Node> nodes, Span span) {
|
||||
super(span, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitAnnotation(this);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(0);
|
||||
}
|
||||
|
||||
public @Nullable ObjectBody getBody() {
|
||||
assert children != null;
|
||||
return (ObjectBody) children.get(1);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class ArgumentList extends AbstractNode {
|
||||
|
||||
public ArgumentList(List<Expr> arguments, Span span) {
|
||||
super(span, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitArgumentList(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Expr> getArguments() {
|
||||
assert children != null;
|
||||
return (List<Expr>) children;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class Class extends AbstractNode {
|
||||
private final int modifiersOffset;
|
||||
private final int keywordOffset;
|
||||
|
||||
public Class(List<Node> nodes, int modifiersOffset, int keywordOffset, Span span) {
|
||||
super(span, nodes);
|
||||
this.modifiersOffset = modifiersOffset;
|
||||
this.keywordOffset = keywordOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitClass(this);
|
||||
}
|
||||
|
||||
public @Nullable DocComment getDocComment() {
|
||||
assert children != null;
|
||||
return (DocComment) children.get(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Annotation> getAnnotations() {
|
||||
assert children != null;
|
||||
return (List<Annotation>) children.subList(1, modifiersOffset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Modifier> getModifiers() {
|
||||
assert children != null;
|
||||
return (List<Modifier>) children.subList(modifiersOffset, keywordOffset);
|
||||
}
|
||||
|
||||
public Keyword getClassKeyword() {
|
||||
assert children != null;
|
||||
return (Keyword) children.get(keywordOffset);
|
||||
}
|
||||
|
||||
public Identifier getName() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(keywordOffset + 1);
|
||||
}
|
||||
|
||||
public @Nullable TypeParameterList getTypeParameterList() {
|
||||
assert children != null;
|
||||
return (TypeParameterList) children.get(keywordOffset + 2);
|
||||
}
|
||||
|
||||
public @Nullable Type getSuperClass() {
|
||||
assert children != null;
|
||||
return (Type) children.get(keywordOffset + 3);
|
||||
}
|
||||
|
||||
public @Nullable ClassBody getBody() {
|
||||
assert children != null;
|
||||
return (ClassBody) children.get(keywordOffset + 4);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public Span getHeaderSpan() {
|
||||
Span start = null;
|
||||
assert children != null;
|
||||
for (var i = modifiersOffset; i < children.size(); i++) {
|
||||
var child = children.get(i);
|
||||
if (child != null) {
|
||||
start = child.span();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Span end;
|
||||
if (getSuperClass() != null) {
|
||||
end = getSuperClass().span();
|
||||
} else if (getTypeParameterList() != null) {
|
||||
end = getTypeParameterList().span();
|
||||
} else {
|
||||
end = getName().span();
|
||||
}
|
||||
assert start != null;
|
||||
return start.endWith(end);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class ClassBody extends AbstractNode {
|
||||
|
||||
public ClassBody(List<Node> nodes, Span span) {
|
||||
super(span, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitClassBody(this);
|
||||
}
|
||||
|
||||
public List<ClassProperty> getProperties() {
|
||||
var props = new ArrayList<ClassProperty>();
|
||||
assert children != null;
|
||||
for (var child : children) {
|
||||
if (child instanceof ClassProperty prop) {
|
||||
props.add(prop);
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
public List<ClassMethod> getMethods() {
|
||||
var methods = new ArrayList<ClassMethod>();
|
||||
assert children != null;
|
||||
for (var child : children) {
|
||||
if (child instanceof ClassMethod method) {
|
||||
methods.add(method);
|
||||
}
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class ClassMethod extends AbstractNode {
|
||||
private final int modifiersOffset;
|
||||
private final int nameOffset;
|
||||
private final Span headerSpan;
|
||||
|
||||
public ClassMethod(
|
||||
List<Node> nodes, int modifiersOffset, int nameOffset, Span headerSpan, Span span) {
|
||||
super(span, nodes);
|
||||
this.headerSpan = headerSpan;
|
||||
this.modifiersOffset = modifiersOffset;
|
||||
this.nameOffset = nameOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitClassMethod(this);
|
||||
}
|
||||
|
||||
public @Nullable DocComment getDocComment() {
|
||||
assert children != null;
|
||||
return (DocComment) children.get(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Annotation> getAnnotations() {
|
||||
assert children != null;
|
||||
return (List<Annotation>) children.subList(1, modifiersOffset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Modifier> getModifiers() {
|
||||
assert children != null;
|
||||
return (List<Modifier>) children.subList(modifiersOffset, nameOffset);
|
||||
}
|
||||
|
||||
public Identifier getName() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(nameOffset);
|
||||
}
|
||||
|
||||
public @Nullable TypeParameterList getTypeParameterList() {
|
||||
assert children != null;
|
||||
return (TypeParameterList) children.get(nameOffset + 1);
|
||||
}
|
||||
|
||||
public ParameterList getParameterList() {
|
||||
assert children != null;
|
||||
return (ParameterList) children.get(nameOffset + 2);
|
||||
}
|
||||
|
||||
public @Nullable TypeAnnotation getTypeAnnotation() {
|
||||
assert children != null;
|
||||
return (TypeAnnotation) children.get(nameOffset + 3);
|
||||
}
|
||||
|
||||
public @Nullable Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(nameOffset + 4);
|
||||
}
|
||||
|
||||
public Span getHeaderSpan() {
|
||||
return headerSpan;
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class ClassProperty extends AbstractNode {
|
||||
private final int modifiersOffset;
|
||||
private final int nameOffset;
|
||||
|
||||
public ClassProperty(List<Node> nodes, int modifiersOffset, int nameOffset, Span span) {
|
||||
super(span, nodes);
|
||||
this.modifiersOffset = modifiersOffset;
|
||||
this.nameOffset = nameOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitClassProperty(this);
|
||||
}
|
||||
|
||||
public @Nullable DocComment getDocComment() {
|
||||
assert children != null;
|
||||
return (DocComment) children.get(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Annotation> getAnnotations() {
|
||||
assert children != null;
|
||||
return (List<Annotation>) children.subList(1, modifiersOffset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Modifier> getModifiers() {
|
||||
assert children != null;
|
||||
return (List<Modifier>) children.subList(modifiersOffset, nameOffset);
|
||||
}
|
||||
|
||||
public Identifier getName() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(nameOffset);
|
||||
}
|
||||
|
||||
public @Nullable TypeAnnotation getTypeAnnotation() {
|
||||
assert children != null;
|
||||
return (TypeAnnotation) children.get(nameOffset + 1);
|
||||
}
|
||||
|
||||
public @Nullable Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(nameOffset + 2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ObjectBody> getBodyList() {
|
||||
assert children != null;
|
||||
return (List<ObjectBody>) children.subList(nameOffset + 3, children.size());
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class DocComment extends AbstractNode {
|
||||
private final List<Span> spans;
|
||||
|
||||
public DocComment(List<Span> spans) {
|
||||
super(spans.get(0).endWith(spans.get(spans.size() - 1)), null);
|
||||
this.spans = spans;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Span span() {
|
||||
return spans.get(0).endWith(spans.get(spans.size() - 1));
|
||||
}
|
||||
|
||||
public List<Span> getSpans() {
|
||||
return spans;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitDocComment(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String text(char[] source) {
|
||||
var builder = new StringBuilder();
|
||||
for (var span : spans) {
|
||||
builder.append(new String(source, span.charIndex(), span.length()));
|
||||
builder.append('\n');
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,732 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public abstract sealed class Expr extends AbstractNode {
|
||||
|
||||
public Expr(Span span, @Nullable List<? extends @Nullable Node> children) {
|
||||
super(span, children);
|
||||
}
|
||||
|
||||
public static final class ThisExpr extends Expr {
|
||||
public ThisExpr(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitThisExpr(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OuterExpr extends Expr {
|
||||
public OuterExpr(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitOuterExpr(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ModuleExpr extends Expr {
|
||||
public ModuleExpr(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitModuleExpr(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class NullLiteralExpr extends Expr {
|
||||
public NullLiteralExpr(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitNullLiteralExpr(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class BoolLiteralExpr extends Expr {
|
||||
private final boolean b;
|
||||
|
||||
public BoolLiteralExpr(boolean b, Span span) {
|
||||
super(span, null);
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitBoolLiteralExpr(this);
|
||||
}
|
||||
|
||||
public boolean isB() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class IntLiteralExpr extends Expr {
|
||||
private final String number;
|
||||
|
||||
public IntLiteralExpr(String number, Span span) {
|
||||
super(span, null);
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitIntLiteralExpr(this);
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class FloatLiteralExpr extends Expr {
|
||||
private final String number;
|
||||
|
||||
public FloatLiteralExpr(String number, Span span) {
|
||||
super(span, null);
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitFloatLiteralExpr(this);
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SingleLineStringLiteralExpr extends Expr {
|
||||
private final Span startDelimiterSpan;
|
||||
private final Span endDelimiterSpan;
|
||||
|
||||
public SingleLineStringLiteralExpr(
|
||||
List<StringPart> parts, Span startDelimiterSpan, Span endDelimiterSpan, Span span) {
|
||||
super(span, parts);
|
||||
this.startDelimiterSpan = startDelimiterSpan;
|
||||
this.endDelimiterSpan = endDelimiterSpan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitSingleLineStringLiteralExpr(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<StringPart> getParts() {
|
||||
assert children != null;
|
||||
return (List<StringPart>) children;
|
||||
}
|
||||
|
||||
public Span getStartDelimiterSpan() {
|
||||
return startDelimiterSpan;
|
||||
}
|
||||
|
||||
public Span getEndDelimiterSpan() {
|
||||
return endDelimiterSpan;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class MultiLineStringLiteralExpr extends Expr {
|
||||
private final Span startDelimiterSpan;
|
||||
private final Span endDelimiterSpan;
|
||||
|
||||
public MultiLineStringLiteralExpr(
|
||||
List<StringPart> parts, Span startDelimiterSpan, Span endDelimiterSpan, Span span) {
|
||||
super(span, parts);
|
||||
this.startDelimiterSpan = startDelimiterSpan;
|
||||
this.endDelimiterSpan = endDelimiterSpan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitMultiLineStringLiteralExpr(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<StringPart> getParts() {
|
||||
assert children != null;
|
||||
return (List<StringPart>) children;
|
||||
}
|
||||
|
||||
public Span getStartDelimiterSpan() {
|
||||
return startDelimiterSpan;
|
||||
}
|
||||
|
||||
public Span getEndDelimiterSpan() {
|
||||
return endDelimiterSpan;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ThrowExpr extends Expr {
|
||||
public ThrowExpr(Expr expr, Span span) {
|
||||
super(span, List.of(expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitThrowExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TraceExpr extends Expr {
|
||||
public TraceExpr(Expr expr, Span span) {
|
||||
super(span, List.of(expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitTraceExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ImportExpr extends Expr {
|
||||
private final boolean isGlob;
|
||||
|
||||
public ImportExpr(StringConstant importStr, boolean isGlob, Span span) {
|
||||
super(span, List.of(importStr));
|
||||
this.isGlob = isGlob;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitImportExpr(this);
|
||||
}
|
||||
|
||||
public StringConstant getImportStr() {
|
||||
assert children != null;
|
||||
return (StringConstant) children.get(0);
|
||||
}
|
||||
|
||||
public boolean isGlob() {
|
||||
return isGlob;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ReadExpr extends Expr {
|
||||
private final ReadType readType;
|
||||
|
||||
public ReadExpr(Expr expr, ReadType readType, Span span) {
|
||||
super(span, List.of(expr));
|
||||
this.readType = readType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitReadExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public ReadType getReadType() {
|
||||
return readType;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ReadType {
|
||||
READ,
|
||||
GLOB,
|
||||
NULL
|
||||
}
|
||||
|
||||
public static final class UnqualifiedAccessExpr extends Expr {
|
||||
public UnqualifiedAccessExpr(
|
||||
Identifier identifier, @Nullable ArgumentList argumentList, Span span) {
|
||||
super(span, Arrays.asList(identifier, argumentList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitUnqualifiedAccessExpr(this);
|
||||
}
|
||||
|
||||
public Identifier getIdentifier() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(0);
|
||||
}
|
||||
|
||||
public @Nullable ArgumentList getArgumentList() {
|
||||
assert children != null;
|
||||
return (ArgumentList) children.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class QualifiedAccessExpr extends Expr {
|
||||
private final boolean isNullable;
|
||||
|
||||
public QualifiedAccessExpr(
|
||||
Expr expr,
|
||||
Identifier identifier,
|
||||
boolean isNullable,
|
||||
@Nullable ArgumentList argumentList,
|
||||
Span span) {
|
||||
super(span, Arrays.asList(expr, identifier, argumentList));
|
||||
this.isNullable = isNullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitQualifiedAccessExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public Identifier getIdentifier() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(1);
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return isNullable;
|
||||
}
|
||||
|
||||
public @Nullable ArgumentList getArgumentList() {
|
||||
assert children != null;
|
||||
return (ArgumentList) children.get(2);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SuperAccessExpr extends Expr {
|
||||
public SuperAccessExpr(Identifier identifier, @Nullable ArgumentList argumentList, Span span) {
|
||||
super(span, Arrays.asList(identifier, argumentList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitSuperAccessExpr(this);
|
||||
}
|
||||
|
||||
public Identifier getIdentifier() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(0);
|
||||
}
|
||||
|
||||
public @Nullable ArgumentList getArgumentList() {
|
||||
assert children != null;
|
||||
return (ArgumentList) children.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SuperSubscriptExpr extends Expr {
|
||||
public SuperSubscriptExpr(Expr arg, Span span) {
|
||||
super(span, List.of(arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitSuperSubscriptExpr(this);
|
||||
}
|
||||
|
||||
public Expr getArg() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SubscriptExpr extends Expr {
|
||||
public SubscriptExpr(Expr expr, Expr arg, Span span) {
|
||||
super(span, List.of(expr, arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitSubscriptExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public Expr getArg() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class IfExpr extends Expr {
|
||||
public IfExpr(Expr cond, Expr then, Expr els, Span span) {
|
||||
super(span, List.of(cond, then, els));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitIfExpr(this);
|
||||
}
|
||||
|
||||
public Expr getCond() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public Expr getThen() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(1);
|
||||
}
|
||||
|
||||
public Expr getEls() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(2);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class LetExpr extends Expr {
|
||||
public LetExpr(Parameter parameter, Expr bindingExpr, Expr expr, Span span) {
|
||||
super(span, List.of(parameter, bindingExpr, expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitLetExpr(this);
|
||||
}
|
||||
|
||||
public Parameter getParameter() {
|
||||
assert children != null;
|
||||
return (Parameter) children.get(0);
|
||||
}
|
||||
|
||||
public Expr getBindingExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(1);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(2);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class FunctionLiteralExpr extends Expr {
|
||||
public FunctionLiteralExpr(ParameterList parameterList, Expr expr, Span span) {
|
||||
super(span, List.of(parameterList, expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitFunctionLiteralExpr(this);
|
||||
}
|
||||
|
||||
public ParameterList getParameterList() {
|
||||
assert children != null;
|
||||
return (ParameterList) children.get(0);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ParenthesizedExpr extends Expr {
|
||||
public ParenthesizedExpr(Expr expr, Span span) {
|
||||
super(span, List.of(expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitParenthesizedExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class NewExpr extends Expr {
|
||||
public NewExpr(@Nullable Type type, ObjectBody body, Span span) {
|
||||
super(span, Arrays.asList(type, body));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitNewExpr(this);
|
||||
}
|
||||
|
||||
public @Nullable Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(0);
|
||||
}
|
||||
|
||||
public ObjectBody getBody() {
|
||||
assert children != null;
|
||||
return (ObjectBody) children.get(1);
|
||||
}
|
||||
|
||||
public Span newSpan() {
|
||||
return new Span(span.charIndex(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class AmendsExpr extends Expr {
|
||||
public AmendsExpr(Expr expr, ObjectBody body, Span span) {
|
||||
super(span, List.of(expr, body));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitAmendsExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public ObjectBody getBody() {
|
||||
assert children != null;
|
||||
return (ObjectBody) children.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class NonNullExpr extends Expr {
|
||||
public NonNullExpr(Expr expr, Span span) {
|
||||
super(span, List.of(expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitNonNullExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class UnaryMinusExpr extends Expr {
|
||||
public UnaryMinusExpr(Expr expr, Span span) {
|
||||
super(span, List.of(expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitUnaryMinusExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class LogicalNotExpr extends Expr {
|
||||
public LogicalNotExpr(Expr expr, Span span) {
|
||||
super(span, List.of(expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitLogicalNotExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class BinaryOperatorExpr extends Expr {
|
||||
private final Operator op;
|
||||
|
||||
public BinaryOperatorExpr(Expr left, Expr right, Operator op, Span span) {
|
||||
super(span, List.of(left, right));
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitBinaryOperatorExpr(this);
|
||||
}
|
||||
|
||||
public Expr getLeft() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public Expr getRight() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(1);
|
||||
}
|
||||
|
||||
public Operator getOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BinaryOp{children=" + children + ", op=" + op + ", span=" + span + '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
BinaryOperatorExpr binaryOp = (BinaryOperatorExpr) o;
|
||||
return Objects.deepEquals(children, binaryOp.children)
|
||||
&& op == binaryOp.op
|
||||
&& Objects.equals(span, binaryOp.span);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(children, op, span);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TypeCheckExpr extends Expr {
|
||||
public TypeCheckExpr(Expr expr, Type type, Span span) {
|
||||
super(span, List.of(expr, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitTypeCheckExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TypeCastExpr extends Expr {
|
||||
public TypeCastExpr(Expr expr, Type type, Span span) {
|
||||
super(span, List.of(expr, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitTypeCastExpr(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
/** This is a synthetic class only used at parse time. */
|
||||
public static final class OperatorExpr extends Expr {
|
||||
private final Operator op;
|
||||
|
||||
public OperatorExpr(Operator op, Span span) {
|
||||
super(span, null);
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
// should never be called
|
||||
throw PklBugException.unreachableCode();
|
||||
}
|
||||
|
||||
public Operator getOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OperatorExpr{op=" + op + ", span=" + span + '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
OperatorExpr that = (OperatorExpr) o;
|
||||
return op == that.op && Objects.equals(span, that.span);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(op, span);
|
||||
}
|
||||
}
|
||||
|
||||
/** This is a synthetic class only used at parse time. */
|
||||
public static final class TypeExpr extends Expr {
|
||||
public TypeExpr(Type type) {
|
||||
super(type.span(), List.of(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
// should never be called
|
||||
throw PklBugException.unreachableCode();
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class ExtendsOrAmendsClause extends AbstractNode {
|
||||
private final Type type;
|
||||
|
||||
public ExtendsOrAmendsClause(StringConstant url, Type type, Span span) {
|
||||
super(span, List.of(url));
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitExtendsOrAmendsClause(this);
|
||||
}
|
||||
|
||||
public StringConstant getUrl() {
|
||||
assert children != null;
|
||||
return (StringConstant) children.get(0);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExtendsOrAmendsClause{"
|
||||
+ "type="
|
||||
+ type
|
||||
+ ", span="
|
||||
+ span
|
||||
+ ", children="
|
||||
+ children
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
ExtendsOrAmendsClause that = (ExtendsOrAmendsClause) o;
|
||||
return type == that.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), type);
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
EXTENDS,
|
||||
AMENDS
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
|
||||
public final class Identifier extends AbstractNode {
|
||||
private final String value;
|
||||
|
||||
public Identifier(String value, Span span) {
|
||||
super(span, null);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitIdentifier(this);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return removeBackticks(value);
|
||||
}
|
||||
|
||||
public String getRawValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private static String removeBackticks(String text) {
|
||||
if (!text.isEmpty() && text.charAt(0) == '`') {
|
||||
// lexer makes sure there's a ` at the end
|
||||
return text.substring(1, text.length() - 1);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Identifier{value='" + value + '\'' + ", span=" + span + '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Identifier identifier = (Identifier) o;
|
||||
return Objects.equals(value, identifier.value) && Objects.equals(span, identifier.span);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(value, span);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class ImportClause extends AbstractNode {
|
||||
private final boolean isGlob;
|
||||
|
||||
public ImportClause(
|
||||
StringConstant importStr, boolean isGlob, @Nullable Identifier alias, Span span) {
|
||||
super(span, Arrays.asList(importStr, alias));
|
||||
this.isGlob = isGlob;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitImportClause(this);
|
||||
}
|
||||
|
||||
public StringConstant getImportStr() {
|
||||
assert children != null;
|
||||
return (StringConstant) children.get(0);
|
||||
}
|
||||
|
||||
public boolean isGlob() {
|
||||
return isGlob;
|
||||
}
|
||||
|
||||
public @Nullable Identifier getAlias() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Import{isGlob=" + isGlob + ", span=" + span + ", children=" + children + '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
ImportClause anImport = (ImportClause) o;
|
||||
return isGlob == anImport.isGlob;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), isGlob);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
|
||||
public class Keyword extends AbstractNode {
|
||||
|
||||
public Keyword(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitKeyword(this);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
|
||||
public final class Modifier extends AbstractNode {
|
||||
private final ModifierValue value;
|
||||
|
||||
public Modifier(ModifierValue value, Span span) {
|
||||
super(span, null);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitModifier(this);
|
||||
}
|
||||
|
||||
public ModifierValue getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Modifier{value=" + value + ", span=" + span + '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Modifier modifier = (Modifier) o;
|
||||
return value == modifier.value && Objects.equals(span, modifier.span);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(value, span);
|
||||
}
|
||||
|
||||
public enum ModifierValue {
|
||||
EXTERNAL,
|
||||
ABSTRACT,
|
||||
OPEN,
|
||||
LOCAL,
|
||||
HIDDEN,
|
||||
FIXED,
|
||||
CONST
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class Module extends AbstractNode {
|
||||
public Module(List<Node> nodes, Span span) {
|
||||
super(span, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitModule(this);
|
||||
}
|
||||
|
||||
public @Nullable ModuleDecl getDecl() {
|
||||
assert children != null;
|
||||
return (ModuleDecl) children.get(0);
|
||||
}
|
||||
|
||||
public List<ImportClause> getImports() {
|
||||
assert children != null;
|
||||
if (children.size() < 2) return List.of();
|
||||
var res = new ArrayList<ImportClause>();
|
||||
for (int i = 1; i < children.size(); i++) {
|
||||
var child = children.get(i);
|
||||
if (child instanceof ImportClause imp) {
|
||||
res.add(imp);
|
||||
} else {
|
||||
// imports are sequential
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<Class> getClasses() {
|
||||
var res = new ArrayList<Class>();
|
||||
assert children != null;
|
||||
for (var child : children) {
|
||||
if (child instanceof Class clazz) {
|
||||
res.add(clazz);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<TypeAlias> getTypeAliases() {
|
||||
var res = new ArrayList<TypeAlias>();
|
||||
assert children != null;
|
||||
for (var child : children) {
|
||||
if (child instanceof TypeAlias typeAlias) {
|
||||
res.add(typeAlias);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<ClassProperty> getProperties() {
|
||||
var res = new ArrayList<ClassProperty>();
|
||||
assert children != null;
|
||||
for (var child : children) {
|
||||
if (child instanceof ClassProperty classProperty) {
|
||||
res.add(classProperty);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<ClassMethod> getMethods() {
|
||||
var res = new ArrayList<ClassMethod>();
|
||||
assert children != null;
|
||||
for (var child : children) {
|
||||
if (child instanceof ClassMethod classMethod) {
|
||||
res.add(classMethod);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class ModuleDecl extends AbstractNode {
|
||||
private final int modifiersOffset;
|
||||
private final int nameOffset;
|
||||
|
||||
public ModuleDecl(List<Node> nodes, int modifiersOffset, int nameOffset, Span span) {
|
||||
super(span, nodes);
|
||||
this.modifiersOffset = modifiersOffset;
|
||||
this.nameOffset = nameOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitModuleDecl(this);
|
||||
}
|
||||
|
||||
public @Nullable DocComment getDocComment() {
|
||||
assert children != null;
|
||||
return (DocComment) children.get(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Annotation> getAnnotations() {
|
||||
assert children != null;
|
||||
return (List<Annotation>) children.subList(1, modifiersOffset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Modifier> getModifiers() {
|
||||
assert children != null;
|
||||
return (List<Modifier>) children.subList(modifiersOffset, nameOffset);
|
||||
}
|
||||
|
||||
public @Nullable Keyword getModuleKeyword() {
|
||||
assert children != null;
|
||||
return (Keyword) children.get(nameOffset);
|
||||
}
|
||||
|
||||
public @Nullable QualifiedIdentifier getName() {
|
||||
assert children != null;
|
||||
return (QualifiedIdentifier) children.get(nameOffset + 1);
|
||||
}
|
||||
|
||||
public @Nullable ExtendsOrAmendsClause getExtendsOrAmendsDecl() {
|
||||
assert children != null;
|
||||
return (ExtendsOrAmendsClause) children.get(nameOffset + 2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public Span headerSpan() {
|
||||
Span start = null;
|
||||
assert children != null;
|
||||
for (var i = modifiersOffset; i < children.size(); i++) {
|
||||
var child = children.get(i);
|
||||
if (child != null) {
|
||||
start = child.span();
|
||||
break;
|
||||
}
|
||||
}
|
||||
var extendsOrAmends = children.get(nameOffset + 2);
|
||||
assert start != null;
|
||||
if (extendsOrAmends != null) {
|
||||
return start.endWith(extendsOrAmends.span());
|
||||
}
|
||||
return start.endWith(children.get(nameOffset + 1).span());
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public interface Node {
|
||||
Span span();
|
||||
|
||||
@Nullable
|
||||
Node parent();
|
||||
|
||||
void setParent(Node parent);
|
||||
|
||||
@Nullable
|
||||
List<? extends @Nullable Node> children();
|
||||
|
||||
<T> T accept(ParserVisitor<? extends T> visitor);
|
||||
|
||||
default String text(char[] source) {
|
||||
return new String(source, span().charIndex(), span().length());
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
|
||||
public final class ObjectBody extends AbstractNode {
|
||||
private final int membersOffset;
|
||||
|
||||
public ObjectBody(List<Node> nodes, int membersOffset, Span span) {
|
||||
super(span, nodes);
|
||||
this.membersOffset = membersOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitObjectBody(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Parameter> getParameters() {
|
||||
assert children != null;
|
||||
return (List<Parameter>) children.subList(0, membersOffset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ObjectMember> getMembers() {
|
||||
assert children != null;
|
||||
return (List<ObjectMember>) children.subList(membersOffset, children.size());
|
||||
}
|
||||
}
|
||||
@@ -1,331 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public abstract sealed class ObjectMember extends AbstractNode {
|
||||
|
||||
public ObjectMember(Span span, @Nullable List<? extends @Nullable Node> children) {
|
||||
super(span, children);
|
||||
}
|
||||
|
||||
public static final class ObjectElement extends ObjectMember {
|
||||
public ObjectElement(Expr expr, Span span) {
|
||||
super(span, List.of(expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitObjectElement(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ObjectProperty extends ObjectMember {
|
||||
private final int identifierOffset;
|
||||
|
||||
public ObjectProperty(List<Node> nodes, int identifierOffset, Span span) {
|
||||
super(span, nodes);
|
||||
this.identifierOffset = identifierOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitObjectProperty(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Modifier> getModifiers() {
|
||||
assert children != null;
|
||||
return (List<Modifier>) children.subList(0, identifierOffset);
|
||||
}
|
||||
|
||||
public Identifier getIdentifier() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(identifierOffset);
|
||||
}
|
||||
|
||||
public @Nullable TypeAnnotation getTypeAnnotation() {
|
||||
assert children != null;
|
||||
return (TypeAnnotation) children.get(identifierOffset + 1);
|
||||
}
|
||||
|
||||
public @Nullable Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(identifierOffset + 2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ObjectBody> getBodyList() {
|
||||
assert children != null;
|
||||
return (List<ObjectBody>) children.subList(identifierOffset + 3, children.size());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ObjectMethod extends ObjectMember {
|
||||
private final int identifierOffset;
|
||||
|
||||
public ObjectMethod(List<Node> nodes, int identifierOffset, Span span) {
|
||||
super(span, nodes);
|
||||
this.identifierOffset = identifierOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitObjectMethod(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Modifier> getModifiers() {
|
||||
assert children != null;
|
||||
return (List<Modifier>) children.subList(0, identifierOffset);
|
||||
}
|
||||
|
||||
public Keyword getFunctionKeyword() {
|
||||
assert children != null;
|
||||
return (Keyword) children.get(identifierOffset);
|
||||
}
|
||||
|
||||
public Identifier getIdentifier() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(identifierOffset + 1);
|
||||
}
|
||||
|
||||
public @Nullable TypeParameterList getTypeParameterList() {
|
||||
assert children != null;
|
||||
return (TypeParameterList) children.get(identifierOffset + 2);
|
||||
}
|
||||
|
||||
public ParameterList getParamList() {
|
||||
assert children != null;
|
||||
return (ParameterList) children.get(identifierOffset + 3);
|
||||
}
|
||||
|
||||
public @Nullable TypeAnnotation getTypeAnnotation() {
|
||||
assert children != null;
|
||||
return (TypeAnnotation) children.get(identifierOffset + 4);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(identifierOffset + 5);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public Span headerSpan() {
|
||||
Span start = null;
|
||||
assert children != null;
|
||||
for (var child : children) {
|
||||
if (child != null) {
|
||||
start = child.span();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Span end;
|
||||
var typeAnnotation = children.get(identifierOffset + 4);
|
||||
if (typeAnnotation == null) {
|
||||
end = children.get(identifierOffset + 3).span();
|
||||
} else {
|
||||
end = typeAnnotation.span();
|
||||
}
|
||||
assert start != null;
|
||||
return start.endWith(end);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class MemberPredicate extends ObjectMember {
|
||||
public MemberPredicate(List<Node> nodes, Span span) {
|
||||
super(span, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitMemberPredicate(this);
|
||||
}
|
||||
|
||||
public Expr getPred() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public @Nullable Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ObjectBody> getBodyList() {
|
||||
assert children != null;
|
||||
return (List<ObjectBody>) children.subList(2, children.size());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ObjectEntry extends ObjectMember {
|
||||
public ObjectEntry(List<Node> nodes, Span span) {
|
||||
super(span, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitObjectEntry(this);
|
||||
}
|
||||
|
||||
public Expr getKey() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public @Nullable Expr getValue() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ObjectBody> getBodyList() {
|
||||
assert children != null;
|
||||
return (List<ObjectBody>) children.subList(2, children.size());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ObjectSpread extends ObjectMember {
|
||||
private final boolean isNullable;
|
||||
|
||||
public ObjectSpread(Expr expr, boolean isNullable, Span span) {
|
||||
super(span, List.of(expr));
|
||||
this.isNullable = isNullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitObjectSpread(this);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return isNullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ObjectSpread{"
|
||||
+ "isNullable="
|
||||
+ isNullable
|
||||
+ ", span="
|
||||
+ span
|
||||
+ ", children="
|
||||
+ children
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
ObjectSpread that = (ObjectSpread) o;
|
||||
return isNullable == that.isNullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), isNullable);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class WhenGenerator extends ObjectMember {
|
||||
public WhenGenerator(
|
||||
Expr predicate, ObjectBody thenClause, @Nullable ObjectBody elseClause, Span span) {
|
||||
super(span, Arrays.asList(predicate, thenClause, elseClause));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitWhenGenerator(this);
|
||||
}
|
||||
|
||||
public Expr getPredicate() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
|
||||
public ObjectBody getThenClause() {
|
||||
assert children != null;
|
||||
return (ObjectBody) children.get(1);
|
||||
}
|
||||
|
||||
public @Nullable ObjectBody getElseClause() {
|
||||
assert children != null;
|
||||
return (ObjectBody) children.get(2);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ForGenerator extends ObjectMember {
|
||||
public ForGenerator(
|
||||
Parameter p1, @Nullable Parameter p2, Expr expr, ObjectBody body, Span span) {
|
||||
super(span, Arrays.asList(p1, p2, expr, body));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitForGenerator(this);
|
||||
}
|
||||
|
||||
public Parameter getP1() {
|
||||
assert children != null;
|
||||
return (Parameter) children.get(0);
|
||||
}
|
||||
|
||||
public @Nullable Parameter getP2() {
|
||||
assert children != null;
|
||||
return (Parameter) children.get(1);
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(2);
|
||||
}
|
||||
|
||||
public ObjectBody getBody() {
|
||||
assert children != null;
|
||||
return (ObjectBody) children.get(3);
|
||||
}
|
||||
|
||||
public Span forSpan() {
|
||||
return new Span(span.charIndex(), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
public enum Operator {
|
||||
POW,
|
||||
MULT,
|
||||
DIV,
|
||||
INT_DIV,
|
||||
MOD,
|
||||
PLUS,
|
||||
MINUS,
|
||||
LT,
|
||||
GT,
|
||||
LTE,
|
||||
GTE,
|
||||
IS,
|
||||
AS,
|
||||
EQ_EQ,
|
||||
NOT_EQ,
|
||||
AND,
|
||||
OR,
|
||||
PIPE,
|
||||
NULL_COALESCE,
|
||||
DOT,
|
||||
QDOT,
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public abstract sealed class Parameter extends AbstractNode {
|
||||
|
||||
public Parameter(Span span, @Nullable List<? extends @Nullable Node> children) {
|
||||
super(span, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitParameter(this);
|
||||
}
|
||||
|
||||
public static final class Underscore extends Parameter {
|
||||
public Underscore(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TypedIdentifier extends Parameter {
|
||||
public TypedIdentifier(
|
||||
Identifier identifier, @Nullable TypeAnnotation typeAnnotation, Span span) {
|
||||
super(span, Arrays.asList(identifier, typeAnnotation));
|
||||
}
|
||||
|
||||
public Identifier getIdentifier() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(0);
|
||||
}
|
||||
|
||||
public @Nullable TypeAnnotation getTypeAnnotation() {
|
||||
assert children != null;
|
||||
return (TypeAnnotation) children.get(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class ParameterList extends AbstractNode {
|
||||
public ParameterList(List<Parameter> parameters, Span span) {
|
||||
super(span, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitParameterList(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Parameter> getParameters() {
|
||||
assert children != null;
|
||||
return (List<Parameter>) children;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
|
||||
public final class QualifiedIdentifier extends AbstractNode {
|
||||
public QualifiedIdentifier(List<Identifier> identifiers) {
|
||||
super(
|
||||
identifiers.get(0).span.endWith(identifiers.get(identifiers.size() - 1).span), identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitQualifiedIdentifier(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Identifier> getIdentifiers() {
|
||||
assert children != null;
|
||||
return (List<Identifier>) children;
|
||||
}
|
||||
|
||||
public String text() {
|
||||
return getIdentifiers().stream().map(Identifier::getValue).collect(Collectors.joining("."));
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class ReplInput extends AbstractNode {
|
||||
public ReplInput(List<Node> nodes, Span span) {
|
||||
super(span, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitReplInput(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Node> getNodes() {
|
||||
assert children != null;
|
||||
return (List<Node>) children;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class StringConstant extends AbstractNode {
|
||||
private final String string;
|
||||
|
||||
public StringConstant(String string, Span span) {
|
||||
super(span, null);
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitStringConstant(this);
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StringConstant{string='" + string + '\'' + ", span=" + span + '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
StringConstant that = (StringConstant) o;
|
||||
return Objects.equals(string, that.string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), string);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public abstract sealed class StringPart extends AbstractNode {
|
||||
|
||||
public StringPart(Span span, @Nullable List<? extends @Nullable Node> children) {
|
||||
super(span, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitStringPart(this);
|
||||
}
|
||||
|
||||
public static final class StringChars extends StringPart {
|
||||
private final String string;
|
||||
|
||||
public StringChars(String string, Span span) {
|
||||
super(span, null);
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StringChars{string='" + string + '\'' + ", span=" + span + '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
StringChars that = (StringChars) o;
|
||||
return Objects.equals(string, that.string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), string);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class StringInterpolation extends StringPart {
|
||||
public StringInterpolation(Expr expr, Span span) {
|
||||
super(span, List.of(expr));
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
assert children != null;
|
||||
return (Expr) children.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public abstract sealed class Type extends AbstractNode {
|
||||
|
||||
public Type(Span span, @Nullable List<? extends @Nullable Node> children) {
|
||||
super(span, children);
|
||||
}
|
||||
|
||||
public static final class UnknownType extends Type {
|
||||
public UnknownType(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitUnknownType(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class NothingType extends Type {
|
||||
public NothingType(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitNothingType(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ModuleType extends Type {
|
||||
public ModuleType(Span span) {
|
||||
super(span, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitModuleType(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class StringConstantType extends Type {
|
||||
public StringConstantType(StringConstant str, Span span) {
|
||||
super(span, List.of(str));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitStringConstantType(this);
|
||||
}
|
||||
|
||||
public StringConstant getStr() {
|
||||
assert children != null;
|
||||
return (StringConstant) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class DeclaredType extends Type {
|
||||
public DeclaredType(QualifiedIdentifier name, @Nullable TypeArgumentList typeArgs, Span span) {
|
||||
super(span, Arrays.asList(name, typeArgs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitDeclaredType(this);
|
||||
}
|
||||
|
||||
public QualifiedIdentifier getName() {
|
||||
assert children != null;
|
||||
return (QualifiedIdentifier) children.get(0);
|
||||
}
|
||||
|
||||
public @Nullable TypeArgumentList getArgs() {
|
||||
assert children != null;
|
||||
return (TypeArgumentList) children.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ParenthesizedType extends Type {
|
||||
public ParenthesizedType(Type type, Span span) {
|
||||
super(span, List.of(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitParenthesizedType(this);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class NullableType extends Type {
|
||||
public NullableType(Type type, Span span) {
|
||||
super(span, List.of(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitNullableType(this);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ConstrainedType extends Type {
|
||||
public ConstrainedType(List<Node> nodes, Span span) {
|
||||
super(span, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitConstrainedType(this);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Expr> getExprs() {
|
||||
assert children != null;
|
||||
return (List<Expr>) children.subList(1, children.size());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class UnionType extends Type {
|
||||
private final int defaultIndex;
|
||||
|
||||
public UnionType(List<Type> types, int defaultIndex, Span span) {
|
||||
super(span, types);
|
||||
this.defaultIndex = defaultIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitUnionType(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Type> getTypes() {
|
||||
assert children != null;
|
||||
return (List<Type>) children;
|
||||
}
|
||||
|
||||
public int getDefaultIndex() {
|
||||
return defaultIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UnionType{"
|
||||
+ "defaultIndex="
|
||||
+ defaultIndex
|
||||
+ ", span="
|
||||
+ span
|
||||
+ ", children="
|
||||
+ children
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
UnionType unionType = (UnionType) o;
|
||||
return defaultIndex == unionType.defaultIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), defaultIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class FunctionType extends Type {
|
||||
public FunctionType(List<Node> children, Span span) {
|
||||
super(span, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitFunctionType(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Type> getArgs() {
|
||||
assert children != null;
|
||||
return (List<Type>) children.subList(0, children.size() - 1);
|
||||
}
|
||||
|
||||
public Type getRet() {
|
||||
assert children != null;
|
||||
return (Type) children.get(children.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class TypeAlias extends AbstractNode {
|
||||
private final int modifiersOffset;
|
||||
private final int nameOffset;
|
||||
|
||||
public TypeAlias(List<Node> children, int modifiersOffset, int nameOffset, Span span) {
|
||||
super(span, children);
|
||||
this.modifiersOffset = modifiersOffset;
|
||||
this.nameOffset = nameOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitTypeAlias(this);
|
||||
}
|
||||
|
||||
public @Nullable DocComment getDocComment() {
|
||||
assert children != null;
|
||||
return (DocComment) children.get(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Annotation> getAnnotations() {
|
||||
assert children != null;
|
||||
return (List<Annotation>) children.subList(1, modifiersOffset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Modifier> getModifiers() {
|
||||
assert children != null;
|
||||
return (List<Modifier>) children.subList(modifiersOffset, nameOffset);
|
||||
}
|
||||
|
||||
public Keyword getTypealiasKeyword() {
|
||||
assert children != null;
|
||||
return (Keyword) children.get(nameOffset);
|
||||
}
|
||||
|
||||
public Identifier getName() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(nameOffset + 1);
|
||||
}
|
||||
|
||||
public @Nullable TypeParameterList getTypeParameterList() {
|
||||
assert children != null;
|
||||
return (TypeParameterList) children.get(nameOffset + 2);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(nameOffset + 3);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public Span getHeaderSpan() {
|
||||
Span start = null;
|
||||
assert children != null;
|
||||
for (var i = modifiersOffset; i < children.size(); i++) {
|
||||
var child = children.get(i);
|
||||
if (child != null) {
|
||||
start = child.span();
|
||||
break;
|
||||
}
|
||||
}
|
||||
var end = children.get(nameOffset + 1).span();
|
||||
var tparList = children.get(nameOffset + 2);
|
||||
if (tparList != null) {
|
||||
end = tparList.span();
|
||||
}
|
||||
assert start != null;
|
||||
return start.endWith(end);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class TypeAnnotation extends AbstractNode {
|
||||
public TypeAnnotation(Type type, Span span) {
|
||||
super(span, List.of(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitTypeAnnotation(this);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
assert children != null;
|
||||
return (Type) children.get(0);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
|
||||
public class TypeArgumentList extends AbstractNode {
|
||||
|
||||
public TypeArgumentList(List<Type> children, Span span) {
|
||||
super(span, children);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Type> getTypes() {
|
||||
assert children != null;
|
||||
return (List<Type>) children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitTypeArgumentList(this);
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class TypeParameter extends AbstractNode {
|
||||
private final @Nullable Variance variance;
|
||||
|
||||
public TypeParameter(@Nullable Variance variance, Identifier identifier, Span span) {
|
||||
super(span, List.of(identifier));
|
||||
this.variance = variance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitTypeParameter(this);
|
||||
}
|
||||
|
||||
public @Nullable Variance getVariance() {
|
||||
return variance;
|
||||
}
|
||||
|
||||
public Identifier getIdentifier() {
|
||||
assert children != null;
|
||||
return (Identifier) children.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TypeParameter{"
|
||||
+ "variance="
|
||||
+ variance
|
||||
+ ", children="
|
||||
+ children
|
||||
+ ", span="
|
||||
+ span
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
TypeParameter that = (TypeParameter) o;
|
||||
return variance == that.variance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), variance);
|
||||
}
|
||||
|
||||
public enum Variance {
|
||||
IN,
|
||||
OUT
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import java.util.List;
|
||||
import org.pkl.core.parser.ParserVisitor;
|
||||
import org.pkl.core.parser.Span;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public class TypeParameterList extends AbstractNode {
|
||||
public TypeParameterList(List<TypeParameter> parameters, Span span) {
|
||||
super(span, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> @Nullable T accept(ParserVisitor<? extends T> visitor) {
|
||||
return visitor.visitTypeParameterList(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<TypeParameter> getParameters() {
|
||||
assert children != null;
|
||||
return (List<TypeParameter>) children;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@NonnullByDefault
|
||||
package org.pkl.core.parser.syntax;
|
||||
|
||||
import org.pkl.core.util.NonnullByDefault;
|
||||
@@ -35,14 +35,6 @@ import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.http.HttpClient;
|
||||
import org.pkl.core.module.*;
|
||||
import org.pkl.core.packages.PackageResolver;
|
||||
import org.pkl.core.parser.Parser;
|
||||
import org.pkl.core.parser.ParserError;
|
||||
import org.pkl.core.parser.syntax.Class;
|
||||
import org.pkl.core.parser.syntax.ClassProperty;
|
||||
import org.pkl.core.parser.syntax.Expr;
|
||||
import org.pkl.core.parser.syntax.ImportClause;
|
||||
import org.pkl.core.parser.syntax.ModuleDecl;
|
||||
import org.pkl.core.parser.syntax.ReplInput;
|
||||
import org.pkl.core.project.DeclaredDependencies;
|
||||
import org.pkl.core.repl.ReplRequest.Eval;
|
||||
import org.pkl.core.repl.ReplRequest.Load;
|
||||
@@ -56,6 +48,14 @@ import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.core.util.MutableReference;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.parser.Parser;
|
||||
import org.pkl.parser.ParserError;
|
||||
import org.pkl.parser.syntax.Class;
|
||||
import org.pkl.parser.syntax.ClassProperty;
|
||||
import org.pkl.parser.syntax.Expr;
|
||||
import org.pkl.parser.syntax.ImportClause;
|
||||
import org.pkl.parser.syntax.ModuleDecl;
|
||||
import org.pkl.parser.syntax.ReplInput;
|
||||
|
||||
public class ReplServer implements AutoCloseable {
|
||||
private final IndirectCallNode callNode = Truffle.getRuntime().createIndirectCallNode();
|
||||
@@ -222,9 +222,9 @@ public class ReplServer implements AutoCloseable {
|
||||
}
|
||||
} else if (tree instanceof Class clazz) {
|
||||
addStaticModuleProperty(builder.visitClass(clazz));
|
||||
} else if (tree instanceof org.pkl.core.parser.syntax.TypeAlias typeAlias) {
|
||||
} else if (tree instanceof org.pkl.parser.syntax.TypeAlias typeAlias) {
|
||||
addStaticModuleProperty(builder.visitTypeAlias(typeAlias));
|
||||
} else if (tree instanceof org.pkl.core.parser.syntax.ClassMethod classMethod) {
|
||||
} else if (tree instanceof org.pkl.parser.syntax.ClassMethod classMethod) {
|
||||
addModuleMethodDef(builder.visitClassMethod(classMethod));
|
||||
} else if (tree instanceof ModuleDecl) {
|
||||
// do nothing for now
|
||||
|
||||
@@ -18,11 +18,11 @@ package org.pkl.core.runtime;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.pkl.core.Release;
|
||||
import org.pkl.core.Version;
|
||||
import org.pkl.core.parser.syntax.Module;
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectProperty;
|
||||
import org.pkl.core.parser.syntax.Type;
|
||||
import org.pkl.core.parser.syntax.Type.DeclaredType;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.parser.syntax.Module;
|
||||
import org.pkl.parser.syntax.ObjectMember.ObjectProperty;
|
||||
import org.pkl.parser.syntax.Type;
|
||||
import org.pkl.parser.syntax.Type.DeclaredType;
|
||||
|
||||
final class MinPklVersionChecker {
|
||||
private static final Version currentVersion = Release.current().version();
|
||||
|
||||
@@ -24,11 +24,11 @@ import com.oracle.truffle.api.source.Source;
|
||||
import org.pkl.core.ast.builder.AstBuilder;
|
||||
import org.pkl.core.module.ModuleKey;
|
||||
import org.pkl.core.module.ResolvedModuleKey;
|
||||
import org.pkl.core.parser.Parser;
|
||||
import org.pkl.core.parser.ParserError;
|
||||
import org.pkl.core.parser.syntax.Module;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.parser.Parser;
|
||||
import org.pkl.parser.ParserError;
|
||||
import org.pkl.parser.syntax.Module;
|
||||
|
||||
@TruffleLanguage.Registration(
|
||||
id = "pkl",
|
||||
|
||||
@@ -22,8 +22,8 @@ import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.pkl.core.StackFrame;
|
||||
import org.pkl.core.parser.Lexer;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.parser.Lexer;
|
||||
|
||||
public final class VmUndefinedValueException extends VmEvalException {
|
||||
private final @Nullable Object receiver;
|
||||
|
||||
@@ -56,11 +56,11 @@ import org.pkl.core.ast.type.UnresolvedTypeNode;
|
||||
import org.pkl.core.module.ModuleKey;
|
||||
import org.pkl.core.module.ModuleKeys;
|
||||
import org.pkl.core.module.ResolvedModuleKey;
|
||||
import org.pkl.core.parser.Parser;
|
||||
import org.pkl.core.parser.ParserError;
|
||||
import org.pkl.core.parser.syntax.Expr;
|
||||
import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.parser.Parser;
|
||||
import org.pkl.parser.ParserError;
|
||||
import org.pkl.parser.syntax.Expr;
|
||||
|
||||
public final class VmUtils {
|
||||
/** See {@link VmUtils#shouldRunTypeCheck(VirtualFrame)}. */
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.pkl.core.runtime;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import org.pkl.core.ValueFormatter;
|
||||
import org.pkl.core.parser.Lexer;
|
||||
import org.pkl.core.util.MutableBoolean;
|
||||
import org.pkl.parser.Lexer;
|
||||
|
||||
/**
|
||||
* Renders values for use in REPL and error messages. Does not force values to avoid consecutive
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.pkl.core.stdlib.base;
|
||||
|
||||
import org.pkl.core.ValueFormatter;
|
||||
import org.pkl.core.parser.Lexer;
|
||||
import org.pkl.core.runtime.Identifier;
|
||||
import org.pkl.core.runtime.VmDataSize;
|
||||
import org.pkl.core.runtime.VmDuration;
|
||||
@@ -37,6 +36,7 @@ import org.pkl.core.runtime.VmUtils;
|
||||
import org.pkl.core.stdlib.AbstractRenderer;
|
||||
import org.pkl.core.stdlib.PklConverter;
|
||||
import org.pkl.core.util.LateInit;
|
||||
import org.pkl.parser.Lexer;
|
||||
|
||||
public final class PcfRenderer extends AbstractRenderer {
|
||||
private final ValueFormatter valueFormatter;
|
||||
|
||||
@@ -99,11 +99,6 @@ A local property definition cannot be amended.\n\
|
||||
\n\
|
||||
Use definition syntax instead, for example `local person = new { ... }` instead of `local person { ... }`.
|
||||
|
||||
unexpectedCurlyProbablyAmendsExpression=\
|
||||
Unexpected token: `'{'`.\n\
|
||||
\n\
|
||||
If you meant to write an amends expression, wrap the parent in parentheses. Try: `({0}) '{' ... '}'`
|
||||
|
||||
moduleCannotExtendSelf=\
|
||||
Module `{0}` cannot extend itself.
|
||||
|
||||
@@ -217,35 +212,6 @@ Expected {0} type argument(s) but got {1}.
|
||||
duplicateDefinition=\
|
||||
Duplicate definition of member `{0}`.
|
||||
|
||||
invalidCharacterEscapeSequence=\
|
||||
Invalid character escape sequence `{0}`.\n\
|
||||
\n\
|
||||
Valid character escape sequences are: {1}n {1}r {1}t {1}" {1}\\
|
||||
|
||||
unterminatedUnicodeEscapeSequence=\
|
||||
Unterminated Unicode escape sequence `{0}`.\n\
|
||||
\n\
|
||||
Unicode escape sequences must end with `}`.
|
||||
|
||||
invalidUnicodeEscapeSequence=\
|
||||
Invalid Unicode escape sequence `{0}`.\n\
|
||||
\n\
|
||||
Valid Unicode escape sequences are {1}'{'0'}' to {1}'{'10FFFF'}' (1-6 hexadecimal characters).
|
||||
|
||||
invalidSeparatorPosition=\
|
||||
Unexpected separator character.\n\
|
||||
\n\
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
|
||||
stringContentMustBeginOnNewLine=\
|
||||
The content of a multi-line string must begin on a new line.
|
||||
|
||||
closingStringDelimiterMustBeginOnNewLine=\
|
||||
The closing delimiter of a multi-line string must begin on a new line.
|
||||
|
||||
stringIndentationMustMatchLastLine=\
|
||||
Line must match or exceed indentation of the String's last line.
|
||||
|
||||
floatTooLarge=\
|
||||
Float literal `{0}` is too large.
|
||||
|
||||
@@ -704,11 +670,6 @@ Cannot resolve a triple-dot import from module URI `{0}`.\n\
|
||||
\n\
|
||||
Triple-dot imports may only be resolved by module schemes that are considered local, and have hierarchical URIs.
|
||||
|
||||
moduleDoesNotSupportDependencies=\
|
||||
Module `{0}` does not support importing dependencies.\n\
|
||||
\n\
|
||||
Dependencies can only be imported in modules that belong to a project, or within a package.
|
||||
|
||||
cannotHaveRelativeImport=\
|
||||
Module `{0}` cannot have a relative import URI.
|
||||
|
||||
@@ -764,18 +725,6 @@ A value of type `{0}` cannot be exported.
|
||||
incompatiblePklVersion=\
|
||||
Module `{0}` requires Pkl version {1} or higher, but your Pkl version is {2}.
|
||||
|
||||
missingDelimiter=\
|
||||
Missing `{0}` delimiter.
|
||||
|
||||
wrongDelimiter=\
|
||||
Expected delimiter `{0}`, but got `{1}`.
|
||||
|
||||
danglingDelimiter=\
|
||||
Unmatched delimiter `{0}`.
|
||||
|
||||
missingCommaSeparator=\
|
||||
Missing `,` separator.
|
||||
|
||||
missingFixedModifier=\
|
||||
Missing modifier `fixed`.\n\
|
||||
\n\
|
||||
@@ -855,12 +804,6 @@ The problematic cycles are those declared as local dependencies.\n\
|
||||
\n\
|
||||
{0}
|
||||
|
||||
multipleUnionDefaults=\
|
||||
A type union cannot have more than one default type.
|
||||
|
||||
notAUnion=\
|
||||
Only type unions can have a default marker (*).
|
||||
|
||||
invalidModuleOutput=\
|
||||
Expected `{0}` of module `{3}` to be of type `{1}`, but got type `{2}`.
|
||||
|
||||
@@ -878,11 +821,6 @@ Cannot find a dependency named `{0}`, because it is not declared in the current
|
||||
\n\
|
||||
To fix this, add it to the `dependencies` section of your `PklProject` file, and resolve your dependencies.
|
||||
|
||||
cannotResolveDependencyFromReaderWithOpaqueUris=\
|
||||
Cannot resolve dependencies from module reader with opaque URIs.\n\
|
||||
\n\
|
||||
Module reader for scheme `{0}` does not support hierarchical URIs.
|
||||
|
||||
cannotFindDependencyInPackage=\
|
||||
Cannot find dependency named `{0}`, because it was not declared in package `{1}`.
|
||||
|
||||
@@ -1080,14 +1018,6 @@ The only supported checksum algorithm is sha256.
|
||||
testsFailed=\
|
||||
Tests failed.
|
||||
|
||||
expectedJarOrFileUrl=\
|
||||
Certificates can only be loaded from `jar:` or `file:` URLs, but got:\n\
|
||||
{0}
|
||||
|
||||
cannotFindBuiltInCertificates=\
|
||||
Cannot find Pkl's trusted CA certificates on the class path.\n\
|
||||
To fix this problem, add dependency `org.pkl:pkl-certs`.
|
||||
|
||||
# suppress inspection "HttpUrlsUsage"
|
||||
malformedProxyAddress=\
|
||||
Malformed proxy URI (expecting `http://<host>[:<port>]`): `{0}`.
|
||||
@@ -1127,58 +1057,3 @@ External {0} reader does not support scheme `{1}`.
|
||||
|
||||
externalReaderAlreadyTerminated=\
|
||||
External reader process has already terminated.
|
||||
|
||||
keywordNotAllowedHere=\
|
||||
Keyword `{0}` is not allowed here.\n\
|
||||
\n\
|
||||
If you must use this name as identifier, enclose it in backticks.
|
||||
|
||||
unexpectedEndOfFile=\
|
||||
Unexpected end of file.
|
||||
|
||||
wrongHeaders=\
|
||||
{0} cannot have doc comments, annotations or modifiers.
|
||||
|
||||
invalidTopLevelToken=\
|
||||
Invalid token at position. Expected a class, typealias, method, or property.
|
||||
|
||||
interpolationInConstant=\
|
||||
String constant cannot have interpolated values.
|
||||
|
||||
unexpectedToken=\
|
||||
Unexpected token `{0}`. Expected `{1}`.
|
||||
|
||||
unexpectedToken2=\
|
||||
Unexpected token `{0}`. Expected `{1}` or `{2}`.
|
||||
|
||||
unexpectedTokenForExpression=\
|
||||
Unexpected token `{0}`.
|
||||
|
||||
unexpectedTokenForType=\
|
||||
Unexpected token `{0}`. Expected a type.
|
||||
|
||||
unexpectedTokenForType2=\
|
||||
Unexpected token `{0}`. Expected a type or `{1}`.
|
||||
|
||||
typeAnnotationInAmends=\
|
||||
Properties with type annotations cannot have object bodies.\n\
|
||||
\n\
|
||||
To define both a type annotation and an object body, try using assignment instead.\n\
|
||||
For example: `obj: Bird = new { ... }`.
|
||||
|
||||
invalidProperty=\
|
||||
Invalid property definition. Expected a type annotation, `=` or `{`.
|
||||
|
||||
unexpectedCharacter=\
|
||||
Unexpected character `{0}`. Did you mean `{1}`?
|
||||
|
||||
unexpectedCharacter3=\
|
||||
Unexpected character `{0}`. Did you mean `{1}`, `{2}` or `{3}`?
|
||||
|
||||
invalidCharacter=\
|
||||
Invalid identifier `{0}`.
|
||||
|
||||
danglingDocComment=\
|
||||
Dangling documentation comment.\n\
|
||||
\n\
|
||||
Documentation comments must be attached to modules, classes, typealiases, methods, or properties.
|
||||
|
||||
@@ -1,387 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
lexer grammar PklLexer;
|
||||
|
||||
@header {
|
||||
package org.pkl.core.parser.antlr;
|
||||
}
|
||||
|
||||
@members {
|
||||
class StringInterpolationScope {
|
||||
int parenLevel = 0;
|
||||
int poundLength = 0;
|
||||
}
|
||||
|
||||
java.util.Deque<StringInterpolationScope> interpolationScopes = new java.util.ArrayDeque<>();
|
||||
StringInterpolationScope interpolationScope;
|
||||
|
||||
{ pushInterpolationScope(); }
|
||||
|
||||
void pushInterpolationScope() {
|
||||
interpolationScope = new StringInterpolationScope();
|
||||
interpolationScopes.push(interpolationScope);
|
||||
}
|
||||
|
||||
void incParenLevel() {
|
||||
interpolationScope.parenLevel += 1;
|
||||
}
|
||||
|
||||
void decParenLevel() {
|
||||
if (interpolationScope.parenLevel == 0) {
|
||||
// guard against syntax errors
|
||||
if (interpolationScopes.size() > 1) {
|
||||
interpolationScopes.pop();
|
||||
interpolationScope = interpolationScopes.peek();
|
||||
popMode();
|
||||
}
|
||||
} else {
|
||||
interpolationScope.parenLevel -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isPounds() {
|
||||
// optimize for common cases (0, 1)
|
||||
switch (interpolationScope.poundLength) {
|
||||
case 0: return true;
|
||||
case 1: return _input.LA(1) == '#';
|
||||
default:
|
||||
int poundLength = interpolationScope.poundLength;
|
||||
for (int i = 1; i <= poundLength; i++) {
|
||||
if (_input.LA(i) != '#') return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isQuote() {
|
||||
return _input.LA(1) == '"';
|
||||
}
|
||||
|
||||
boolean endsWithPounds(String text) {
|
||||
assert text.length() >= 2;
|
||||
|
||||
// optimize for common cases (0, 1)
|
||||
switch (interpolationScope.poundLength) {
|
||||
case 0: return true;
|
||||
case 1: return text.charAt(text.length() - 1) == '#';
|
||||
default:
|
||||
int poundLength = interpolationScope.poundLength;
|
||||
int textLength = text.length();
|
||||
if (textLength < poundLength) return false;
|
||||
|
||||
int stop = textLength - poundLength;
|
||||
for (int i = textLength - 1; i >= stop; i--) {
|
||||
if (text.charAt(i) != '#') return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void removeBackTicks() {
|
||||
String text = getText();
|
||||
setText(text.substring(1, text.length() - 1));
|
||||
}
|
||||
|
||||
// look ahead in predicate rather than consume in grammar so that newlines
|
||||
// go to NewlineSemicolonChannel, which is important for consumers of that channel
|
||||
boolean isNewlineOrEof() {
|
||||
int input = _input.LA(1);
|
||||
return input == '\n' || input == '\r' || input == IntStream.EOF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
channels {
|
||||
NewlineSemicolonChannel,
|
||||
WhitespaceChannel,
|
||||
CommentsChannel,
|
||||
ShebangChannel
|
||||
}
|
||||
|
||||
ABSTRACT : 'abstract';
|
||||
AMENDS : 'amends';
|
||||
AS : 'as';
|
||||
CLASS : 'class';
|
||||
CONST : 'const';
|
||||
ELSE : 'else';
|
||||
EXTENDS : 'extends';
|
||||
EXTERNAL : 'external';
|
||||
FALSE : 'false';
|
||||
FIXED : 'fixed';
|
||||
FOR : 'for';
|
||||
FUNCTION : 'function';
|
||||
HIDDEN_ : 'hidden';
|
||||
IF : 'if';
|
||||
IMPORT : 'import';
|
||||
IMPORT_GLOB : 'import*';
|
||||
IN : 'in';
|
||||
IS : 'is';
|
||||
LET : 'let';
|
||||
LOCAL : 'local';
|
||||
MODULE : 'module';
|
||||
NEW : 'new';
|
||||
NOTHING : 'nothing';
|
||||
NULL : 'null';
|
||||
OPEN : 'open';
|
||||
OUT : 'out';
|
||||
OUTER : 'outer';
|
||||
READ : 'read';
|
||||
READ_GLOB : 'read*';
|
||||
READ_OR_NULL : 'read?';
|
||||
SUPER : 'super';
|
||||
THIS : 'this';
|
||||
THROW : 'throw';
|
||||
TRACE : 'trace';
|
||||
TRUE : 'true';
|
||||
TYPE_ALIAS : 'typealias';
|
||||
UNKNOWN : 'unknown';
|
||||
WHEN : 'when';
|
||||
|
||||
// reserved for future use, but not used today
|
||||
PROTECTED : 'protected';
|
||||
OVERRIDE : 'override';
|
||||
RECORD : 'record';
|
||||
DELETE : 'delete';
|
||||
CASE : 'case';
|
||||
SWITCH : 'switch';
|
||||
VARARG : 'vararg';
|
||||
|
||||
LPAREN : '(' { incParenLevel(); };
|
||||
RPAREN : ')' { decParenLevel(); };
|
||||
LBRACE : '{';
|
||||
RBRACE : '}';
|
||||
LBRACK : '[';
|
||||
RBRACK : ']';
|
||||
LPRED : '[['; // No RPRED, because that lexes too eager to allow nested index expressions, e.g. foo[bar[baz]]
|
||||
COMMA : ',';
|
||||
DOT : '.';
|
||||
QDOT : '?.';
|
||||
COALESCE : '??';
|
||||
NON_NULL : '!!';
|
||||
|
||||
AT : '@';
|
||||
ASSIGN : '=';
|
||||
GT : '>';
|
||||
LT : '<';
|
||||
NOT : '!';
|
||||
QUESTION : '?';
|
||||
COLON : ':';
|
||||
ARROW : '->';
|
||||
EQUAL : '==';
|
||||
NOT_EQUAL : '!=';
|
||||
LTE : '<=';
|
||||
GTE : '>=';
|
||||
AND : '&&';
|
||||
OR : '||';
|
||||
PLUS : '+';
|
||||
MINUS : '-';
|
||||
POW : '**';
|
||||
STAR : '*';
|
||||
DIV : '/';
|
||||
INT_DIV : '~/';
|
||||
MOD : '%';
|
||||
UNION : '|';
|
||||
PIPE : '|>';
|
||||
SPREAD : '...';
|
||||
QSPREAD : '...?';
|
||||
UNDERSCORE : '_';
|
||||
|
||||
SLQuote : '#'* '"' { interpolationScope.poundLength = getText().length() - 1; } -> pushMode(SLString);
|
||||
MLQuote : '#'* '"""' { interpolationScope.poundLength = getText().length() - 3; } -> pushMode(MLString);
|
||||
|
||||
IntLiteral
|
||||
: DecimalLiteral
|
||||
| HexadecimalLiteral
|
||||
| BinaryLiteral
|
||||
| OctalLiteral
|
||||
;
|
||||
|
||||
// leading zeros are allowed (cf. Swift)
|
||||
fragment DecimalLiteral
|
||||
: DecimalDigit DecimalDigitCharacters?
|
||||
;
|
||||
|
||||
fragment DecimalDigitCharacters
|
||||
: DecimalDigitCharacter+
|
||||
;
|
||||
|
||||
fragment DecimalDigitCharacter
|
||||
: DecimalDigit
|
||||
| '_'
|
||||
;
|
||||
|
||||
fragment DecimalDigit
|
||||
: [0-9]
|
||||
;
|
||||
|
||||
fragment HexadecimalLiteral
|
||||
: '0x' HexadecimalCharacter+ // intentionally allow underscore after '0x'; e.g. `0x_ab`. We will throw an error in AstBuilder.
|
||||
;
|
||||
|
||||
fragment HexadecimalCharacter
|
||||
: [0-9a-fA-F_]
|
||||
;
|
||||
|
||||
fragment BinaryLiteral
|
||||
: '0b' BinaryCharacter+ // intentionally allow underscore after '0b'; e.g. `0b_11`. We will throw an error in AstBuilder.
|
||||
;
|
||||
|
||||
fragment BinaryCharacter
|
||||
: [01_]
|
||||
;
|
||||
|
||||
fragment OctalLiteral
|
||||
: '0o' OctalCharacter+ // intentionally allow underscore after '0o'; e.g. `0o_34`. We will throw an error in AstBuilder.
|
||||
;
|
||||
|
||||
fragment OctalCharacter
|
||||
: [0-7_]
|
||||
;
|
||||
|
||||
FloatLiteral
|
||||
: DecimalLiteral? '.' '_'? DecimalLiteral Exponent? // intentionally allow underscore. We will throw an error in AstBuilder.
|
||||
| DecimalLiteral Exponent
|
||||
;
|
||||
|
||||
fragment Exponent
|
||||
: [eE] [+-]? '_'? DecimalLiteral // intentionally allow underscore. We will throw an error in AstBuilder.
|
||||
;
|
||||
|
||||
Identifier
|
||||
: RegularIdentifier
|
||||
| QuotedIdentifier { removeBackTicks(); }
|
||||
;
|
||||
|
||||
// Note: Keep in sync with Lexer.isRegularIdentifier()
|
||||
fragment RegularIdentifier
|
||||
: IdentifierStart IdentifierPart*
|
||||
;
|
||||
|
||||
fragment QuotedIdentifier
|
||||
: '`' (~'`')+ '`'
|
||||
;
|
||||
|
||||
fragment
|
||||
IdentifierStart
|
||||
: [a-zA-Z$_] // handle common cases without a predicate
|
||||
| . {Character.isUnicodeIdentifierStart(_input.LA(-1))}?
|
||||
;
|
||||
|
||||
fragment
|
||||
IdentifierPart
|
||||
: [a-zA-Z0-9$_] // handle common cases without a predicate
|
||||
| . {Character.isUnicodeIdentifierPart(_input.LA(-1))}?
|
||||
;
|
||||
|
||||
NewlineSemicolon
|
||||
: [\r\n;]+ -> channel(NewlineSemicolonChannel)
|
||||
;
|
||||
|
||||
// Note: Java, Scala, and Swift treat \f as whitespace; Dart doesn't.
|
||||
// Python and C also include vertical tab.
|
||||
// C# also includes Unicode class Zs (separator, space).
|
||||
Whitespace
|
||||
: [ \t\f]+ -> channel(WhitespaceChannel)
|
||||
;
|
||||
|
||||
DocComment
|
||||
: ([ \t\f]* '///' .*? (Newline|EOF))+
|
||||
;
|
||||
|
||||
BlockComment
|
||||
: '/*' (BlockComment | .)*? '*/' -> channel(CommentsChannel)
|
||||
;
|
||||
|
||||
LineComment
|
||||
: '//' .*? {isNewlineOrEof()}? -> channel(CommentsChannel)
|
||||
;
|
||||
|
||||
ShebangComment
|
||||
: '#!' .*? {isNewlineOrEof()}? -> channel(ShebangChannel)
|
||||
;
|
||||
|
||||
// strict: '\\' Pounds 'u{' HexDigit (HexDigit (HexDigit (HexDigit (HexDigit (HexDigit (HexDigit HexDigit? )?)?)?)?)?)? '}'
|
||||
fragment UnicodeEscape
|
||||
: '\\' Pounds 'u{' ~[}\r\n "]* '}'?
|
||||
;
|
||||
|
||||
// strict: '\\' Pounds [tnr"\\]
|
||||
fragment CharacterEscape
|
||||
: '\\' Pounds .
|
||||
;
|
||||
|
||||
fragment Pounds
|
||||
: { interpolationScope.poundLength == 0 }?
|
||||
| '#' { interpolationScope.poundLength == 1 }?
|
||||
| '#'+ { endsWithPounds(getText()) }?
|
||||
;
|
||||
|
||||
fragment Newline
|
||||
: '\n' | '\r' '\n'?
|
||||
;
|
||||
|
||||
mode SLString;
|
||||
|
||||
// strict: '"' Pounds
|
||||
SLEndQuote
|
||||
: ('"' Pounds | Newline ) -> popMode
|
||||
;
|
||||
|
||||
SLInterpolation
|
||||
: '\\' Pounds '(' { pushInterpolationScope(); } -> pushMode(DEFAULT_MODE)
|
||||
;
|
||||
|
||||
SLUnicodeEscape
|
||||
: UnicodeEscape
|
||||
;
|
||||
|
||||
SLCharacterEscape
|
||||
: CharacterEscape
|
||||
;
|
||||
|
||||
SLCharacters
|
||||
: ~["\\\r\n]+ SLCharacters?
|
||||
| ["\\] {!isPounds()}? SLCharacters?
|
||||
;
|
||||
|
||||
mode MLString;
|
||||
|
||||
MLEndQuote
|
||||
: '"""' Pounds -> popMode
|
||||
;
|
||||
|
||||
MLInterpolation
|
||||
: '\\' Pounds '(' { pushInterpolationScope(); } -> pushMode(DEFAULT_MODE)
|
||||
;
|
||||
|
||||
MLUnicodeEscape
|
||||
: UnicodeEscape
|
||||
;
|
||||
|
||||
MLCharacterEscape
|
||||
: CharacterEscape
|
||||
;
|
||||
|
||||
MLNewline
|
||||
: Newline
|
||||
;
|
||||
|
||||
MLCharacters
|
||||
: ~["\\\r\n]+ MLCharacters?
|
||||
| ('\\' | '"""') {!isPounds()}? MLCharacters?
|
||||
| '"' '"'? {!isQuote()}? MLCharacters?
|
||||
;
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
parser grammar PklParser;
|
||||
|
||||
@header {
|
||||
package org.pkl.core.parser.antlr;
|
||||
}
|
||||
|
||||
@members {
|
||||
/**
|
||||
* Returns true if and only if the next token to be consumed is not preceded by a newline or semicolon.
|
||||
*/
|
||||
boolean noNewlineOrSemicolon() {
|
||||
for (int i = _input.index() - 1; i >= 0; i--) {
|
||||
Token token = _input.get(i);
|
||||
int channel = token.getChannel();
|
||||
if (channel == PklLexer.DEFAULT_TOKEN_CHANNEL) return true;
|
||||
if (channel == PklLexer.NewlineSemicolonChannel) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
options {
|
||||
tokenVocab = PklLexer;
|
||||
}
|
||||
|
||||
replInput
|
||||
: ((moduleDecl
|
||||
| importClause
|
||||
| clazz
|
||||
| typeAlias
|
||||
| classProperty
|
||||
| classMethod
|
||||
| expr))* EOF
|
||||
;
|
||||
|
||||
exprInput
|
||||
: expr EOF
|
||||
;
|
||||
|
||||
module
|
||||
: moduleDecl? (is+=importClause)* ((cs+=clazz | ts+=typeAlias | ps+=classProperty | ms+=classMethod))* EOF
|
||||
;
|
||||
|
||||
moduleDecl
|
||||
: t=DocComment? annotation* moduleHeader
|
||||
;
|
||||
|
||||
moduleHeader
|
||||
: modifier* 'module' qualifiedIdentifier moduleExtendsOrAmendsClause?
|
||||
| moduleExtendsOrAmendsClause
|
||||
;
|
||||
|
||||
moduleExtendsOrAmendsClause
|
||||
: t=('extends' | 'amends') stringConstant
|
||||
;
|
||||
|
||||
importClause
|
||||
: t=('import' | 'import*') stringConstant ('as' Identifier)?
|
||||
;
|
||||
|
||||
clazz
|
||||
: t=DocComment? annotation* classHeader classBody?
|
||||
;
|
||||
|
||||
classHeader
|
||||
: modifier* 'class' Identifier typeParameterList? ('extends' type)?
|
||||
;
|
||||
|
||||
modifier
|
||||
: t=('external' | 'abstract' | 'open' | 'local' | 'hidden' | 'fixed' | 'const')
|
||||
;
|
||||
|
||||
classBody
|
||||
: '{' ((ps+=classProperty | ms+=classMethod))* err='}'?
|
||||
;
|
||||
|
||||
typeAlias
|
||||
: t=DocComment? annotation* typeAliasHeader '=' type
|
||||
;
|
||||
|
||||
typeAliasHeader
|
||||
: modifier* 'typealias' Identifier typeParameterList?
|
||||
;
|
||||
|
||||
// allows `foo: Bar { ... }` s.t. AstBuilder can provide better error message
|
||||
classProperty
|
||||
: t=DocComment? annotation* modifier* Identifier (typeAnnotation | typeAnnotation? ('=' expr | objectBody+))
|
||||
;
|
||||
|
||||
classMethod
|
||||
: t=DocComment? annotation* methodHeader ('=' expr)?
|
||||
;
|
||||
|
||||
methodHeader
|
||||
: modifier* 'function' Identifier typeParameterList? parameterList typeAnnotation?
|
||||
;
|
||||
|
||||
parameterList
|
||||
: '(' (ts+=parameter (errs+=','? ts+=parameter)*)? err=')'?
|
||||
;
|
||||
|
||||
argumentList
|
||||
: {noNewlineOrSemicolon()}? '(' (es+=expr (errs+=','? es+=expr)*)? err=')'?
|
||||
;
|
||||
|
||||
annotation
|
||||
: '@' type objectBody?
|
||||
;
|
||||
|
||||
qualifiedIdentifier
|
||||
: ts+=Identifier ('.' ts+=Identifier)*
|
||||
;
|
||||
|
||||
typeAnnotation
|
||||
: ':' type
|
||||
;
|
||||
|
||||
typeParameterList
|
||||
: '<' ts+=typeParameter (errs+=','? ts+=typeParameter)* err='>'?
|
||||
;
|
||||
|
||||
typeParameter
|
||||
: t=('in' | 'out')? Identifier
|
||||
;
|
||||
|
||||
typeArgumentList
|
||||
: '<' ts+=type (errs+=','? ts+=type)* err='>'?
|
||||
;
|
||||
|
||||
type
|
||||
: 'unknown' # unknownType
|
||||
| 'nothing' # nothingType
|
||||
| 'module' # moduleType
|
||||
| stringConstant # stringLiteralType
|
||||
| qualifiedIdentifier typeArgumentList? # declaredType
|
||||
| '(' type err=')'? # parenthesizedType
|
||||
| type '?' # nullableType
|
||||
| type {noNewlineOrSemicolon()}? t='(' es+=expr (errs+=','? es+=expr)* err=')'? # constrainedType
|
||||
| '*' u=type # defaultUnionType
|
||||
| l=type '|' r=type # unionType
|
||||
| t='(' (ps+=type (errs+=','? ps+=type)*)? err=')'? '->' r=type # functionType
|
||||
;
|
||||
|
||||
typedIdentifier
|
||||
: Identifier typeAnnotation?
|
||||
;
|
||||
|
||||
parameter
|
||||
: '_'
|
||||
| typedIdentifier
|
||||
;
|
||||
|
||||
// Many languages (e.g., Python) give `**` higher precedence than unary minus.
|
||||
// The reason is that in Math, `-a^2` means `-(a^2)`.
|
||||
// To avoid confusion, JS rejects `-a**2` and requires explicit parens.
|
||||
// `-3.abs()` is a similar problem, handled differently by different languages.
|
||||
expr
|
||||
: 'this' # thisExpr
|
||||
| 'outer' # outerExpr
|
||||
| 'module' # moduleExpr
|
||||
| 'null' # nullLiteral
|
||||
| 'true' # trueLiteral
|
||||
| 'false' # falseLiteral
|
||||
| IntLiteral # intLiteral
|
||||
| FloatLiteral # floatLiteral
|
||||
| 'throw' '(' expr err=')'? # throwExpr
|
||||
| 'trace' '(' expr err=')'? # traceExpr
|
||||
| t=('import' | 'import*') '(' stringConstant err=')'? # importExpr
|
||||
| t=('read' | 'read?' | 'read*') '(' expr err=')'? # readExpr
|
||||
| Identifier argumentList? # unqualifiedAccessExpr
|
||||
| t=SLQuote singleLineStringPart* t2=SLEndQuote # singleLineStringLiteral
|
||||
| t=MLQuote multiLineStringPart* t2=MLEndQuote # multiLineStringLiteral
|
||||
| t='new' type? objectBody # newExpr
|
||||
| expr objectBody # amendExpr
|
||||
| 'super' '.' Identifier argumentList? # superAccessExpr
|
||||
| 'super' t='[' e=expr err=']'? # superSubscriptExpr
|
||||
| expr t=('.' | '?.') Identifier argumentList? # qualifiedAccessExpr
|
||||
| l=expr {noNewlineOrSemicolon()}? t='[' r=expr err=']'? # subscriptExpr
|
||||
| expr '!!' # nonNullExpr
|
||||
| '-' expr # unaryMinusExpr
|
||||
| '!' expr # logicalNotExpr
|
||||
| <assoc=right> l=expr t='**' r=expr # exponentiationExpr
|
||||
// for some reason, moving rhs of rules starting with `l=expr` into a
|
||||
// separate rule (to avoid repeated parsing of `expr`) messes up precedence
|
||||
| l=expr t=('*' | '/' | '~/' | '%') r=expr # multiplicativeExpr
|
||||
| l=expr (t='+' | {noNewlineOrSemicolon()}? t='-') r=expr # additiveExpr
|
||||
| l=expr t=('<' | '>' | '<=' | '>=') r=expr # comparisonExpr
|
||||
| l=expr t=('is' | 'as') r=type # typeTestExpr
|
||||
| l=expr t=('==' | '!=') r=expr # equalityExpr
|
||||
| l=expr t='&&' r=expr # logicalAndExpr
|
||||
| l=expr t='||' r=expr # logicalOrExpr
|
||||
| l=expr t='|>' r=expr # pipeExpr
|
||||
| <assoc=right> l=expr t='??' r=expr # nullCoalesceExpr
|
||||
| 'if' '(' c=expr err=')'? l=expr 'else' r=expr # ifExpr
|
||||
| 'let' '(' parameter '=' l=expr err=')'? r=expr # letExpr
|
||||
| parameterList '->' expr # functionLiteral
|
||||
| '(' expr err=')'? # parenthesizedExpr
|
||||
;
|
||||
|
||||
objectBody
|
||||
: '{' (ps+=parameter (errs+=','? ps+=parameter)* '->')? objectMember* err='}'?
|
||||
;
|
||||
|
||||
objectMember
|
||||
: modifier* Identifier (typeAnnotation? '=' expr | objectBody+) # objectProperty
|
||||
| methodHeader '=' expr # objectMethod
|
||||
| t='[[' k=expr err1=']'? err2=']'? ('=' v=expr | objectBody+) # memberPredicate
|
||||
| t='[' k=expr err1=']'? err2=']'? ('=' v=expr | objectBody+) # objectEntry
|
||||
| expr # objectElement
|
||||
| ('...' | '...?') expr # objectSpread
|
||||
| 'when' '(' e=expr err=')'? (b1=objectBody ('else' b2=objectBody)?) # whenGenerator
|
||||
| 'for' '(' t1=parameter (',' t2=parameter)? 'in' e=expr err=')'? objectBody # forGenerator
|
||||
;
|
||||
|
||||
stringConstant
|
||||
: t=SLQuote (ts+=SLCharacters | ts+=SLCharacterEscape | ts+=SLUnicodeEscape)* t2=SLEndQuote
|
||||
;
|
||||
|
||||
singleLineStringPart
|
||||
: SLInterpolation e=expr ')'
|
||||
| (ts+=SLCharacters | ts+=SLCharacterEscape | ts+=SLUnicodeEscape)+
|
||||
;
|
||||
|
||||
multiLineStringPart
|
||||
: MLInterpolation e=expr ')'
|
||||
| (ts+=MLCharacters | ts+=MLNewline | ts+=MLCharacterEscape | ts+=MLUnicodeEscape)+
|
||||
;
|
||||
|
||||
// intentionally unused
|
||||
//TODO: we get a "Mismatched Input" error unless we introduce this parser rule. Why?
|
||||
reservedKeyword
|
||||
: 'protected'
|
||||
| 'override'
|
||||
| 'record'
|
||||
| 'delete'
|
||||
| 'case'
|
||||
| 'switch'
|
||||
| 'vararg'
|
||||
;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class LexerTest {
|
||||
|
||||
@Test
|
||||
fun isRegularIdentifier() {
|
||||
assertThat(Lexer.isRegularIdentifier("pigeon")).isTrue
|
||||
|
||||
assertThat(Lexer.isRegularIdentifier("_pigeon")).isTrue
|
||||
assertThat(Lexer.isRegularIdentifier("f_red")).isTrue
|
||||
|
||||
assertThat(Lexer.isRegularIdentifier("\$pigeon")).isTrue
|
||||
assertThat(Lexer.isRegularIdentifier("f\$red")).isTrue
|
||||
|
||||
assertThat(Lexer.isRegularIdentifier("जावास्क्रिप्ट")).isTrue
|
||||
|
||||
assertThat(Lexer.isRegularIdentifier("this")).isFalse
|
||||
assertThat(Lexer.isRegularIdentifier("😀")).isFalse
|
||||
}
|
||||
|
||||
@Test
|
||||
fun maybeQuoteIdentifier() {
|
||||
assertThat(Lexer.maybeQuoteIdentifier("pigeon")).isEqualTo("pigeon")
|
||||
assertThat(Lexer.maybeQuoteIdentifier("_pigeon")).isEqualTo("_pigeon")
|
||||
assertThat(Lexer.maybeQuoteIdentifier("\$pigeon")).isEqualTo("\$pigeon")
|
||||
assertThat(Lexer.maybeQuoteIdentifier("जावास्क्रिप्ट")).isEqualTo("जावास्क्रिप्ट")
|
||||
|
||||
assertThat(Lexer.maybeQuoteIdentifier("this")).isEqualTo("`this`")
|
||||
assertThat(Lexer.maybeQuoteIdentifier("😀")).isEqualTo("`😀`")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `lexer keywords are sorted`() {
|
||||
assertThat(Lexer.KEYWORDS).isSortedAccordingTo { a, b -> a.compareTo(b.name) }
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser
|
||||
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.extension
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.pkl.commons.walk
|
||||
|
||||
class ParserComparisonTest : ParserComparisonTestInterface {
|
||||
|
||||
@Test
|
||||
fun testAsPrecedence() {
|
||||
compare("prop = 3 + bar as Int * 5")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStringInterpolation() {
|
||||
compare(
|
||||
"""
|
||||
prop = "\(bar)"
|
||||
prop2 = "foo \(bar)"
|
||||
prop3 = "\(bar) foo"
|
||||
prop4 = "foo \(bar + baz) foo"
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
compare(
|
||||
"""
|
||||
prop = ""${'"'}
|
||||
\(bar)
|
||||
""${'"'}
|
||||
prop2 = ""${'"'}
|
||||
foo \(bar)
|
||||
""${'"'}
|
||||
prop3 = ""${'"'}
|
||||
\(bar) foo
|
||||
""${'"'}
|
||||
prop4 = ""${'"'}
|
||||
foo \(bar + baz) foo
|
||||
""${'"'}
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSnippets(): List<Path> {
|
||||
return Path("src/test/files/LanguageSnippetTests/input")
|
||||
.walk()
|
||||
.filter { path ->
|
||||
val pathStr = path.toString().replace("\\", "/")
|
||||
path.extension == "pkl" &&
|
||||
!exceptions.any { pathStr.endsWith(it) } &&
|
||||
!regexExceptions.any { it.matches(pathStr) }
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
|
||||
companion object {
|
||||
// tests that are not syntactically valid Pkl
|
||||
private val exceptions =
|
||||
setOf(
|
||||
"stringError1.pkl",
|
||||
"annotationIsNotExpression2.pkl",
|
||||
"amendsRequiresParens.pkl",
|
||||
"errors/parser18.pkl",
|
||||
"errors/nested1.pkl",
|
||||
"errors/invalidCharacterEscape.pkl",
|
||||
"errors/invalidUnicodeEscape.pkl",
|
||||
"errors/unterminatedUnicodeEscape.pkl",
|
||||
"errors/keywordNotAllowedHere1.pkl",
|
||||
"errors/keywordNotAllowedHere2.pkl",
|
||||
"errors/keywordNotAllowedHere3.pkl",
|
||||
"errors/keywordNotAllowedHere4.pkl",
|
||||
"errors/moduleWithHighMinPklVersionAndParseErrors.pkl",
|
||||
"errors/underscore.pkl",
|
||||
"notAUnionDefault.pkl",
|
||||
"multipleDefaults.pkl",
|
||||
)
|
||||
|
||||
private val regexExceptions =
|
||||
setOf(
|
||||
Regex(".*/errors/delimiters/.*"),
|
||||
Regex(".*/errors/parser\\d+\\.pkl"),
|
||||
Regex(".*/parser/.*"),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser
|
||||
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.pathString
|
||||
import kotlin.io.path.readText
|
||||
import org.antlr.v4.runtime.ANTLRInputStream
|
||||
import org.antlr.v4.runtime.CommonTokenStream
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.SoftAssertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.parallel.Execution
|
||||
import org.junit.jupiter.api.parallel.ExecutionMode
|
||||
import org.pkl.core.parser.antlr.PklLexer
|
||||
import org.pkl.core.parser.antlr.PklParser
|
||||
|
||||
@Execution(ExecutionMode.CONCURRENT)
|
||||
interface ParserComparisonTestInterface {
|
||||
@Test
|
||||
@Execution(ExecutionMode.CONCURRENT)
|
||||
fun compareSnippetTests() {
|
||||
SoftAssertions.assertSoftly { softly ->
|
||||
getSnippets()
|
||||
.parallelStream()
|
||||
.map { Pair(it.pathString, it.readText()) }
|
||||
.forEach { (path, snippet) ->
|
||||
try {
|
||||
compare(snippet, path, softly)
|
||||
} catch (e: ParserError) {
|
||||
softly.fail("path: $path. Message: ${e.message}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Execution(ExecutionMode.CONCURRENT)
|
||||
fun compareSnippetTestsSpans() {
|
||||
SoftAssertions.assertSoftly { softly ->
|
||||
getSnippets()
|
||||
.parallelStream()
|
||||
.map { Pair(it.pathString, it.readText()) }
|
||||
.forEach { (path, snippet) ->
|
||||
try {
|
||||
compareSpans(snippet, path, softly)
|
||||
} catch (e: ParserError) {
|
||||
softly.fail("path: $path. Message: ${e.message}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getSnippets(): List<Path>
|
||||
|
||||
fun compare(code: String, path: String? = null, softly: SoftAssertions? = null) {
|
||||
val (sexp, antlrExp) = renderBoth(code)
|
||||
when {
|
||||
(path != null && softly != null) ->
|
||||
softly.assertThat(sexp).`as`("path: $path").isEqualTo(antlrExp)
|
||||
else -> assertThat(sexp).isEqualTo(antlrExp)
|
||||
}
|
||||
}
|
||||
|
||||
fun compareSpans(code: String, path: String, softly: SoftAssertions) {
|
||||
// Our ANTLR grammar always start doc comment spans in the beginning of the line,
|
||||
// even though they may have leading spaces.
|
||||
// This is a regression, but it's a bugfix
|
||||
if (path.endsWith("annotation1.pkl")) return
|
||||
|
||||
val parser = Parser()
|
||||
val mod = parser.parseModule(code)
|
||||
val lexer = PklLexer(ANTLRInputStream(code))
|
||||
val antlr = PklParser(CommonTokenStream(lexer))
|
||||
val antlrMod = antlr.module()
|
||||
|
||||
val comparer = SpanComparison(path, softly)
|
||||
comparer.compare(mod, antlrMod)
|
||||
}
|
||||
|
||||
fun renderBoth(code: String): Pair<String, String> = Pair(renderCode(code), renderANTLRCode(code))
|
||||
|
||||
companion object {
|
||||
private fun renderCode(code: String): String {
|
||||
val parser = Parser()
|
||||
val mod = parser.parseModule(code)
|
||||
val renderer = SexpRenderer()
|
||||
return renderer.render(mod)
|
||||
}
|
||||
|
||||
private fun renderANTLRCode(code: String): String {
|
||||
val lexer = PklLexer(ANTLRInputStream(code))
|
||||
val parser = PklParser(CommonTokenStream(lexer))
|
||||
val mod = parser.module()
|
||||
val renderer = ANTLRSexpRenderer()
|
||||
return renderer.render(mod)
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,464 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext
|
||||
import org.antlr.v4.runtime.tree.TerminalNode
|
||||
import org.assertj.core.api.SoftAssertions
|
||||
import org.pkl.core.parser.antlr.PklParser.*
|
||||
import org.pkl.core.parser.syntax.*
|
||||
import org.pkl.core.parser.syntax.Annotation
|
||||
import org.pkl.core.parser.syntax.Expr.AmendsExpr
|
||||
import org.pkl.core.parser.syntax.Expr.BinaryOperatorExpr
|
||||
import org.pkl.core.parser.syntax.Expr.FunctionLiteralExpr
|
||||
import org.pkl.core.parser.syntax.Expr.IfExpr
|
||||
import org.pkl.core.parser.syntax.Expr.ImportExpr
|
||||
import org.pkl.core.parser.syntax.Expr.LetExpr
|
||||
import org.pkl.core.parser.syntax.Expr.LogicalNotExpr
|
||||
import org.pkl.core.parser.syntax.Expr.MultiLineStringLiteralExpr
|
||||
import org.pkl.core.parser.syntax.Expr.NewExpr
|
||||
import org.pkl.core.parser.syntax.Expr.NonNullExpr
|
||||
import org.pkl.core.parser.syntax.Expr.ParenthesizedExpr
|
||||
import org.pkl.core.parser.syntax.Expr.QualifiedAccessExpr
|
||||
import org.pkl.core.parser.syntax.Expr.ReadExpr
|
||||
import org.pkl.core.parser.syntax.Expr.SingleLineStringLiteralExpr
|
||||
import org.pkl.core.parser.syntax.Expr.SubscriptExpr
|
||||
import org.pkl.core.parser.syntax.Expr.SuperAccessExpr
|
||||
import org.pkl.core.parser.syntax.Expr.SuperSubscriptExpr
|
||||
import org.pkl.core.parser.syntax.Expr.ThrowExpr
|
||||
import org.pkl.core.parser.syntax.Expr.TraceExpr
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCastExpr
|
||||
import org.pkl.core.parser.syntax.Expr.TypeCheckExpr
|
||||
import org.pkl.core.parser.syntax.Expr.UnaryMinusExpr
|
||||
import org.pkl.core.parser.syntax.Expr.UnqualifiedAccessExpr
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ForGenerator
|
||||
import org.pkl.core.parser.syntax.ObjectMember.MemberPredicate
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectElement
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectEntry
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectMethod
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectProperty
|
||||
import org.pkl.core.parser.syntax.ObjectMember.ObjectSpread
|
||||
import org.pkl.core.parser.syntax.ObjectMember.WhenGenerator
|
||||
import org.pkl.core.parser.syntax.Parameter.TypedIdentifier
|
||||
import org.pkl.core.parser.syntax.Type.ConstrainedType
|
||||
import org.pkl.core.parser.syntax.Type.DeclaredType
|
||||
import org.pkl.core.parser.syntax.Type.FunctionType
|
||||
import org.pkl.core.parser.syntax.Type.NullableType
|
||||
import org.pkl.core.parser.syntax.Type.ParenthesizedType
|
||||
import org.pkl.core.parser.syntax.Type.StringConstantType
|
||||
import org.pkl.core.parser.syntax.Type.UnionType
|
||||
|
||||
class SpanComparison(val path: String, private val softly: SoftAssertions) {
|
||||
|
||||
fun compare(module: Module, modCtx: ModuleContext) {
|
||||
compareSpan(module, modCtx)
|
||||
if (module.decl !== null) {
|
||||
compareModuleDecl(module.decl!!, modCtx.moduleDecl())
|
||||
}
|
||||
module.imports.zip(modCtx.importClause()).forEach { (i1, i2) -> compareImport(i1, i2) }
|
||||
module.classes.zip(modCtx.clazz()).forEach { (class1, class2) -> compareClass(class1, class2) }
|
||||
module.typeAliases.zip(modCtx.typeAlias()).forEach { (ta1, ta2) -> compareTypealias(ta1, ta2) }
|
||||
module.properties.zip(modCtx.classProperty()).forEach { (prop1, prop2) ->
|
||||
compareProperty(prop1, prop2)
|
||||
}
|
||||
module.methods.zip(modCtx.classMethod()).forEach { (m1, m2) -> compareMethod(m1, m2) }
|
||||
}
|
||||
|
||||
private fun compareModuleDecl(node: ModuleDecl, ctx: ModuleDeclContext) {
|
||||
compareSpan(node, ctx)
|
||||
compareDocComment(node.docComment, ctx.DocComment())
|
||||
node.annotations.zip(ctx.annotation()).forEach { (a1, a2) -> compareAnnotation(a1, a2) }
|
||||
val header = ctx.moduleHeader()
|
||||
node.modifiers.zip(header.modifier()).forEach { (m1, m2) -> compareSpan(m1, m2) }
|
||||
compareQualifiedIdentifier(node.name, header.qualifiedIdentifier())
|
||||
compareExtendsOrAmendsClause(node.extendsOrAmendsDecl, header.moduleExtendsOrAmendsClause())
|
||||
}
|
||||
|
||||
private fun compareImport(node: ImportClause, ctx: ImportClauseContext) {
|
||||
compareSpan(node, ctx)
|
||||
compareSpan(node.importStr, ctx.stringConstant())
|
||||
compareSpan(node.alias, ctx.Identifier())
|
||||
}
|
||||
|
||||
private fun compareClass(node: Class, ctx: ClazzContext) {
|
||||
compareSpan(node, ctx)
|
||||
compareDocComment(node.docComment, ctx.DocComment())
|
||||
node.annotations.zip(ctx.annotation()).forEach { (a1, a2) -> compareAnnotation(a1, a2) }
|
||||
val header = ctx.classHeader()
|
||||
node.modifiers.zip(header.modifier()).forEach { (m1, m2) -> compareSpan(m1, m2) }
|
||||
compareSpan(node.classKeyword, header.CLASS())
|
||||
compareSpan(node.name, header.Identifier())
|
||||
compareTypeParameterList(node.typeParameterList, header.typeParameterList())
|
||||
compareType(node.superClass, header.type())
|
||||
compareClassBody(node.body, ctx.classBody())
|
||||
compareSpan(node.headerSpan, header)
|
||||
}
|
||||
|
||||
private fun compareTypealias(node: TypeAlias, ctx: TypeAliasContext) {
|
||||
compareSpan(node, ctx)
|
||||
compareDocComment(node.docComment, ctx.DocComment())
|
||||
node.annotations.zip(ctx.annotation()).forEach { (a1, a2) -> compareAnnotation(a1, a2) }
|
||||
val header = ctx.typeAliasHeader()
|
||||
node.modifiers.zip(header.modifier()).forEach { (m1, m2) -> compareSpan(m1, m2) }
|
||||
compareSpan(node.typealiasKeyword, header.TYPE_ALIAS())
|
||||
compareSpan(node.name, header.Identifier())
|
||||
compareTypeParameterList(node.typeParameterList, header.typeParameterList())
|
||||
compareType(node.type, ctx.type())
|
||||
compareSpan(node.headerSpan, header)
|
||||
}
|
||||
|
||||
private fun compareProperty(node: ClassProperty, ctx: ClassPropertyContext) {
|
||||
if (node.docComment === null) {
|
||||
compareSpan(node, ctx)
|
||||
}
|
||||
compareDocComment(node.docComment, ctx.DocComment())
|
||||
node.annotations.zip(ctx.annotation()).forEach { (a1, a2) -> compareAnnotation(a1, a2) }
|
||||
node.modifiers.zip(ctx.modifier()).forEach { (m1, m2) -> compareSpan(m1, m2) }
|
||||
compareSpan(node.name, ctx.Identifier())
|
||||
compareTypeAnnotation(node.typeAnnotation, ctx.typeAnnotation())
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
node.bodyList.zip(ctx.objectBody()).forEach { (b1, b2) -> compareObjectBody(b1, b2) }
|
||||
}
|
||||
|
||||
private fun compareMethod(node: ClassMethod, ctx: ClassMethodContext) {
|
||||
compareSpan(node, ctx)
|
||||
compareDocComment(node.docComment, ctx.DocComment())
|
||||
node.annotations.zip(ctx.annotation()).forEach { (a1, a2) -> compareAnnotation(a1, a2) }
|
||||
val header = ctx.methodHeader()
|
||||
compareSpan(node.headerSpan, header)
|
||||
node.modifiers.zip(header.modifier()).forEach { (m1, m2) -> compareSpan(m1, m2) }
|
||||
compareSpan(node.name, header.Identifier())
|
||||
compareTypeParameterList(node.typeParameterList, header.typeParameterList())
|
||||
compareParameterList(node.parameterList, header.parameterList())
|
||||
compareTypeAnnotation(node.typeAnnotation, header.typeAnnotation())
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
}
|
||||
|
||||
private fun compareAnnotation(node: Annotation, ctx: AnnotationContext) {
|
||||
compareSpan(node, ctx)
|
||||
compareType(node.type, ctx.type())
|
||||
compareObjectBody(node.body, ctx.objectBody())
|
||||
}
|
||||
|
||||
private fun compareParameterList(node: ParameterList?, ctx: ParameterListContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
node.parameters.zip(ctx.parameter()).forEach { (p1, p2) -> compareParameter(p1, p2) }
|
||||
}
|
||||
|
||||
private fun compareParameter(node: Parameter?, ctx: ParameterContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
if (node is TypedIdentifier) {
|
||||
val tident = ctx.typedIdentifier()
|
||||
compareSpan(node.identifier, tident.Identifier())
|
||||
compareTypeAnnotation(node.typeAnnotation, tident.typeAnnotation())
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareTypeParameterList(node: TypeParameterList?, ctx: TypeParameterListContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
node.parameters.zip(ctx.typeParameter()).forEach { (p1, p2) -> compareTypeParameter(p1, p2) }
|
||||
}
|
||||
|
||||
private fun compareTypeParameter(node: TypeParameter, ctx: TypeParameterContext) {
|
||||
compareSpan(node, ctx)
|
||||
compareSpan(node.identifier, ctx.Identifier())
|
||||
}
|
||||
|
||||
private fun compareClassBody(node: ClassBody?, ctx: ClassBodyContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
node.properties.zip(ctx.classProperty()).forEach { (p1, p2) -> compareProperty(p1, p2) }
|
||||
node.methods.zip(ctx.classMethod()).forEach { (m1, m2) -> compareMethod(m1, m2) }
|
||||
}
|
||||
|
||||
private fun compareTypeAnnotation(node: TypeAnnotation?, ctx: TypeAnnotationContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
compareSpan(node.type, ctx.type())
|
||||
}
|
||||
|
||||
private fun compareObjectBody(node: ObjectBody?, ctx: ObjectBodyContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
node.parameters.zip(ctx.parameter()).forEach { (p1, p2) -> compareParameter(p1, p2) }
|
||||
node.members.zip(ctx.objectMember()).forEach { (m1, m2) -> compareObjectMember(m1, m2) }
|
||||
}
|
||||
|
||||
private fun compareType(node: Type?, actx: TypeContext?) {
|
||||
if (node === null) return
|
||||
val ctx = if (actx is DefaultUnionTypeContext) actx.type() else actx
|
||||
compareSpan(node, ctx!!)
|
||||
when (node) {
|
||||
is StringConstantType ->
|
||||
compareSpan(node.str, (ctx as StringLiteralTypeContext).stringConstant())
|
||||
is DeclaredType -> {
|
||||
val decl = ctx as DeclaredTypeContext
|
||||
compareQualifiedIdentifier(node.name, decl.qualifiedIdentifier())
|
||||
compareTypeArgumentList(node.args, ctx.typeArgumentList())
|
||||
}
|
||||
is ParenthesizedType -> compareType(node.type, (ctx as ParenthesizedTypeContext).type())
|
||||
is NullableType -> compareType(node.type, (ctx as NullableTypeContext).type())
|
||||
is ConstrainedType -> {
|
||||
val cons = ctx as ConstrainedTypeContext
|
||||
compareType(node.type, cons.type())
|
||||
node.exprs.zip(cons.expr()).forEach { (e1, e2) -> compareExpr(e1, e2) }
|
||||
}
|
||||
is UnionType -> {
|
||||
val flattened = ANTLRSexpRenderer.flattenUnion(ctx as UnionTypeContext)
|
||||
node.types.zip(flattened).forEach { (t1, t2) -> compareType(t1, t2) }
|
||||
}
|
||||
is FunctionType -> {
|
||||
val func = ctx as FunctionTypeContext
|
||||
node.args.zip(func.ps).forEach { (t1, t2) -> compareType(t1, t2) }
|
||||
compareType(node.ret, func.r)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareObjectMember(node: ObjectMember, ctx: ObjectMemberContext) {
|
||||
compareSpan(node, ctx)
|
||||
when (node) {
|
||||
is ObjectElement -> compareExpr(node.expr, (ctx as ObjectElementContext).expr())
|
||||
is ObjectProperty -> {
|
||||
ctx as ObjectPropertyContext
|
||||
node.modifiers.zip(ctx.modifier()).forEach { (m1, m2) -> compareSpan(m1, m2) }
|
||||
compareSpan(node.identifier, ctx.Identifier())
|
||||
compareTypeAnnotation(node.typeAnnotation, ctx.typeAnnotation())
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
if (node.bodyList.isNotEmpty()) {
|
||||
node.bodyList.zip(ctx.objectBody()).forEach { (b1, b2) -> compareObjectBody(b1, b2) }
|
||||
}
|
||||
}
|
||||
is ObjectMethod -> {
|
||||
ctx as ObjectMethodContext
|
||||
val header = ctx.methodHeader()
|
||||
node.modifiers.zip(header.modifier()).forEach { (m1, m2) -> compareSpan(m1, m2) }
|
||||
compareSpan(node.functionKeyword, header.FUNCTION())
|
||||
compareSpan(node.identifier, header.Identifier())
|
||||
compareTypeParameterList(node.typeParameterList, header.typeParameterList())
|
||||
compareParameterList(node.paramList, header.parameterList())
|
||||
compareTypeAnnotation(node.typeAnnotation, header.typeAnnotation())
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
compareSpan(node.headerSpan(), header)
|
||||
}
|
||||
is MemberPredicate -> {
|
||||
ctx as MemberPredicateContext
|
||||
compareExpr(node.pred, ctx.k)
|
||||
compareExpr(node.expr, ctx.v)
|
||||
if (node.bodyList.isNotEmpty()) {
|
||||
node.bodyList.zip(ctx.objectBody()).forEach { (b1, b2) -> compareObjectBody(b1, b2) }
|
||||
}
|
||||
}
|
||||
is ObjectEntry -> {
|
||||
ctx as ObjectEntryContext
|
||||
compareExpr(node.key, ctx.k)
|
||||
compareExpr(node.value, ctx.v)
|
||||
if (node.bodyList.isNotEmpty()) {
|
||||
node.bodyList.zip(ctx.objectBody()).forEach { (b1, b2) -> compareObjectBody(b1, b2) }
|
||||
}
|
||||
}
|
||||
is ObjectSpread -> compareExpr(node.expr, (ctx as ObjectSpreadContext).expr())
|
||||
is WhenGenerator -> {
|
||||
ctx as WhenGeneratorContext
|
||||
compareExpr(node.predicate, ctx.expr())
|
||||
compareObjectBody(node.thenClause, ctx.b1)
|
||||
compareObjectBody(node.elseClause, ctx.b2)
|
||||
}
|
||||
is ForGenerator -> {
|
||||
ctx as ForGeneratorContext
|
||||
compareParameter(node.p1, ctx.t1)
|
||||
compareParameter(node.p2, ctx.t2)
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
compareObjectBody(node.body, ctx.objectBody())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareExpr(node: Expr?, ctx: ExprContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
when (node) {
|
||||
is SingleLineStringLiteralExpr -> {
|
||||
node.parts.zip((ctx as SingleLineStringLiteralContext).singleLineStringPart()).forEach {
|
||||
(s1, s2) ->
|
||||
compareSpan(s1, s2)
|
||||
}
|
||||
}
|
||||
is MultiLineStringLiteralExpr -> {
|
||||
// only compare interpolated expressions
|
||||
val exprs = node.parts.filterIsInstance<StringPart.StringInterpolation>()
|
||||
val antlrExprs =
|
||||
(ctx as MultiLineStringLiteralContext).multiLineStringPart().mapNotNull { it.expr() }
|
||||
exprs.zip(antlrExprs).forEach { (s1, s2) -> compareExpr(s1.expr, s2) }
|
||||
}
|
||||
is ThrowExpr -> compareExpr(node.expr, (ctx as ThrowExprContext).expr())
|
||||
is TraceExpr -> compareExpr(node.expr, (ctx as TraceExprContext).expr())
|
||||
is ImportExpr -> compareSpan(node.importStr, (ctx as ImportExprContext).stringConstant())
|
||||
is ReadExpr -> compareExpr(node.expr, (ctx as ReadExprContext).expr())
|
||||
is UnqualifiedAccessExpr -> {
|
||||
ctx as UnqualifiedAccessExprContext
|
||||
compareSpan(node.identifier, ctx.Identifier())
|
||||
compareArgumentList(node.argumentList, ctx.argumentList())
|
||||
}
|
||||
is QualifiedAccessExpr -> {
|
||||
ctx as QualifiedAccessExprContext
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
compareSpan(node.identifier, ctx.Identifier())
|
||||
compareArgumentList(node.argumentList, ctx.argumentList())
|
||||
}
|
||||
is SuperAccessExpr -> {
|
||||
ctx as SuperAccessExprContext
|
||||
compareSpan(node.identifier, ctx.Identifier())
|
||||
compareArgumentList(node.argumentList, ctx.argumentList())
|
||||
}
|
||||
is SuperSubscriptExpr -> compareExpr(node.arg, (ctx as SuperSubscriptExprContext).expr())
|
||||
is SubscriptExpr -> {
|
||||
ctx as SubscriptExprContext
|
||||
compareExpr(node.expr, ctx.l)
|
||||
compareExpr(node.arg, ctx.r)
|
||||
}
|
||||
is IfExpr -> {
|
||||
ctx as IfExprContext
|
||||
compareExpr(node.cond, ctx.c)
|
||||
compareExpr(node.then, ctx.l)
|
||||
compareExpr(node.els, ctx.r)
|
||||
}
|
||||
is LetExpr -> {
|
||||
ctx as LetExprContext
|
||||
compareParameter(node.parameter, ctx.parameter())
|
||||
compareExpr(node.bindingExpr, ctx.l)
|
||||
compareExpr(node.expr, ctx.r)
|
||||
}
|
||||
is FunctionLiteralExpr -> {
|
||||
ctx as FunctionLiteralContext
|
||||
compareParameterList(node.parameterList, ctx.parameterList())
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
}
|
||||
is ParenthesizedExpr -> compareExpr(node.expr, (ctx as ParenthesizedExprContext).expr())
|
||||
is NewExpr -> {
|
||||
ctx as NewExprContext
|
||||
compareType(node.type, ctx.type())
|
||||
compareObjectBody(node.body, ctx.objectBody())
|
||||
}
|
||||
is AmendsExpr -> {
|
||||
ctx as AmendExprContext
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
compareObjectBody(node.body, ctx.objectBody())
|
||||
}
|
||||
is NonNullExpr -> compareExpr(node.expr, (ctx as NonNullExprContext).expr())
|
||||
is UnaryMinusExpr -> compareExpr(node.expr, (ctx as UnaryMinusExprContext).expr())
|
||||
is LogicalNotExpr -> compareExpr(node.expr, (ctx as LogicalNotExprContext).expr())
|
||||
is BinaryOperatorExpr -> {
|
||||
val (l, r) =
|
||||
when (ctx) {
|
||||
is ExponentiationExprContext -> ctx.l to ctx.r
|
||||
is MultiplicativeExprContext -> ctx.l to ctx.r
|
||||
is AdditiveExprContext -> ctx.l to ctx.r
|
||||
is ComparisonExprContext -> ctx.l to ctx.r
|
||||
is EqualityExprContext -> ctx.l to ctx.r
|
||||
is LogicalAndExprContext -> ctx.l to ctx.r
|
||||
is LogicalOrExprContext -> ctx.l to ctx.r
|
||||
is PipeExprContext -> ctx.l to ctx.r
|
||||
is NullCoalesceExprContext -> ctx.l to ctx.r
|
||||
else -> throw RuntimeException("unreacheable code")
|
||||
}
|
||||
compareExpr(node.left, l)
|
||||
compareExpr(node.right, r)
|
||||
}
|
||||
is TypeCheckExpr -> {
|
||||
ctx as TypeTestExprContext
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
compareType(node.type, ctx.type())
|
||||
}
|
||||
is TypeCastExpr -> {
|
||||
ctx as TypeTestExprContext
|
||||
compareExpr(node.expr, ctx.expr())
|
||||
compareType(node.type, ctx.type())
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareArgumentList(node: ArgumentList?, ctx: ArgumentListContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
node.arguments.zip(ctx.expr()).forEach { (e1, e2) -> compareExpr(e1, e2) }
|
||||
}
|
||||
|
||||
private fun compareTypeArgumentList(node: TypeArgumentList?, ctx: TypeArgumentListContext?) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
node.types.zip(ctx.type()).forEach { (t1, t2) -> compareType(t1, t2) }
|
||||
}
|
||||
|
||||
private fun compareQualifiedIdentifier(
|
||||
node: QualifiedIdentifier?,
|
||||
ctx: QualifiedIdentifierContext?,
|
||||
) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
node.identifiers.zip(ctx.Identifier()).forEach { (id1, id2) -> compareSpan(id1, id2) }
|
||||
}
|
||||
|
||||
private fun compareExtendsOrAmendsClause(
|
||||
node: ExtendsOrAmendsClause?,
|
||||
ctx: ModuleExtendsOrAmendsClauseContext?,
|
||||
) {
|
||||
if (node === null) return
|
||||
compareSpan(node, ctx!!)
|
||||
compareSpan(node.url, ctx.stringConstant())
|
||||
}
|
||||
|
||||
private fun compareSpan(node: Node?, ctx: ParserRuleContext) {
|
||||
if (node != null) {
|
||||
compareSpan(node, ctx.start.startIndex, ctx.stop.stopIndex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareSpan(node: Node?, ctx: TerminalNode?) {
|
||||
if (node != null) {
|
||||
compareSpan(node, ctx!!.symbol.startIndex, ctx.symbol.stopIndex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareSpan(node: Node, charIndex: Int, tokenStop: Int) {
|
||||
compareSpan(node.span(), charIndex, tokenStop)
|
||||
}
|
||||
|
||||
private fun compareSpan(span: Span, ctx: ParserRuleContext) {
|
||||
compareSpan(span, ctx.start.startIndex, ctx.stop.stopIndex)
|
||||
}
|
||||
|
||||
private fun compareSpan(span: Span, charIndex: Int, tokenStop: Int) {
|
||||
val length = tokenStop - charIndex + 1
|
||||
softly.assertThat(span.charIndex).`as`("$span, index for path: $path").isEqualTo(charIndex)
|
||||
softly.assertThat(span.length).`as`("$span, length for path: $path").isEqualTo(length)
|
||||
}
|
||||
|
||||
private fun compareDocComment(node: Node?, ctx: TerminalNode?) {
|
||||
if (node == null) return
|
||||
val charIndex = ctx!!.symbol.startIndex
|
||||
// for some reason antlr's doc coments are off by one
|
||||
val length = ctx.symbol.stopIndex - charIndex
|
||||
val span = node.span()
|
||||
softly.assertThat(span.charIndex).`as`("$span, index for path: $path").isEqualTo(charIndex)
|
||||
softly.assertThat(span.length).`as`("$span, length for path: $path").isEqualTo(length)
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.parser
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class SpanTest {
|
||||
|
||||
@Test
|
||||
fun `endWith test`() {
|
||||
var span1 = Span(10, 20)
|
||||
var span2 = Span(20, 20)
|
||||
assertThat(span1.endWith(span2)).isEqualTo(Span(10, 30))
|
||||
|
||||
span1 = Span(10, 20)
|
||||
span2 = Span(0, 40)
|
||||
assertThat(span1.endWith(span2)).isEqualTo(Span(10, 30))
|
||||
|
||||
span1 = Span(10, 30)
|
||||
span2 = Span(20, 20)
|
||||
assertThat(span1.endWith(span2)).isEqualTo(Span(10, 30))
|
||||
|
||||
span1 = Span(10, 30)
|
||||
span2 = Span(20, 5)
|
||||
assertThat(span1.endWith(span2)).isEqualTo(Span(10, 15))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user