mirror of
https://github.com/apple/pkl.git
synced 2026-07-01 02:31:45 +02:00
Replace ANTLR with hand-rolled parser (#917)
Co-authored-by: Kushal Pisavadia <kushi.p@gmail.com> Co-authored-by: Daniel Chao <daniel.h.chao@gmail.com>
This commit is contained in:
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* 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?
|
||||
;
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* 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'
|
||||
;
|
||||
@@ -29,5 +29,5 @@ baz = new Listing<Listing<Listing<Number>>> {
|
||||
inner.fold(_acc, (__acc, it) -> __acc.add(it))))
|
||||
|
||||
qux {
|
||||
(foo.bar) { "world" "!" } { [0] = "Goodbye " [1] = "cruel " }.toList().join("")
|
||||
(foo.bar) { "world" "!" } { [0] = "Goodbye "; [1] = "cruel " }.toList().join("")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@ res6{1;2}
|
||||
res7{foo = 1}
|
||||
res8{foo = 1 bar = 2}
|
||||
res9{nested{1}}
|
||||
res10{["foo"] = 1 ["bar"] = 2}
|
||||
res10{["foo"] = 1; ["bar"] = 2}
|
||||
res11 { new {} new {} new {} }
|
||||
res12 {1.2;.3;.4;.5}
|
||||
|
||||
+2
@@ -1,2 +1,4 @@
|
||||
foo = (bar) {
|
||||
x = 1
|
||||
|
||||
class Foo
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@ class Foo {
|
||||
open function foo() = 42
|
||||
}
|
||||
|
||||
res1 = Foo {}
|
||||
res1 = new Foo {}
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@ class Foo {
|
||||
open foo: Int = 42
|
||||
}
|
||||
|
||||
res1 = Foo {}
|
||||
res1 = new Foo {}
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
foo {
|
||||
1 2 3...IntSeq(4, 10)...IntSeq(11, 20)
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import "\(name).pkl"
|
||||
|
||||
name = "Bird"
|
||||
+1
@@ -0,0 +1 @@
|
||||
foo = 1 ^ 1
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import "pkl:reflect"
|
||||
|
||||
/// doc comment
|
||||
// line comments can appear between doc comments
|
||||
/*
|
||||
block comments also
|
||||
*/
|
||||
/// doc continuation
|
||||
foo = 1
|
||||
|
||||
theComment = reflect.Class(module.getClass()).properties["foo"].docComment
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/// doc comment start
|
||||
|
||||
/// doc comment continuation
|
||||
foo = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
bird: Listing<String> {
|
||||
"Crow"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
/// not a valid doc comment
|
||||
import "../../input-helper/basic/read/module1.pkl"
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Object members must be separated by whitespace, newline, or semicolon.
|
||||
Object entries must be separated by newline or semicolon.
|
||||
|
||||
x | 1.2.3
|
||||
^^
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Object members must be separated by whitespace, newline, or semicolon.
|
||||
Object entries must be separated by newline or semicolon.
|
||||
|
||||
x | res1 {foo=1bar=2}
|
||||
^^^^^
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Object members must be separated by whitespace, newline, or semicolon.
|
||||
Object entries must be separated by newline or semicolon.
|
||||
|
||||
x | }new{
|
||||
^^^^
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Mismatched input: `are`. Expected one of: `{`, `=`, `:`
|
||||
Missing `"` delimiter.
|
||||
|
||||
x | How are you today?
|
||||
^^^
|
||||
x | singleLineStringCannotSpanLines = "
|
||||
^
|
||||
at stringError1 (file:///$snippetsDir/input/basic/stringError1.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `this`. Expected `,` or `)`.
|
||||
|
||||
x | x: Int(isPositive this > 10)
|
||||
^
|
||||
at missingConstrainedTypeSeparator#x (file:///$snippetsDir/input/errors/delimiters/missingConstrainedTypeSeparator.pkl)
|
||||
^^^^
|
||||
at missingConstrainedTypeSeparator (file:///$snippetsDir/input/errors/delimiters/missingConstrainedTypeSeparator.pkl)
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ Missing `}` delimiter.
|
||||
|
||||
x | x = 1
|
||||
^
|
||||
at missingContainerAmendDefDelimiter#foo (file:///$snippetsDir/input/errors/delimiters/missingContainerAmendDefDelimiter.pkl)
|
||||
at missingContainerAmendDefDelimiter (file:///$snippetsDir/input/errors/delimiters/missingContainerAmendDefDelimiter.pkl)
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ Missing `}` delimiter.
|
||||
|
||||
x | x = 1
|
||||
^
|
||||
at missingContainerAmendExprDelimiter#foo (file:///$snippetsDir/input/errors/delimiters/missingContainerAmendExprDelimiter.pkl)
|
||||
at missingContainerAmendExprDelimiter (file:///$snippetsDir/input/errors/delimiters/missingContainerAmendExprDelimiter.pkl)
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Extraneous input: `<EOF>`. Expected one of: MLEndQuote, MLInterpolation, MLUnicodeEscape, MLCharacterEscape, MLNewline, MLCharacters
|
||||
Unexpected end of file.
|
||||
|
||||
x | res2 = 42
|
||||
^
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Mismatched input: `<EOF>`. Expected one of: MLEndQuote, MLInterpolation, MLUnicodeEscape, MLCharacterEscape, MLNewline, MLCharacters
|
||||
Unexpected end of file.
|
||||
|
||||
x | res1 = """
|
||||
^
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ Missing `"` delimiter.
|
||||
|
||||
x | res1 = "
|
||||
^
|
||||
at missingEmptyStringDelimiter#res1 (file:///$snippetsDir/input/errors/delimiters/missingEmptyStringDelimiter.pkl)
|
||||
at missingEmptyStringDelimiter (file:///$snippetsDir/input/errors/delimiters/missingEmptyStringDelimiter.pkl)
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Mismatched input: `<EOF>`. Expected one of: SLEndQuote, SLInterpolation, SLUnicodeEscape, SLCharacterEscape, SLCharacters
|
||||
Unexpected end of file.
|
||||
|
||||
x | res1 = "
|
||||
^
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `->`. Expected `)`.
|
||||
|
||||
x | f = ( -> 42
|
||||
^
|
||||
at missingFunction0ParameterListDelimiter#f (file:///$snippetsDir/input/errors/delimiters/missingFunction0ParameterListDelimiter.pkl)
|
||||
^^
|
||||
at missingFunction0ParameterListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingFunction0ParameterListDelimiter.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `->`. Expected `)`.
|
||||
|
||||
x | f = (arg -> arg + 1
|
||||
^
|
||||
at missingFunction1ParameterListDelimiter#f (file:///$snippetsDir/input/errors/delimiters/missingFunction1ParameterListDelimiter.pkl)
|
||||
^^
|
||||
at missingFunction1ParameterListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingFunction1ParameterListDelimiter.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `arg3`. Expected `,` or `->`.
|
||||
|
||||
x | f { arg1, arg2 arg3 ->
|
||||
^
|
||||
at missingFunctionAmendParameterListSeparator#f (file:///$snippetsDir/input/errors/delimiters/missingFunctionAmendParameterListSeparator.pkl)
|
||||
^^^^
|
||||
at missingFunctionAmendParameterListSeparator (file:///$snippetsDir/input/errors/delimiters/missingFunctionAmendParameterListSeparator.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `->`. Expected `,` or `)`.
|
||||
|
||||
x | f = (arg1, arg2, arg3 -> arg1 + arg2 + arg3
|
||||
^
|
||||
at missingFunctionNParameterListDelimiter#f (file:///$snippetsDir/input/errors/delimiters/missingFunctionNParameterListDelimiter.pkl)
|
||||
^^
|
||||
at missingFunctionNParameterListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingFunctionNParameterListDelimiter.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `arg3`. Expected `,` or `)`.
|
||||
|
||||
x | f = (arg1, arg2 arg3) -> arg1 + arg2 + arg3
|
||||
^
|
||||
at missingFunctionParameterListSeparator#f (file:///$snippetsDir/input/errors/delimiters/missingFunctionParameterListSeparator.pkl)
|
||||
^^^^
|
||||
at missingFunctionParameterListSeparator (file:///$snippetsDir/input/errors/delimiters/missingFunctionParameterListSeparator.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `->`. Expected a type or `)`.
|
||||
|
||||
x | f: ( -> String
|
||||
^
|
||||
at missingFunctionType0ParameterListDelimiter#f (file:///$snippetsDir/input/errors/delimiters/missingFunctionType0ParameterListDelimiter.pkl)
|
||||
^^
|
||||
at missingFunctionType0ParameterListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingFunctionType0ParameterListDelimiter.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `->`. Expected `,` or `)`.
|
||||
|
||||
x | f: (String -> String
|
||||
^
|
||||
at missingFunctionType1ParameterListDelimiter#f (file:///$snippetsDir/input/errors/delimiters/missingFunctionType1ParameterListDelimiter.pkl)
|
||||
^^
|
||||
at missingFunctionType1ParameterListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingFunctionType1ParameterListDelimiter.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `->`. Expected `,` or `)`.
|
||||
|
||||
x | f: (String, Int, String -> String
|
||||
^
|
||||
at missingFunctionTypeNParameterListDelimiter#f (file:///$snippetsDir/input/errors/delimiters/missingFunctionTypeNParameterListDelimiter.pkl)
|
||||
^^
|
||||
at missingFunctionTypeNParameterListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingFunctionTypeNParameterListDelimiter.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `String`. Expected `,` or `)`.
|
||||
|
||||
x | f: (String, Int String) -> String
|
||||
^
|
||||
at missingFunctionTypeParameterListSeparator#f (file:///$snippetsDir/input/errors/delimiters/missingFunctionTypeParameterListSeparator.pkl)
|
||||
^^^^^^
|
||||
at missingFunctionTypeParameterListSeparator (file:///$snippetsDir/input/errors/delimiters/missingFunctionTypeParameterListSeparator.pkl)
|
||||
|
||||
Vendored
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `3`. Expected `)`.
|
||||
|
||||
x | res1 = if (cond 3 else 4
|
||||
^
|
||||
at missingIfExprDelimiter#res1 (file:///$snippetsDir/input/errors/delimiters/missingIfExprDelimiter.pkl)
|
||||
^
|
||||
at missingIfExprDelimiter (file:///$snippetsDir/input/errors/delimiters/missingIfExprDelimiter.pkl)
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `EOF`. Expected `,` or `)`.
|
||||
|
||||
x | l = List("one", "two"
|
||||
^
|
||||
at missingListDelimiter#l (file:///$snippetsDir/input/errors/delimiters/missingListDelimiter.pkl)
|
||||
at missingListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingListDelimiter.pkl)
|
||||
|
||||
Vendored
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `3`. Expected `,` or `)`.
|
||||
|
||||
x | list = List(1, 2 3, 4)
|
||||
^
|
||||
at missingListSeparator#list (file:///$snippetsDir/input/errors/delimiters/missingListSeparator.pkl)
|
||||
^
|
||||
at missingListSeparator (file:///$snippetsDir/input/errors/delimiters/missingListSeparator.pkl)
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `EOF`. Expected `,` or `)`.
|
||||
|
||||
x | map = Map("one", 1, "two", 2
|
||||
^
|
||||
at missingMapDelimiter#map (file:///$snippetsDir/input/errors/delimiters/missingMapDelimiter.pkl)
|
||||
at missingMapDelimiter (file:///$snippetsDir/input/errors/delimiters/missingMapDelimiter.pkl)
|
||||
|
||||
Vendored
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `4`. Expected `,` or `)`.
|
||||
|
||||
x | map = Map(1, 2, 3 4, 5, 6)
|
||||
^
|
||||
at missingMapSeparator#map (file:///$snippetsDir/input/errors/delimiters/missingMapSeparator.pkl)
|
||||
^
|
||||
at missingMapSeparator (file:///$snippetsDir/input/errors/delimiters/missingMapSeparator.pkl)
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `res2`. Expected `,` or `)`.
|
||||
|
||||
x | res1 = "abc".substring(0, 1 + "def"
|
||||
^
|
||||
at missingMethodArgumentListDelimiter#res1 (file:///$snippetsDir/input/errors/delimiters/missingMethodArgumentListDelimiter.pkl)
|
||||
at missingMethodArgumentListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingMethodArgumentListDelimiter.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `3`. Expected `,` or `)`.
|
||||
|
||||
x | res1 = foo(1, 2 3)
|
||||
^
|
||||
at missingMethodArgumentListSeparator#res1 (file:///$snippetsDir/input/errors/delimiters/missingMethodArgumentListSeparator.pkl)
|
||||
^
|
||||
at missingMethodArgumentListSeparator (file:///$snippetsDir/input/errors/delimiters/missingMethodArgumentListSeparator.pkl)
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `=`. Expected `,` or `)`.
|
||||
|
||||
x | function foo(arg1, arg2 = arg1 + arg2
|
||||
^
|
||||
^
|
||||
at missingMethodParameterListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingMethodParameterListDelimiter.pkl)
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `arg2`. Expected `,` or `)`.
|
||||
|
||||
x | function foo(arg1 arg2) = arg1 + arg2
|
||||
^
|
||||
^^^^
|
||||
at missingMethodParameterListSeparator (file:///$snippetsDir/input/errors/delimiters/missingMethodParameterListSeparator.pkl)
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Extraneous input: `<EOF>`. Expected one of: MLEndQuote, MLInterpolation, MLUnicodeEscape, MLCharacterEscape, MLNewline, MLCharacters
|
||||
Unexpected end of file.
|
||||
|
||||
x |
|
||||
^
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ Missing `}` delimiter.
|
||||
|
||||
x | x = 1
|
||||
^
|
||||
at missingObjectAmendDefDelimiter#foo (file:///$snippetsDir/input/errors/delimiters/missingObjectAmendDefDelimiter.pkl)
|
||||
at missingObjectAmendDefDelimiter (file:///$snippetsDir/input/errors/delimiters/missingObjectAmendDefDelimiter.pkl)
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ Missing `}` delimiter.
|
||||
|
||||
x | }
|
||||
^
|
||||
at missingObjectAmendDefDelimiter2#foo (file:///$snippetsDir/input/errors/delimiters/missingObjectAmendDefDelimiter2.pkl)
|
||||
at missingObjectAmendDefDelimiter2 (file:///$snippetsDir/input/errors/delimiters/missingObjectAmendDefDelimiter2.pkl)
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ Missing `}` delimiter.
|
||||
|
||||
x | }
|
||||
^
|
||||
at missingObjectAmendDefDelimiter3#foo (file:///$snippetsDir/input/errors/delimiters/missingObjectAmendDefDelimiter3.pkl)
|
||||
at missingObjectAmendDefDelimiter3 (file:///$snippetsDir/input/errors/delimiters/missingObjectAmendDefDelimiter3.pkl)
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ Missing `}` delimiter.
|
||||
|
||||
x | x = 1
|
||||
^
|
||||
at missingObjectAmendExprDelimiter#foo (file:///$snippetsDir/input/errors/delimiters/missingObjectAmendExprDelimiter.pkl)
|
||||
at missingObjectAmendExprDelimiter (file:///$snippetsDir/input/errors/delimiters/missingObjectAmendExprDelimiter.pkl)
|
||||
|
||||
Vendored
+1
-1
@@ -3,4 +3,4 @@ Missing `}` delimiter.
|
||||
|
||||
x | x = 1
|
||||
^
|
||||
at missingObjectDelimiter#foo (file:///$snippetsDir/input/errors/delimiters/missingObjectDelimiter.pkl)
|
||||
at missingObjectDelimiter (file:///$snippetsDir/input/errors/delimiters/missingObjectDelimiter.pkl)
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `y`. Expected `)`.
|
||||
|
||||
x | x = 3 * (1 + 2
|
||||
^
|
||||
at missingParenthesizedExprDelimiter#x (file:///$snippetsDir/input/errors/delimiters/missingParenthesizedExprDelimiter.pkl)
|
||||
at missingParenthesizedExprDelimiter (file:///$snippetsDir/input/errors/delimiters/missingParenthesizedExprDelimiter.pkl)
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `res2`. Expected `,` or `)`.
|
||||
|
||||
x | res1: ((String) -> String | List<String>
|
||||
^
|
||||
at missingParenthesizedTypeDelimiter#res1 (file:///$snippetsDir/input/errors/delimiters/missingParenthesizedTypeDelimiter.pkl)
|
||||
at missingParenthesizedTypeDelimiter (file:///$snippetsDir/input/errors/delimiters/missingParenthesizedTypeDelimiter.pkl)
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Extraneous input: `<EOF>`. Expected one of: MLEndQuote, MLInterpolation, MLUnicodeEscape, MLCharacterEscape, MLNewline, MLCharacters
|
||||
Unexpected end of file.
|
||||
|
||||
x |
|
||||
^
|
||||
|
||||
Vendored
+1
-1
@@ -3,4 +3,4 @@ Missing `"#` delimiter.
|
||||
|
||||
x | res1 = #"abc
|
||||
^
|
||||
at missingRawStringDelimiter#res1 (file:///$snippetsDir/input/errors/delimiters/missingRawStringDelimiter.pkl)
|
||||
at missingRawStringDelimiter (file:///$snippetsDir/input/errors/delimiters/missingRawStringDelimiter.pkl)
|
||||
|
||||
Vendored
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `3`. Expected `,` or `)`.
|
||||
|
||||
x | set = Set(1, 2 3, 4)
|
||||
^
|
||||
at missingSetSeparator#set (file:///$snippetsDir/input/errors/delimiters/missingSetSeparator.pkl)
|
||||
^
|
||||
at missingSetSeparator (file:///$snippetsDir/input/errors/delimiters/missingSetSeparator.pkl)
|
||||
|
||||
Vendored
+1
-1
@@ -3,4 +3,4 @@ Missing `"` delimiter.
|
||||
|
||||
x | res1 = "abc
|
||||
^
|
||||
at missingStringDelimiter#res1 (file:///$snippetsDir/input/errors/delimiters/missingStringDelimiter.pkl)
|
||||
at missingStringDelimiter (file:///$snippetsDir/input/errors/delimiters/missingStringDelimiter.pkl)
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `]` delimiter.
|
||||
Unexpected token `EOF`. Expected `]`.
|
||||
|
||||
x | res1 = x[3 + 4
|
||||
^
|
||||
at missingSubscriptDelimiter#res1 (file:///$snippetsDir/input/errors/delimiters/missingSubscriptDelimiter.pkl)
|
||||
at missingSubscriptDelimiter (file:///$snippetsDir/input/errors/delimiters/missingSubscriptDelimiter.pkl)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `=`. Expected `,` or `)`.
|
||||
|
||||
x | res1: String(!isEmpty, length < 5 = "abc"
|
||||
^
|
||||
at missingTypeConstraintListDelimiter#res1 (file:///$snippetsDir/input/errors/delimiters/missingTypeConstraintListDelimiter.pkl)
|
||||
^
|
||||
at missingTypeConstraintListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingTypeConstraintListDelimiter.pkl)
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `)` delimiter.
|
||||
Unexpected token `=`. Expected `,` or `)`.
|
||||
|
||||
x | function foo(arg1: String, arg2: String = arg1 + arg2
|
||||
^
|
||||
^
|
||||
at missingTypedMethodParameterListDelimiter (file:///$snippetsDir/input/errors/delimiters/missingTypedMethodParameterListDelimiter.pkl)
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Missing `,` separator.
|
||||
Unexpected token `arg2`. Expected `,` or `)`.
|
||||
|
||||
x | function foo(arg1: String arg2: String) = arg1 + arg2
|
||||
^
|
||||
^^^^
|
||||
at missingTypedMethodParameterListSeparator (file:///$snippetsDir/input/errors/delimiters/missingTypedMethodParameterListSeparator.pkl)
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Expected delimiter `]]`, but got `]`.
|
||||
Unexpected token `{`. Expected `]]`.
|
||||
|
||||
x | [[name == "Pigeon"] { age = 42 }
|
||||
^
|
||||
at unbalancedEntryBrackets1#res (file:///$snippetsDir/input/errors/delimiters/unbalancedEntryBrackets1.pkl)
|
||||
at unbalancedEntryBrackets1 (file:///$snippetsDir/input/errors/delimiters/unbalancedEntryBrackets1.pkl)
|
||||
|
||||
Vendored
+3
-3
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Expected delimiter `]`, but got `]]`.
|
||||
Unexpected token `]`. Expected `{` or `=`.
|
||||
|
||||
x | [name == "Pigeon"]] { age = 42 }
|
||||
^
|
||||
at unbalancedEntryBrackets2#res (file:///$snippetsDir/input/errors/delimiters/unbalancedEntryBrackets2.pkl)
|
||||
^
|
||||
at unbalancedEntryBrackets2 (file:///$snippetsDir/input/errors/delimiters/unbalancedEntryBrackets2.pkl)
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Expected delimiter `]]`, but got `]`.
|
||||
Unexpected token `] ]`. Expected `]]`.
|
||||
|
||||
x | [[name == "Pigeon"] ] { age = 42 }
|
||||
^
|
||||
at unbalancedEntryBrackets3#res (file:///$snippetsDir/input/errors/delimiters/unbalancedEntryBrackets3.pkl)
|
||||
at unbalancedEntryBrackets3 (file:///$snippetsDir/input/errors/delimiters/unbalancedEntryBrackets3.pkl)
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Unmatched delimiter `]`.
|
||||
Unexpected token `]`. Expected `{` or `=`.
|
||||
|
||||
x | [name == "Pigeon"] ] { age = 42 }
|
||||
^
|
||||
at unbalancedEntryBrackets4#res (file:///$snippetsDir/input/errors/delimiters/unbalancedEntryBrackets4.pkl)
|
||||
at unbalancedEntryBrackets4 (file:///$snippetsDir/input/errors/delimiters/unbalancedEntryBrackets4.pkl)
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
–– Pkl Error ––
|
||||
Invalid character escape sequence `\a`.
|
||||
|
||||
Valid character escape sequences are: \n \r \t \" \\
|
||||
|
||||
x | res1 = "xxx\axxx"
|
||||
^^
|
||||
at invalidCharacterEscape#res1 (file:///$snippetsDir/input/errors/invalidCharacterEscape.pkl)
|
||||
|
||||
Valid character escape sequences are: \n \r \t \" \\
|
||||
at invalidCharacterEscape (file:///$snippetsDir/input/errors/invalidCharacterEscape.pkl)
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
–– Pkl Error ––
|
||||
Keyword `outer` is not allowed here. (If you must use this name as identifier, enclose it in backticks.)
|
||||
Keyword `outer` is not allowed here.
|
||||
|
||||
If you must use this name as identifier, enclose it in backticks.
|
||||
|
||||
x | outer = 42
|
||||
^^^^^
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
–– Pkl Error ––
|
||||
Keyword `outer` is not allowed here. (If you must use this name as identifier, enclose it in backticks.)
|
||||
Keyword `outer` is not allowed here.
|
||||
|
||||
If you must use this name as identifier, enclose it in backticks.
|
||||
|
||||
x | function outer() = 42
|
||||
^^^^^
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
–– Pkl Error ––
|
||||
Keyword `outer` is not allowed here. (If you must use this name as identifier, enclose it in backticks.)
|
||||
Keyword `outer` is not allowed here.
|
||||
|
||||
If you must use this name as identifier, enclose it in backticks.
|
||||
|
||||
x | res1 = outer.outer
|
||||
^^^^^
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
–– Pkl Error ––
|
||||
Keyword `record` is not allowed here. (If you must use this name as identifier, enclose it in backticks.)
|
||||
Keyword `record` is not allowed here.
|
||||
|
||||
If you must use this name as identifier, enclose it in backticks.
|
||||
|
||||
x | record = 5
|
||||
^^^^^^
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
Module `moduleAmendsSelf` cannot amend itself.
|
||||
|
||||
x | amends "moduleAmendsSelf.pkl"
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at moduleAmendsSelf (file:///$snippetsDir/input/errors/moduleAmendsSelf.pkl)
|
||||
|
||||
+2
-2
@@ -2,5 +2,5 @@
|
||||
A type union cannot have more than one default type.
|
||||
|
||||
x | foo: *Int|*String|*"foo"
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
at multipleDefaults#foo (file:///$snippetsDir/input/errors/multipleDefaults.pkl)
|
||||
^
|
||||
at multipleDefaults (file:///$snippetsDir/input/errors/multipleDefaults.pkl)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
–– Pkl Error ––
|
||||
Keyword `outer` is not allowed here. (If you must use this name as identifier, enclose it in backticks.)
|
||||
Keyword `outer` is not allowed here.
|
||||
|
||||
If you must use this name as identifier, enclose it in backticks.
|
||||
|
||||
x | x = outer.outer // nested syntax error
|
||||
^^^^^
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ Only type unions can have a default marker (*).
|
||||
|
||||
x | foo: *"foo"
|
||||
^^^^^^
|
||||
at notAUnionDefault#foo (file:///$snippetsDir/input/errors/notAUnionDefault.pkl)
|
||||
at notAUnionDefault (file:///$snippetsDir/input/errors/notAUnionDefault.pkl)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Token recognition error at: `#`
|
||||
Unexpected end of file.
|
||||
|
||||
x | res1 = 9#
|
||||
^
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Mismatched input: `[`. Expected one of: `module`, `nothing`, `unknown`, `(`, `{`, `*`, SLQuote, Identifier
|
||||
Unexpected token `[`. Expected a type or `{`.
|
||||
|
||||
x | res1 = new [ 42 }
|
||||
^
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
No viable alternative at input `foo = 42 ]`.
|
||||
Unexpected token `]`. Expected `}`.
|
||||
|
||||
x | res1 = new { foo = 42 ]
|
||||
^
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Extraneous input: `}`. Expected one of: <EOF>, `abstract`, `class`, `const`, `external`, `fixed`, `function`, `hidden`, `local`, `open`, `typealias`, `@`, Identifier, DocComment
|
||||
Invalid token at position. Expected a class, typealias, method, or property.
|
||||
|
||||
x | res1 = new { foo = 42 }}
|
||||
^
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
No viable alternative at input `///[1,2,3]\n`.
|
||||
Unexpected end of file.
|
||||
|
||||
x |
|
||||
^
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
–– Pkl Error ––
|
||||
Unexpected separator character.
|
||||
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
|
||||
x | res = 100e_10
|
||||
^
|
||||
at parser15#res (file:///$snippetsDir/input/errors/parser15.pkl)
|
||||
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
at parser15 (file:///$snippetsDir/input/errors/parser15.pkl)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
–– Pkl Error ––
|
||||
Unexpected separator character.
|
||||
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
|
||||
x | res = 0x_01
|
||||
^
|
||||
at parser16#res (file:///$snippetsDir/input/errors/parser16.pkl)
|
||||
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
at parser16 (file:///$snippetsDir/input/errors/parser16.pkl)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
–– Pkl Error ––
|
||||
Unexpected separator character.
|
||||
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
|
||||
x | res = 0b_01
|
||||
^
|
||||
at parser17#res (file:///$snippetsDir/input/errors/parser17.pkl)
|
||||
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
at parser17 (file:///$snippetsDir/input/errors/parser17.pkl)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
–– Pkl Error ––
|
||||
Unexpected separator character.
|
||||
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
|
||||
x | res = 100._01
|
||||
^
|
||||
at parser18#res (file:///$snippetsDir/input/errors/parser18.pkl)
|
||||
|
||||
The separator character (`_`) cannot follow `0x`, `0b`, `.`, `e`, or 'E' in a number literal.
|
||||
at parser18 (file:///$snippetsDir/input/errors/parser18.pkl)
|
||||
|
||||
@@ -3,4 +3,4 @@ Missing `"` delimiter.
|
||||
|
||||
x | res1 = "some string
|
||||
^
|
||||
at parser2#res1 (file:///$snippetsDir/input/errors/parser2.pkl)
|
||||
at parser2 (file:///$snippetsDir/input/errors/parser2.pkl)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Extraneous input: `<EOF>`. Expected one of: MLEndQuote, MLInterpolation, MLUnicodeEscape, MLCharacterEscape, MLNewline, MLCharacters
|
||||
Unexpected end of file.
|
||||
|
||||
x | res1 = """some string
|
||||
^
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Extraneous input: `<EOF>`. Expected one of: MLEndQuote, MLInterpolation, MLUnicodeEscape, MLCharacterEscape, MLNewline, MLCharacters
|
||||
Unexpected end of file.
|
||||
|
||||
x | res2 = 2
|
||||
^
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Extraneous input: `"`. Expected one of: <EOF>, `abstract`, `class`, `const`, `external`, `fixed`, `function`, `hidden`, `local`, `open`, `typealias`, `@`, Identifier, DocComment
|
||||
Invalid token at position. Expected a class, typealias, method, or property.
|
||||
|
||||
x | res1 = "some string"""
|
||||
^
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
Extraneous input: `<EOF>`. Expected one of: MLEndQuote, MLInterpolation, MLUnicodeEscape, MLCharacterEscape, MLNewline, MLCharacters
|
||||
Unexpected end of file.
|
||||
|
||||
x | res1 = """some string"
|
||||
^
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
–– Pkl Error ––
|
||||
No viable alternative at input `@11`.
|
||||
Unexpected token `11`. Expected a type.
|
||||
|
||||
x | res1 = a@11
|
||||
^^
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
–– Pkl Error ––
|
||||
Keyword `_` is not allowed here. (If you must use this name as identifier, enclose it in backticks.)
|
||||
Keyword `_` is not allowed here.
|
||||
|
||||
If you must use this name as identifier, enclose it in backticks.
|
||||
|
||||
x | _ = 0
|
||||
^
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
–– Pkl Error ––
|
||||
Unterminated Unicode escape sequence `\u{123`.
|
||||
|
||||
Unicode escape sequences must end with `}`.
|
||||
|
||||
x | res1 = "foo \u{123 bar"
|
||||
^^^^^^
|
||||
at unterminatedUnicodeEscape#res1 (file:///$snippetsDir/input/errors/unterminatedUnicodeEscape.pkl)
|
||||
|
||||
Unicode escape sequences must end with `}`.
|
||||
at unterminatedUnicodeEscape (file:///$snippetsDir/input/errors/unterminatedUnicodeEscape.pkl)
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
–– Pkl Error ––
|
||||
Object members must be separated by whitespace, newline, or semicolon.
|
||||
Object entries must be separated by newline or semicolon.
|
||||
|
||||
x | 1 2 3...IntSeq(4, 10)...IntSeq(11, 20)
|
||||
^^^^^^^^^^^^^^^^
|
||||
at spreadSyntaxNoSpace#foo (file:///$snippetsDir/input/generators/spreadSyntaxNoSpace.pkl)
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
–– Pkl Error ––
|
||||
Unexpected token: `{`.
|
||||
|
||||
If you meant to write an amends expression, wrap the parent in parentheses. Try: `(bar) { ... }`
|
||||
|
||||
x | (bar { "baz" })
|
||||
^
|
||||
at amendsRequiresParens#foo[#1] (file:///$snippetsDir/input/parser/amendsRequiresParens.pkl)
|
||||
|
||||
If you meant to write an amends expression, wrap the parent in parentheses. Try: `(bar) { ... }`
|
||||
at amendsRequiresParens (file:///$snippetsDir/input/parser/amendsRequiresParens.pkl)
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
String constant cannot have interpolated values.
|
||||
|
||||
x | import "\(name).pkl"
|
||||
^^
|
||||
at constantStringInterpolation (file:///$snippetsDir/input/parser/constantStringInterpolation.pkl)
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Invalid identifier `^`.
|
||||
|
||||
x | foo = 1 ^ 1
|
||||
^
|
||||
at invalidCharacter (file:///$snippetsDir/input/parser/invalidCharacter.pkl)
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
foo = 1
|
||||
theComment = """
|
||||
doc comment
|
||||
doc continuation
|
||||
"""
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
–– Pkl Error ––
|
||||
Dangling documentation comment.
|
||||
|
||||
Documentation comments must be attached to modules, classes, typealiases, methods, or properties.
|
||||
|
||||
x | /// doc comment continuation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at spacesBetweenDocComments (file:///$snippetsDir/input/parser/spacesBetweenDocComments.pkl)
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
–– Pkl Error ––
|
||||
Properties with type annotations cannot have object bodies.
|
||||
|
||||
To define both a type annotation and an object body, try using assignment instead.
|
||||
For example: `obj: Bird = new { ... }`.
|
||||
|
||||
x | bird: Listing<String> {
|
||||
^
|
||||
at typeAnnotationInAmends (file:///$snippetsDir/input/parser/typeAnnotationInAmends.pkl)
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
–– Pkl Error ––
|
||||
Imports cannot have doc comments, annotations or modifiers.
|
||||
|
||||
x | import "../../input-helper/basic/read/module1.pkl"
|
||||
^^^^^^
|
||||
at wrongDocComment (file:///$snippetsDir/input/parser/wrongDocComment.pkl)
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
Expected `output.value` of module `file:///$snippetsDir/input/projects/badPklProject1/PklProject` to be of type `pkl.Project`, but got type `invalid.project.Module`.
|
||||
|
||||
x | module invalid.project.Module
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
at invalid.project.Module (file:///$snippetsDir/input/projects/badPklProject1/PklProject)
|
||||
|
||||
Try adding `amends "pkl:Project"` to the module header.
|
||||
|
||||
@@ -116,7 +116,7 @@ class EvaluateExpressionTest {
|
||||
fun `evaluate expression with invalid syntax`() {
|
||||
val error = assertThrows<PklException> { evaluate("foo = 1", "<>!!!") }
|
||||
|
||||
assertThat(error).hasMessageContaining("Mismatched input")
|
||||
assertThat(error).hasMessageContaining("Unexpected token")
|
||||
assertThat(error).hasMessageContaining("<>!!!")
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ class EvaluateExpressionTest {
|
||||
fun `evaluate non-expression`() {
|
||||
val error = assertThrows<PklException> { evaluate("bar = 2", "bar = 15") }
|
||||
|
||||
assertThat(error).hasMessageContaining("Mismatched input")
|
||||
assertThat(error).hasMessageContaining("Unexpected token")
|
||||
assertThat(error).hasMessageContaining("bar = 15")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* 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.
|
||||
@@ -61,7 +61,7 @@ class ImportsAndReadsParserTest {
|
||||
"qux/*.pkl",
|
||||
"/some/dir/chown.txt",
|
||||
"/some/dir/chowner.txt",
|
||||
"/some/dir/*.txt"
|
||||
"/some/dir/*.txt",
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -82,10 +82,10 @@ class ImportsAndReadsParserTest {
|
||||
.hasMessage(
|
||||
"""
|
||||
–– Pkl Error ––
|
||||
Mismatched input: `<EOF>`. Expected one of: `{`, `=`, `:`
|
||||
|
||||
Invalid property definition. Expected a type annotation, `=` or `{`.
|
||||
|
||||
1 | not valid Pkl syntax
|
||||
^
|
||||
^^^
|
||||
at text (repl:text)
|
||||
|
||||
"""
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user