Improve Parser implementation (#1508)

- Make leaf AST classes final
- Make protected Lexer fields private and add getter
- Split Parser into Parser and ParserImpl
- Using a fresh ParserImpl instance per parse simplifies reasoning
(important) and makes the Parser API thread-safe (nice to have)
- Split GenericParser into GenericParser and GenericParserImpl
  - Same motivation as for Parser

Some of these changes will facilitate the move to JSpecify, which has
proven challenging for this package.
This commit is contained in:
odenix
2026-04-08 08:13:39 -07:00
committed by GitHub
parent e793f4bd04
commit 24e69fd1e2
20 changed files with 3486 additions and 3429 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@ package org.pkl.parser;
import org.pkl.parser.syntax.generic.FullSpan; import org.pkl.parser.syntax.generic.FullSpan;
public class GenericParserError extends RuntimeException { public final class GenericParserError extends RuntimeException {
private final FullSpan span; private final FullSpan span;
public GenericParserError(String msg, FullSpan span) { public GenericParserError(String msg, FullSpan span) {

File diff suppressed because it is too large Load Diff

View File

@@ -20,12 +20,12 @@ import java.util.Deque;
import org.pkl.parser.syntax.generic.FullSpan; import org.pkl.parser.syntax.generic.FullSpan;
import org.pkl.parser.util.ErrorMessages; import org.pkl.parser.util.ErrorMessages;
public class Lexer { public final class Lexer {
private final char[] source; private final char[] source;
private final int size; private final int size;
protected int cursor = 0; private int cursor = 0;
protected int sCursor = 0; private int sCursor = 0;
private int line = 1; private int line = 1;
private int sLine = 1; private int sLine = 1;
private int col = 1; private int col = 1;
@@ -36,7 +36,7 @@ public class Lexer {
private boolean stringEnded = false; private boolean stringEnded = false;
private boolean isEscape = false; private boolean isEscape = false;
// how many newlines exist between two subsequent tokens // how many newlines exist between two subsequent tokens
protected int newLinesBetween = 0; private int newLinesBetween = 0;
private static final int EOF = -1; private static final int EOF = -1;
@@ -73,6 +73,10 @@ public class Lexer {
return cursor; return cursor;
} }
public int getNewLinesBetween() {
return newLinesBetween;
}
public char[] getSource() { public char[] getSource() {
return source; return source;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ package org.pkl.parser;
import org.pkl.parser.syntax.Module; import org.pkl.parser.syntax.Module;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class ParserError extends RuntimeException { public final class ParserError extends RuntimeException {
private final Span span; private final Span span;
private @Nullable Module partialParseResult; private @Nullable Module partialParseResult;

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class Annotation extends AbstractNode { public final class Annotation extends AbstractNode {
public Annotation(List<Node> nodes, Span span) { public Annotation(List<Node> nodes, Span span) {
super(span, nodes); super(span, nodes);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class ArgumentList extends AbstractNode { public final class ArgumentList extends AbstractNode {
public ArgumentList(List<Expr> arguments, Span span) { public ArgumentList(List<Expr> arguments, Span span) {
super(span, arguments); super(span, arguments);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class ClassBody extends AbstractNode { public final class ClassBody extends AbstractNode {
public ClassBody(List<Node> nodes, Span span) { public ClassBody(List<Node> nodes, Span span) {
super(span, nodes); super(span, nodes);

View File

@@ -20,7 +20,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class ClassMethod extends AbstractNode { public final class ClassMethod extends AbstractNode {
private final int modifiersOffset; private final int modifiersOffset;
private final int nameOffset; private final int nameOffset;
private final Span headerSpan; private final Span headerSpan;

View File

@@ -21,7 +21,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class ExtendsOrAmendsClause extends AbstractNode { public final class ExtendsOrAmendsClause extends AbstractNode {
private final Type type; private final Type type;
public ExtendsOrAmendsClause(StringConstant url, Type type, Span span) { public ExtendsOrAmendsClause(StringConstant url, Type type, Span span) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ package org.pkl.parser.syntax;
import org.pkl.parser.ParserVisitor; import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
public class Keyword extends AbstractNode { public final class Keyword extends AbstractNode {
public Keyword(Span span) { public Keyword(Span span) {
super(span, null); super(span, null);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class ParameterList extends AbstractNode { public final class ParameterList extends AbstractNode {
public ParameterList(List<Parameter> parameters, Span span) { public ParameterList(List<Parameter> parameters, Span span) {
super(span, parameters); super(span, parameters);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class ReplInput extends AbstractNode { public final class ReplInput extends AbstractNode {
public ReplInput(List<Node> nodes, Span span) { public ReplInput(List<Node> nodes, Span span) {
super(span, nodes); super(span, nodes);
} }

View File

@@ -20,7 +20,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class StringConstant extends AbstractNode { public final class StringConstant extends AbstractNode {
private final String string; private final String string;
public StringConstant(String string, Span span) { public StringConstant(String string, Span span) {

View File

@@ -20,7 +20,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class TypeAnnotation extends AbstractNode { public final class TypeAnnotation extends AbstractNode {
public TypeAnnotation(Type type, Span span) { public TypeAnnotation(Type type, Span span) {
super(span, List.of(type)); super(span, List.of(type));
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ import java.util.List;
import org.pkl.parser.ParserVisitor; import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
public class TypeArgumentList extends AbstractNode { public final class TypeArgumentList extends AbstractNode {
public TypeArgumentList(List<Type> children, Span span) { public TypeArgumentList(List<Type> children, Span span) {
super(span, children); super(span, children);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import org.pkl.parser.ParserVisitor;
import org.pkl.parser.Span; import org.pkl.parser.Span;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class TypeParameterList extends AbstractNode { public final class TypeParameterList extends AbstractNode {
public TypeParameterList(List<TypeParameter> parameters, Span span) { public TypeParameterList(List<TypeParameter> parameters, Span span) {
super(span, parameters); super(span, parameters);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import org.pkl.parser.util.Nullable; import org.pkl.parser.util.Nullable;
public class Node { public final class Node {
public final List<Node> children; public final List<Node> children;
public final FullSpan span; public final FullSpan span;
public final NodeType type; public final NodeType type;