Upgrade to OPENRNDR 0.4 snapshot

This commit is contained in:
Edwin Jakobs
2021-06-22 11:08:07 +02:00
parent 579ddf9bb5
commit 9435907ef9
339 changed files with 460 additions and 497 deletions

View File

@@ -0,0 +1,46 @@
//plugins {
// id 'antlr'
//}
apply plugin: 'antlr'
sourceSets {
demo {
java {
srcDirs = ["src/demo/kotlin"]
compileClasspath += main.getCompileClasspath()
runtimeClasspath += main.getRuntimeClasspath()
}
}
main {
java {
srcDir("src/main/java")
srcDir("src/main/kotlin")
srcDir("build/generated-src/antlr")
}
}
}
generateGrammarSource {
maxHeapSize = "64m"
arguments += ["-visitor", "-long-messages"]
outputDirectory = file("${project.buildDir}/generated-src/antlr/org/openrndr/extra/kotlin/antlr".toString())
}
dependencies {
antlr("org.antlr:antlr4:$antlrVersion")
implementation("org.antlr:antlr4-runtime:$antlrVersion")
demoImplementation(project(":orx-camera"))
demoImplementation(project(":orx-panel"))
demoImplementation("org.openrndr:openrndr-application:$openrndrVersion")
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion")
demoImplementation(sourceSets.getByName("main").output)
}
tasks.getByName("compileKotlin").dependsOn("generateGrammarSource")

View File

@@ -0,0 +1,527 @@
/**
* Kotlin lexical grammar in ANTLR4 notation
*/
lexer grammar KotlinLexer;
import UnicodeClasses;
// SECTION: lexicalGeneral
ShebangLine
: '#!' ~[\r\n]*
;
DelimitedComment
: '/*' ( DelimitedComment | . )*? '*/'
-> channel(HIDDEN)
;
LineComment
: '//' ~[\r\n]*
-> channel(HIDDEN)
;
WS
: [\u0020\u0009\u000C]
-> channel(HIDDEN)
;
NL: '\n' | '\r' '\n'?;
fragment Hidden: DelimitedComment | LineComment | WS;
// SECTION: separatorsAndOperations
RESERVED: '...';
DOT: '.';
COMMA: ',';
LPAREN: '(' -> pushMode(Inside);
RPAREN: ')';
LSQUARE: '[' -> pushMode(Inside);
RSQUARE: ']';
LCURL: '{' -> pushMode(DEFAULT_MODE);
/*
* When using another programming language (not Java) to generate a parser,
* please replace this code with the corresponding code of a programming language you are using.
*/
RCURL: '}' { if (!_modeStack.isEmpty()) { popMode(); } };
MULT: '*';
MOD: '%';
DIV: '/';
ADD: '+';
SUB: '-';
INCR: '++';
DECR: '--';
CONJ: '&&';
DISJ: '||';
EXCL_WS: '!' Hidden;
EXCL_NO_WS: '!';
COLON: ':';
SEMICOLON: ';';
ASSIGNMENT: '=';
ADD_ASSIGNMENT: '+=';
SUB_ASSIGNMENT: '-=';
MULT_ASSIGNMENT: '*=';
DIV_ASSIGNMENT: '/=';
MOD_ASSIGNMENT: '%=';
ARROW: '->';
DOUBLE_ARROW: '=>';
RANGE: '..';
COLONCOLON: '::';
DOUBLE_SEMICOLON: ';;';
HASH: '#';
AT_NO_WS: '@';
AT_POST_WS: '@' (Hidden | NL);
AT_PRE_WS: (Hidden | NL) '@' ;
AT_BOTH_WS: (Hidden | NL) '@' (Hidden | NL);
QUEST_WS: '?' Hidden;
QUEST_NO_WS: '?';
LANGLE: '<';
RANGLE: '>';
LE: '<=';
GE: '>=';
EXCL_EQ: '!=';
EXCL_EQEQ: '!==';
AS_SAFE: 'as?';
EQEQ: '==';
EQEQEQ: '===';
SINGLE_QUOTE: '\'';
// SECTION: keywords
RETURN_AT: 'return@' Identifier;
CONTINUE_AT: 'continue@' Identifier;
BREAK_AT: 'break@' Identifier;
THIS_AT: 'this@' Identifier;
SUPER_AT: 'super@' Identifier;
FILE: 'file';
FIELD: 'field';
PROPERTY: 'property';
GET: 'get';
SET: 'set';
RECEIVER: 'receiver';
PARAM: 'param';
SETPARAM: 'setparam';
DELEGATE: 'delegate';
PACKAGE: 'package';
IMPORT: 'import';
CLASS: 'class';
INTERFACE: 'interface';
FUN: 'fun';
OBJECT: 'object';
VAL: 'val';
VAR: 'var';
TYPE_ALIAS: 'typealias';
CONSTRUCTOR: 'constructor';
BY: 'by';
COMPANION: 'companion';
INIT: 'init';
THIS: 'this';
SUPER: 'super';
TYPEOF: 'typeof';
WHERE: 'where';
IF: 'if';
ELSE: 'else';
WHEN: 'when';
TRY: 'try';
CATCH: 'catch';
FINALLY: 'finally';
FOR: 'for';
DO: 'do';
WHILE: 'while';
THROW: 'throw';
RETURN: 'return';
CONTINUE: 'continue';
BREAK: 'break';
AS: 'as';
IS: 'is';
IN: 'in';
NOT_IS: '!is' (Hidden | NL);
NOT_IN: '!in' (Hidden | NL);
OUT: 'out';
DYNAMIC: 'dynamic';
// SECTION: lexicalModifiers
PUBLIC: 'public';
PRIVATE: 'private';
PROTECTED: 'protected';
INTERNAL: 'internal';
ENUM: 'enum';
SEALED: 'sealed';
ANNOTATION: 'annotation';
DATA: 'data';
INNER: 'inner';
TAILREC: 'tailrec';
OPERATOR: 'operator';
INLINE: 'inline';
INFIX: 'infix';
EXTERNAL: 'external';
SUSPEND: 'suspend';
OVERRIDE: 'override';
ABSTRACT: 'abstract';
FINAL: 'final';
OPEN: 'open';
CONST: 'const';
LATEINIT: 'lateinit';
VARARG: 'vararg';
NOINLINE: 'noinline';
CROSSINLINE: 'crossinline';
REIFIED: 'reified';
EXPECT: 'expect';
ACTUAL: 'actual';
// SECTION: literals
fragment DecDigit: '0'..'9';
fragment DecDigitNoZero: '1'..'9';
fragment DecDigitOrSeparator: DecDigit | '_';
fragment DecDigits
: DecDigit DecDigitOrSeparator* DecDigit
| DecDigit
;
fragment DoubleExponent: [eE] [+-]? DecDigits;
RealLiteral
: FloatLiteral
| DoubleLiteral
;
FloatLiteral
: DoubleLiteral [fF]
| DecDigits [fF]
;
DoubleLiteral
: DecDigits? '.' DecDigits DoubleExponent?
| DecDigits DoubleExponent
;
IntegerLiteral
: DecDigitNoZero DecDigitOrSeparator* DecDigit
| DecDigit
;
fragment HexDigit: [0-9a-fA-F];
fragment HexDigitOrSeparator: HexDigit | '_';
HexLiteral
: '0' [xX] HexDigit HexDigitOrSeparator* HexDigit
| '0' [xX] HexDigit
;
fragment BinDigit: [01];
fragment BinDigitOrSeparator: BinDigit | '_';
BinLiteral
: '0' [bB] BinDigit BinDigitOrSeparator* BinDigit
| '0' [bB] BinDigit
;
UnsignedLiteral
: (IntegerLiteral | HexLiteral | BinLiteral) [uU] 'L'?
;
LongLiteral
: (IntegerLiteral | HexLiteral | BinLiteral) 'L'
;
BooleanLiteral: 'true'| 'false';
NullLiteral: 'null';
CharacterLiteral
: '\'' (EscapeSeq | ~[\n\r'\\]) '\''
;
// SECTION: lexicalIdentifiers
fragment UnicodeDigit: UNICODE_CLASS_ND;
Identifier
: (Letter | '_') (Letter | '_' | UnicodeDigit)*
| '`' ~([\r\n] | '`')+ '`'
;
IdentifierOrSoftKey
: Identifier
/* Soft keywords */
| ABSTRACT
| ANNOTATION
| BY
| CATCH
| COMPANION
| CONSTRUCTOR
| CROSSINLINE
| DATA
| DYNAMIC
| ENUM
| EXTERNAL
| FINAL
| FINALLY
| IMPORT
| INFIX
| INIT
| INLINE
| INNER
| INTERNAL
| LATEINIT
| NOINLINE
| OPEN
| OPERATOR
| OUT
| OVERRIDE
| PRIVATE
| PROTECTED
| PUBLIC
| REIFIED
| SEALED
| TAILREC
| VARARG
| WHERE
| GET
| SET
| FIELD
| PROPERTY
| RECEIVER
| PARAM
| SETPARAM
| DELEGATE
| FILE
| EXPECT
| ACTUAL
/* Strong keywords */
| CONST
| SUSPEND
;
FieldIdentifier
: '$' IdentifierOrSoftKey
;
fragment UniCharacterLiteral
: '\\' 'u' HexDigit HexDigit HexDigit HexDigit
;
fragment EscapedIdentifier
: '\\' ('t' | 'b' | 'r' | 'n' | '\'' | '"' | '\\' | '$')
;
fragment EscapeSeq
: UniCharacterLiteral
| EscapedIdentifier
;
// SECTION: characters
fragment Letter
: UNICODE_CLASS_LL
| UNICODE_CLASS_LM
| UNICODE_CLASS_LO
| UNICODE_CLASS_LT
| UNICODE_CLASS_LU
| UNICODE_CLASS_NL
;
// SECTION: strings
QUOTE_OPEN: '"' -> pushMode(LineString);
TRIPLE_QUOTE_OPEN: '"""' -> pushMode(MultiLineString);
mode LineString;
QUOTE_CLOSE
: '"' -> popMode
;
LineStrRef
: FieldIdentifier
;
LineStrText
: ~('\\' | '"' | '$')+ | '$'
;
LineStrEscapedChar
: EscapedIdentifier
| UniCharacterLiteral
;
LineStrExprStart
: '${' -> pushMode(DEFAULT_MODE)
;
mode MultiLineString;
TRIPLE_QUOTE_CLOSE
: MultiLineStringQuote? '"""' -> popMode
;
MultiLineStringQuote
: '"'+
;
MultiLineStrRef
: FieldIdentifier
;
MultiLineStrText
: ~('"' | '$')+ | '$'
;
MultiLineStrExprStart
: '${' -> pushMode(DEFAULT_MODE)
;
// SECTION: inside
mode Inside;
Inside_RPAREN: RPAREN -> popMode, type(RPAREN);
Inside_RSQUARE: RSQUARE -> popMode, type(RSQUARE);
Inside_LPAREN: LPAREN -> pushMode(Inside), type(LPAREN);
Inside_LSQUARE: LSQUARE -> pushMode(Inside), type(LSQUARE);
Inside_LCURL: LCURL -> pushMode(DEFAULT_MODE), type(LCURL);
Inside_RCURL: RCURL -> popMode, type(RCURL);
Inside_DOT: DOT -> type(DOT);
Inside_COMMA: COMMA -> type(COMMA);
Inside_MULT: MULT -> type(MULT);
Inside_MOD: MOD -> type(MOD);
Inside_DIV: DIV -> type(DIV);
Inside_ADD: ADD -> type(ADD);
Inside_SUB: SUB -> type(SUB);
Inside_INCR: INCR -> type(INCR);
Inside_DECR: DECR -> type(DECR);
Inside_CONJ: CONJ -> type(CONJ);
Inside_DISJ: DISJ -> type(DISJ);
Inside_EXCL_WS: '!' (Hidden|NL) -> type(EXCL_WS);
Inside_EXCL_NO_WS: EXCL_NO_WS -> type(EXCL_NO_WS);
Inside_COLON: COLON -> type(COLON);
Inside_SEMICOLON: SEMICOLON -> type(SEMICOLON);
Inside_ASSIGNMENT: ASSIGNMENT -> type(ASSIGNMENT);
Inside_ADD_ASSIGNMENT: ADD_ASSIGNMENT -> type(ADD_ASSIGNMENT);
Inside_SUB_ASSIGNMENT: SUB_ASSIGNMENT -> type(SUB_ASSIGNMENT);
Inside_MULT_ASSIGNMENT: MULT_ASSIGNMENT -> type(MULT_ASSIGNMENT);
Inside_DIV_ASSIGNMENT: DIV_ASSIGNMENT -> type(DIV_ASSIGNMENT);
Inside_MOD_ASSIGNMENT: MOD_ASSIGNMENT -> type(MOD_ASSIGNMENT);
Inside_ARROW: ARROW -> type(ARROW);
Inside_DOUBLE_ARROW: DOUBLE_ARROW -> type(DOUBLE_ARROW);
Inside_RANGE: RANGE -> type(RANGE);
Inside_RESERVED: RESERVED -> type(RESERVED);
Inside_COLONCOLON: COLONCOLON -> type(COLONCOLON);
Inside_DOUBLE_SEMICOLON: DOUBLE_SEMICOLON -> type(DOUBLE_SEMICOLON);
Inside_HASH: HASH -> type(HASH);
Inside_AT_NO_WS: AT_NO_WS -> type(AT_NO_WS);
Inside_AT_POST_WS: AT_POST_WS -> type(AT_POST_WS);
Inside_AT_PRE_WS: AT_PRE_WS -> type(AT_PRE_WS);
Inside_AT_BOTH_WS: AT_BOTH_WS -> type(AT_BOTH_WS);
Inside_QUEST_WS: '?' (Hidden | NL) -> type(QUEST_WS);
Inside_QUEST_NO_WS: QUEST_NO_WS -> type(QUEST_NO_WS);
Inside_LANGLE: LANGLE -> type(LANGLE);
Inside_RANGLE: RANGLE -> type(RANGLE);
Inside_LE: LE -> type(LE);
Inside_GE: GE -> type(GE);
Inside_EXCL_EQ: EXCL_EQ -> type(EXCL_EQ);
Inside_EXCL_EQEQ: EXCL_EQEQ -> type(EXCL_EQEQ);
Inside_IS: IS -> type(IS);
Inside_NOT_IS: NOT_IS -> type(NOT_IS);
Inside_NOT_IN: NOT_IN -> type(NOT_IN);
Inside_AS: AS -> type(AS);
Inside_AS_SAFE: AS_SAFE -> type(AS_SAFE);
Inside_EQEQ: EQEQ -> type(EQEQ);
Inside_EQEQEQ: EQEQEQ -> type(EQEQEQ);
Inside_SINGLE_QUOTE: SINGLE_QUOTE -> type(SINGLE_QUOTE);
Inside_QUOTE_OPEN: QUOTE_OPEN -> pushMode(LineString), type(QUOTE_OPEN);
Inside_TRIPLE_QUOTE_OPEN: TRIPLE_QUOTE_OPEN -> pushMode(MultiLineString), type(TRIPLE_QUOTE_OPEN);
Inside_VAL: VAL -> type(VAL);
Inside_VAR: VAR -> type(VAR);
Inside_FUN: FUN -> type(FUN);
Inside_OBJECT: OBJECT -> type(OBJECT);
Inside_SUPER: SUPER -> type(SUPER);
Inside_IN: IN -> type(IN);
Inside_OUT: OUT -> type(OUT);
Inside_FIELD: FIELD -> type(FIELD);
Inside_FILE: FILE -> type(FILE);
Inside_PROPERTY: PROPERTY -> type(PROPERTY);
Inside_GET: GET -> type(GET);
Inside_SET: SET -> type(SET);
Inside_RECEIVER: RECEIVER -> type(RECEIVER);
Inside_PARAM: PARAM -> type(PARAM);
Inside_SETPARAM: SETPARAM -> type(SETPARAM);
Inside_DELEGATE: DELEGATE -> type(DELEGATE);
Inside_THROW: THROW -> type(THROW);
Inside_RETURN: RETURN -> type(RETURN);
Inside_CONTINUE: CONTINUE -> type(CONTINUE);
Inside_BREAK: BREAK -> type(BREAK);
Inside_RETURN_AT: RETURN_AT -> type(RETURN_AT);
Inside_CONTINUE_AT: CONTINUE_AT -> type(CONTINUE_AT);
Inside_BREAK_AT: BREAK_AT -> type(BREAK_AT);
Inside_IF: IF -> type(IF);
Inside_ELSE: ELSE -> type(ELSE);
Inside_WHEN: WHEN -> type(WHEN);
Inside_TRY: TRY -> type(TRY);
Inside_CATCH: CATCH -> type(CATCH);
Inside_FINALLY: FINALLY -> type(FINALLY);
Inside_FOR: FOR -> type(FOR);
Inside_DO: DO -> type(DO);
Inside_WHILE: WHILE -> type(WHILE);
Inside_PUBLIC: PUBLIC -> type(PUBLIC);
Inside_PRIVATE: PRIVATE -> type(PRIVATE);
Inside_PROTECTED: PROTECTED -> type(PROTECTED);
Inside_INTERNAL: INTERNAL -> type(INTERNAL);
Inside_ENUM: ENUM -> type(ENUM);
Inside_SEALED: SEALED -> type(SEALED);
Inside_ANNOTATION: ANNOTATION -> type(ANNOTATION);
Inside_DATA: DATA -> type(DATA);
Inside_INNER: INNER -> type(INNER);
Inside_TAILREC: TAILREC -> type(TAILREC);
Inside_OPERATOR: OPERATOR -> type(OPERATOR);
Inside_INLINE: INLINE -> type(INLINE);
Inside_INFIX: INFIX -> type(INFIX);
Inside_EXTERNAL: EXTERNAL -> type(EXTERNAL);
Inside_SUSPEND: SUSPEND -> type(SUSPEND);
Inside_OVERRIDE: OVERRIDE -> type(OVERRIDE);
Inside_ABSTRACT: ABSTRACT -> type(ABSTRACT);
Inside_FINAL: FINAL -> type(FINAL);
Inside_OPEN: OPEN -> type(OPEN);
Inside_CONST: CONST -> type(CONST);
Inside_LATEINIT: LATEINIT -> type(LATEINIT);
Inside_VARARG: VARARG -> type(VARARG);
Inside_NOINLINE: NOINLINE -> type(NOINLINE);
Inside_CROSSINLINE: CROSSINLINE -> type(CROSSINLINE);
Inside_REIFIED: REIFIED -> type(REIFIED);
Inside_EXPECT: EXPECT -> type(EXPECT);
Inside_ACTUAL: ACTUAL -> type(ACTUAL);
Inside_BooleanLiteral: BooleanLiteral -> type(BooleanLiteral);
Inside_IntegerLiteral: IntegerLiteral -> type(IntegerLiteral);
Inside_HexLiteral: HexLiteral -> type(HexLiteral);
Inside_BinLiteral: BinLiteral -> type(BinLiteral);
Inside_CharacterLiteral: CharacterLiteral -> type(CharacterLiteral);
Inside_RealLiteral: RealLiteral -> type(RealLiteral);
Inside_NullLiteral: NullLiteral -> type(NullLiteral);
Inside_LongLiteral: LongLiteral -> type(LongLiteral);
Inside_UnsignedLiteral: UnsignedLiteral -> type(UnsignedLiteral);
Inside_Identifier: Identifier -> type(Identifier);
Inside_Comment: (LineComment | DelimitedComment) -> channel(HIDDEN);
Inside_WS: WS -> channel(HIDDEN);
Inside_NL: NL -> channel(HIDDEN);
mode DEFAULT_MODE;
ErrorCharacter: .;

View File

@@ -0,0 +1,288 @@
ShebangLine=1
DelimitedComment=2
LineComment=3
WS=4
NL=5
RESERVED=6
DOT=7
COMMA=8
LPAREN=9
RPAREN=10
LSQUARE=11
RSQUARE=12
LCURL=13
RCURL=14
MULT=15
MOD=16
DIV=17
ADD=18
SUB=19
INCR=20
DECR=21
CONJ=22
DISJ=23
EXCL_WS=24
EXCL_NO_WS=25
COLON=26
SEMICOLON=27
ASSIGNMENT=28
ADD_ASSIGNMENT=29
SUB_ASSIGNMENT=30
MULT_ASSIGNMENT=31
DIV_ASSIGNMENT=32
MOD_ASSIGNMENT=33
ARROW=34
DOUBLE_ARROW=35
RANGE=36
COLONCOLON=37
DOUBLE_SEMICOLON=38
HASH=39
AT_NO_WS=40
AT_POST_WS=41
AT_PRE_WS=42
AT_BOTH_WS=43
QUEST_WS=44
QUEST_NO_WS=45
LANGLE=46
RANGLE=47
LE=48
GE=49
EXCL_EQ=50
EXCL_EQEQ=51
AS_SAFE=52
EQEQ=53
EQEQEQ=54
SINGLE_QUOTE=55
RETURN_AT=56
CONTINUE_AT=57
BREAK_AT=58
THIS_AT=59
SUPER_AT=60
FILE=61
FIELD=62
PROPERTY=63
GET=64
SET=65
RECEIVER=66
PARAM=67
SETPARAM=68
DELEGATE=69
PACKAGE=70
IMPORT=71
CLASS=72
INTERFACE=73
FUN=74
OBJECT=75
VAL=76
VAR=77
TYPE_ALIAS=78
CONSTRUCTOR=79
BY=80
COMPANION=81
INIT=82
THIS=83
SUPER=84
TYPEOF=85
WHERE=86
IF=87
ELSE=88
WHEN=89
TRY=90
CATCH=91
FINALLY=92
FOR=93
DO=94
WHILE=95
THROW=96
RETURN=97
CONTINUE=98
BREAK=99
AS=100
IS=101
IN=102
NOT_IS=103
NOT_IN=104
OUT=105
DYNAMIC=106
PUBLIC=107
PRIVATE=108
PROTECTED=109
INTERNAL=110
ENUM=111
SEALED=112
ANNOTATION=113
DATA=114
INNER=115
TAILREC=116
OPERATOR=117
INLINE=118
INFIX=119
EXTERNAL=120
SUSPEND=121
OVERRIDE=122
ABSTRACT=123
FINAL=124
OPEN=125
CONST=126
LATEINIT=127
VARARG=128
NOINLINE=129
CROSSINLINE=130
REIFIED=131
EXPECT=132
ACTUAL=133
RealLiteral=134
FloatLiteral=135
DoubleLiteral=136
IntegerLiteral=137
HexLiteral=138
BinLiteral=139
UnsignedLiteral=140
LongLiteral=141
BooleanLiteral=142
NullLiteral=143
CharacterLiteral=144
Identifier=145
IdentifierOrSoftKey=146
FieldIdentifier=147
QUOTE_OPEN=148
TRIPLE_QUOTE_OPEN=149
UNICODE_CLASS_LL=150
UNICODE_CLASS_LM=151
UNICODE_CLASS_LO=152
UNICODE_CLASS_LT=153
UNICODE_CLASS_LU=154
UNICODE_CLASS_ND=155
UNICODE_CLASS_NL=156
QUOTE_CLOSE=157
LineStrRef=158
LineStrText=159
LineStrEscapedChar=160
LineStrExprStart=161
TRIPLE_QUOTE_CLOSE=162
MultiLineStringQuote=163
MultiLineStrRef=164
MultiLineStrText=165
MultiLineStrExprStart=166
Inside_Comment=167
Inside_WS=168
Inside_NL=169
ErrorCharacter=170
'...'=6
'.'=7
','=8
'('=9
')'=10
'['=11
']'=12
'{'=13
'}'=14
'*'=15
'%'=16
'/'=17
'+'=18
'-'=19
'++'=20
'--'=21
'&&'=22
'||'=23
'!'=25
':'=26
';'=27
'='=28
'+='=29
'-='=30
'*='=31
'/='=32
'%='=33
'->'=34
'=>'=35
'..'=36
'::'=37
';;'=38
'#'=39
'@'=40
'?'=45
'<'=46
'>'=47
'<='=48
'>='=49
'!='=50
'!=='=51
'as?'=52
'=='=53
'==='=54
'\''=55
'file'=61
'field'=62
'property'=63
'get'=64
'set'=65
'receiver'=66
'param'=67
'setparam'=68
'delegate'=69
'package'=70
'import'=71
'class'=72
'interface'=73
'fun'=74
'object'=75
'val'=76
'var'=77
'typealias'=78
'constructor'=79
'by'=80
'companion'=81
'init'=82
'this'=83
'super'=84
'typeof'=85
'where'=86
'if'=87
'else'=88
'when'=89
'try'=90
'catch'=91
'finally'=92
'for'=93
'do'=94
'while'=95
'throw'=96
'return'=97
'continue'=98
'break'=99
'as'=100
'is'=101
'in'=102
'out'=105
'dynamic'=106
'public'=107
'private'=108
'protected'=109
'internal'=110
'enum'=111
'sealed'=112
'annotation'=113
'data'=114
'inner'=115
'tailrec'=116
'operator'=117
'inline'=118
'infix'=119
'external'=120
'suspend'=121
'override'=122
'abstract'=123
'final'=124
'open'=125
'const'=126
'lateinit'=127
'vararg'=128
'noinline'=129
'crossinline'=130
'reified'=131
'expect'=132
'actual'=133
'null'=143
'"""'=149

View File

@@ -0,0 +1,930 @@
/**
* Kotlin syntax grammar in ANTLR4 notation
*/
parser grammar KotlinParser;
@header {
package org.openrndr.extra.kotlin.antlr;
}
options { tokenVocab = KotlinLexer; }
// SECTION: general
kotlinFile
: shebangLine? NL* fileAnnotation* packageHeader importList topLevelObject* EOF
;
script
: shebangLine? NL* fileAnnotation* packageHeader importList (statement semi)* EOF
;
shebangLine
: ShebangLine NL+
;
fileAnnotation
: (AT_NO_WS | AT_PRE_WS) FILE NL* COLON NL* (LSQUARE unescapedAnnotation+ RSQUARE | unescapedAnnotation) NL*
;
packageHeader
: (PACKAGE identifier semi?)?
;
importList
: importHeader*
;
importHeader
: IMPORT identifier (DOT MULT | importAlias)? semi?
;
importAlias
: AS simpleIdentifier
;
topLevelObject
: declaration semis?
;
typeAlias
: modifiers? TYPE_ALIAS NL* simpleIdentifier (NL* typeParameters)? NL* ASSIGNMENT NL* type
;
declaration
: classDeclaration
| objectDeclaration
| functionDeclaration
| propertyDeclaration
| typeAlias
;
// SECTION: classes
classDeclaration
: modifiers? (CLASS | (FUN NL*)? INTERFACE) NL* simpleIdentifier
(NL* typeParameters)? (NL* primaryConstructor)?
(NL* COLON NL* delegationSpecifiers)?
(NL* typeConstraints)?
(NL* classBody | NL* enumClassBody)?
;
primaryConstructor
: (modifiers? CONSTRUCTOR NL*)? classParameters
;
classBody
: LCURL NL* classMemberDeclarations NL* RCURL
;
classParameters
: LPAREN NL* (classParameter (NL* COMMA NL* classParameter)* (NL* COMMA)?)? NL* RPAREN
;
classParameter
: modifiers? (VAL | VAR)? NL* simpleIdentifier COLON NL* type (NL* ASSIGNMENT NL* expression)?
;
delegationSpecifiers
: annotatedDelegationSpecifier (NL* COMMA NL* annotatedDelegationSpecifier)*
;
delegationSpecifier
: constructorInvocation
| explicitDelegation
| userType
| functionType
;
constructorInvocation
: userType valueArguments
;
annotatedDelegationSpecifier
: annotation* NL* delegationSpecifier
;
explicitDelegation
: (userType | functionType) NL* BY NL* expression
;
typeParameters
: LANGLE NL* typeParameter (NL* COMMA NL* typeParameter)* (NL* COMMA)? NL* RANGLE
;
typeParameter
: typeParameterModifiers? NL* simpleIdentifier (NL* COLON NL* type)?
;
typeConstraints
: WHERE NL* typeConstraint (NL* COMMA NL* typeConstraint)*
;
typeConstraint
: annotation* simpleIdentifier NL* COLON NL* type
;
// SECTION: classMembers
classMemberDeclarations
: (classMemberDeclaration semis?)*
;
classMemberDeclaration
: declaration
| companionObject
| anonymousInitializer
| secondaryConstructor
;
anonymousInitializer
: INIT NL* block
;
companionObject
: modifiers? COMPANION NL* OBJECT
(NL* simpleIdentifier)?
(NL* COLON NL* delegationSpecifiers)?
(NL* classBody)?
;
functionValueParameters
: LPAREN NL* (functionValueParameter (NL* COMMA NL* functionValueParameter)* (NL* COMMA)?)? NL* RPAREN
;
functionValueParameter
: parameterModifiers? parameter (NL* ASSIGNMENT NL* expression)?
;
functionDeclaration
: modifiers?
FUN (NL* typeParameters)? (NL* receiverType NL* DOT)? NL* simpleIdentifier
NL* functionValueParameters
(NL* COLON NL* type)?
(NL* typeConstraints)?
(NL* functionBody)?
;
functionBody
: block
| ASSIGNMENT NL* expression
;
variableDeclaration
: annotation* NL* simpleIdentifier (NL* COLON NL* type)?
;
multiVariableDeclaration
: LPAREN NL* variableDeclaration (NL* COMMA NL* variableDeclaration)* (NL* COMMA)? NL* RPAREN
;
propertyDeclaration
: modifiers? (VAL | VAR)
(NL* typeParameters)?
(NL* receiverType NL* DOT)?
(NL* (multiVariableDeclaration | variableDeclaration))
(NL* typeConstraints)?
(NL* (ASSIGNMENT NL* expression | propertyDelegate))?
(NL+ SEMICOLON)? NL* (getter? (NL* semi? setter)? | setter? (NL* semi? getter)?)
;
propertyDelegate
: BY NL* expression
;
getter
: modifiers? GET
| modifiers? GET NL* LPAREN NL* RPAREN (NL* COLON NL* type)? NL* functionBody
;
setter
: modifiers? SET
| modifiers? SET NL* LPAREN NL* parameterWithOptionalType (NL* COMMA)? NL* RPAREN (NL* COLON NL* type)? NL* functionBody
;
parametersWithOptionalType
: LPAREN NL* (parameterWithOptionalType (NL* COMMA NL* parameterWithOptionalType)* (NL* COMMA)?)? NL* RPAREN
;
parameterWithOptionalType
: parameterModifiers? simpleIdentifier NL* (COLON NL* type)?
;
parameter
: simpleIdentifier NL* COLON NL* type
;
objectDeclaration
: modifiers? OBJECT
NL* simpleIdentifier
(NL* COLON NL* delegationSpecifiers)?
(NL* classBody)?
;
secondaryConstructor
: modifiers? CONSTRUCTOR NL* functionValueParameters (NL* COLON NL* constructorDelegationCall)? NL* block?
;
constructorDelegationCall
: THIS NL* valueArguments
| SUPER NL* valueArguments
;
// SECTION: enumClasses
enumClassBody
: LCURL NL* enumEntries? (NL* SEMICOLON NL* classMemberDeclarations)? NL* RCURL
;
enumEntries
: enumEntry (NL* COMMA NL* enumEntry)* NL* COMMA?
;
enumEntry
: (modifiers NL*)? simpleIdentifier (NL* valueArguments)? (NL* classBody)?
;
// SECTION: types
type
: typeModifiers?
( parenthesizedType
| nullableType
| typeReference
| functionType)
;
typeReference
: userType
| DYNAMIC
;
nullableType
: (typeReference | parenthesizedType) NL* quest+
;
quest
: QUEST_NO_WS
| QUEST_WS
;
userType
: simpleUserType (NL* DOT NL* simpleUserType)*
;
simpleUserType
: simpleIdentifier (NL* typeArguments)?
;
typeProjection
: typeProjectionModifiers? type | MULT
;
typeProjectionModifiers
: typeProjectionModifier+
;
typeProjectionModifier
: varianceModifier NL*
| annotation
;
functionType
: (receiverType NL* DOT NL*)? functionTypeParameters NL* ARROW NL* type
;
functionTypeParameters
: LPAREN NL* (parameter | type)? (NL* COMMA NL* (parameter | type))* (NL* COMMA)? NL* RPAREN
;
parenthesizedType
: LPAREN NL* type NL* RPAREN
;
receiverType
: typeModifiers?
( parenthesizedType
| nullableType
| typeReference)
;
parenthesizedUserType
: LPAREN NL* userType NL* RPAREN
| LPAREN NL* parenthesizedUserType NL* RPAREN
;
// SECTION: statements
statements
: (statement (semis statement)*)? semis?
;
statement
: (label | annotation)*
( declaration
| assignment
| loopStatement
| expression)
;
label
: simpleIdentifier (AT_NO_WS | AT_POST_WS) NL*
;
controlStructureBody
: block
| statement
;
block
: LCURL NL* statements NL* RCURL
;
loopStatement
: forStatement
| whileStatement
| doWhileStatement
;
forStatement
: FOR NL* LPAREN annotation* (variableDeclaration | multiVariableDeclaration) IN expression RPAREN NL* controlStructureBody?
;
whileStatement
: WHILE NL* LPAREN expression RPAREN NL* controlStructureBody
| WHILE NL* LPAREN expression RPAREN NL* SEMICOLON
;
doWhileStatement
: DO NL* controlStructureBody? NL* WHILE NL* LPAREN expression RPAREN
;
assignment
: directlyAssignableExpression ASSIGNMENT NL* expression
| assignableExpression assignmentAndOperator NL* expression
;
semi
: (SEMICOLON | NL) NL*
| EOF;
semis
: (SEMICOLON | NL)+
| EOF
;
// SECTION: expressions
expression
: disjunction
;
disjunction
: conjunction (NL* DISJ NL* conjunction)*
;
conjunction
: equality (NL* CONJ NL* equality)*
;
equality
: comparison (equalityOperator NL* comparison)*
;
comparison
: infixOperation (comparisonOperator NL* infixOperation)?
;
infixOperation
: elvisExpression (inOperator NL* elvisExpression | isOperator NL* type)*
;
elvisExpression
: infixFunctionCall (NL* elvis NL* infixFunctionCall)*
;
elvis
: QUEST_NO_WS COLON
;
infixFunctionCall
: rangeExpression (simpleIdentifier NL* rangeExpression)*
;
rangeExpression
: additiveExpression (RANGE NL* additiveExpression)*
;
additiveExpression
: multiplicativeExpression (additiveOperator NL* multiplicativeExpression)*
;
multiplicativeExpression
: asExpression (multiplicativeOperator NL* asExpression)*
;
asExpression
: comparisonWithLiteralRightSide (NL* asOperator NL* type)?
;
comparisonWithLiteralRightSide
: prefixUnaryExpression (NL* LANGLE NL* literalConstant NL* RANGLE NL* (expression | parenthesizedExpression))*
;
prefixUnaryExpression
: unaryPrefix* postfixUnaryExpression
;
unaryPrefix
: annotation
| label
| prefixUnaryOperator NL*
;
postfixUnaryExpression
: primaryExpression
| primaryExpression postfixUnarySuffix+
;
postfixUnarySuffix
: postfixUnaryOperator
| typeArguments
| callSuffix
| indexingSuffix
| navigationSuffix
;
directlyAssignableExpression
: postfixUnaryExpression assignableSuffix
| simpleIdentifier
| parenthesizedDirectlyAssignableExpression
;
parenthesizedDirectlyAssignableExpression
: LPAREN NL* directlyAssignableExpression NL* RPAREN
;
assignableExpression
: prefixUnaryExpression | parenthesizedAssignableExpression
;
parenthesizedAssignableExpression
: LPAREN NL* assignableExpression NL* RPAREN
;
assignableSuffix
: typeArguments
| indexingSuffix
| navigationSuffix
;
indexingSuffix
: LSQUARE NL* expression (NL* COMMA NL* expression)* (NL* COMMA)? NL* RSQUARE
;
navigationSuffix
: NL* memberAccessOperator NL* (simpleIdentifier | parenthesizedExpression | CLASS)
;
callSuffix
: typeArguments? valueArguments? annotatedLambda
| typeArguments? valueArguments
;
annotatedLambda
: annotation* label? NL* lambdaLiteral
;
typeArguments
: LANGLE NL* typeProjection (NL* COMMA NL* typeProjection)* (NL* COMMA)? NL* RANGLE
;
valueArguments
: LPAREN NL* RPAREN
| LPAREN NL* valueArgument (NL* COMMA NL* valueArgument)* (NL* COMMA)? NL* RPAREN
;
valueArgument
: annotation? NL* (simpleIdentifier NL* ASSIGNMENT NL*)? MULT? NL* expression
;
primaryExpression
: parenthesizedExpression
| simpleIdentifier
| literalConstant
| stringLiteral
| callableReference
| functionLiteral
| objectLiteral
| collectionLiteral
| thisExpression
| superExpression
| ifExpression
| whenExpression
| tryExpression
| jumpExpression
;
parenthesizedExpression
: LPAREN NL* expression NL* RPAREN
;
collectionLiteral
: LSQUARE NL* expression (NL* COMMA NL* expression)* (NL* COMMA)? NL* RSQUARE
| LSQUARE NL* RSQUARE
;
literalConstant
: BooleanLiteral
| IntegerLiteral
| HexLiteral
| BinLiteral
| CharacterLiteral
| RealLiteral
| NullLiteral
| LongLiteral
| UnsignedLiteral
;
stringLiteral
: lineStringLiteral
| multiLineStringLiteral
;
lineStringLiteral
: QUOTE_OPEN (lineStringContent | lineStringExpression)* QUOTE_CLOSE
;
multiLineStringLiteral
: TRIPLE_QUOTE_OPEN (multiLineStringContent | multiLineStringExpression | MultiLineStringQuote)* TRIPLE_QUOTE_CLOSE
;
lineStringContent
: LineStrText
| LineStrEscapedChar
| LineStrRef
;
lineStringExpression
: LineStrExprStart expression RCURL
;
multiLineStringContent
: MultiLineStrText
| MultiLineStringQuote
| MultiLineStrRef
;
multiLineStringExpression
: MultiLineStrExprStart NL* expression NL* RCURL
;
lambdaLiteral
: LCURL NL* statements NL* RCURL
| LCURL NL* lambdaParameters? NL* ARROW NL* statements NL* RCURL
;
lambdaParameters
: lambdaParameter (NL* COMMA NL* lambdaParameter)* (NL* COMMA)?
;
lambdaParameter
: variableDeclaration
| multiVariableDeclaration (NL* COLON NL* type)?
;
anonymousFunction
: FUN
(NL* type NL* DOT)?
NL* parametersWithOptionalType
(NL* COLON NL* type)?
(NL* typeConstraints)?
(NL* functionBody)?
;
functionLiteral
: lambdaLiteral
| anonymousFunction
;
objectLiteral
: OBJECT NL* COLON NL* delegationSpecifiers NL* classBody
| OBJECT NL* classBody
;
thisExpression
: THIS
| THIS_AT
;
superExpression
: SUPER (LANGLE NL* type NL* RANGLE)? (AT_NO_WS simpleIdentifier)?
| SUPER_AT
;
ifExpression
: IF NL* LPAREN NL* expression NL* RPAREN NL* (controlStructureBody | SEMICOLON)
| IF NL* LPAREN NL* expression NL* RPAREN NL* controlStructureBody? NL* SEMICOLON? NL* ELSE NL* (controlStructureBody | SEMICOLON)
;
whenSubject
: LPAREN (annotation* NL* VAL NL* variableDeclaration NL* ASSIGNMENT NL*)? expression RPAREN
;
whenExpression
: WHEN NL* whenSubject? NL* LCURL NL* (whenEntry NL*)* NL* RCURL
;
whenEntry
: whenCondition (NL* COMMA NL* whenCondition)* (NL* COMMA)? NL* ARROW NL* controlStructureBody semi?
| ELSE NL* ARROW NL* controlStructureBody semi?
;
whenCondition
: expression
| rangeTest
| typeTest
;
rangeTest
: inOperator NL* expression
;
typeTest
: isOperator NL* type
;
tryExpression
: TRY NL* block ((NL* catchBlock)+ (NL* finallyBlock)? | NL* finallyBlock)
;
catchBlock
: CATCH NL* LPAREN annotation* simpleIdentifier COLON type (NL* COMMA)? RPAREN NL* block
;
finallyBlock
: FINALLY NL* block
;
jumpExpression
: THROW NL* expression
| (RETURN | RETURN_AT) expression?
| CONTINUE | CONTINUE_AT
| BREAK | BREAK_AT
;
callableReference
: (receiverType? NL* COLONCOLON NL* (simpleIdentifier | CLASS))
;
assignmentAndOperator
: ADD_ASSIGNMENT
| SUB_ASSIGNMENT
| MULT_ASSIGNMENT
| DIV_ASSIGNMENT
| MOD_ASSIGNMENT
;
equalityOperator
: EXCL_EQ
| EXCL_EQEQ
| EQEQ
| EQEQEQ
;
comparisonOperator
: LANGLE
| RANGLE
| LE
| GE
;
inOperator
: IN | NOT_IN
;
isOperator
: IS | NOT_IS
;
additiveOperator
: ADD | SUB
;
multiplicativeOperator
: MULT
| DIV
| MOD
;
asOperator
: AS
| AS_SAFE
;
prefixUnaryOperator
: INCR
| DECR
| SUB
| ADD
| excl
;
postfixUnaryOperator
: INCR
| DECR
| EXCL_NO_WS excl
;
excl
: EXCL_NO_WS
| EXCL_WS
;
memberAccessOperator
: DOT | safeNav | COLONCOLON
;
safeNav
: QUEST_NO_WS DOT
;
// SECTION: modifiers
modifiers
: (annotation | modifier)+
;
parameterModifiers
: (annotation | parameterModifier)+
;
modifier
: (classModifier
| memberModifier
| visibilityModifier
| functionModifier
| propertyModifier
| inheritanceModifier
| parameterModifier
| platformModifier) NL*
;
typeModifiers
: typeModifier+
;
typeModifier
: annotation | SUSPEND NL*
;
classModifier
: ENUM
| SEALED
| ANNOTATION
| DATA
| INNER
;
memberModifier
: OVERRIDE
| LATEINIT
;
visibilityModifier
: PUBLIC
| PRIVATE
| INTERNAL
| PROTECTED
;
varianceModifier
: IN
| OUT
;
typeParameterModifiers
: typeParameterModifier+
;
typeParameterModifier
: reificationModifier NL*
| varianceModifier NL*
| annotation
;
functionModifier
: TAILREC
| OPERATOR
| INFIX
| INLINE
| EXTERNAL
| SUSPEND
;
propertyModifier
: CONST
;
inheritanceModifier
: ABSTRACT
| FINAL
| OPEN
;
parameterModifier
: VARARG
| NOINLINE
| CROSSINLINE
;
reificationModifier
: REIFIED
;
platformModifier
: EXPECT
| ACTUAL
;
// SECTION: annotations
annotation
: (singleAnnotation | multiAnnotation) NL*
;
singleAnnotation
: annotationUseSiteTarget NL* unescapedAnnotation
| (AT_NO_WS | AT_PRE_WS) unescapedAnnotation
;
multiAnnotation
: annotationUseSiteTarget NL* LSQUARE unescapedAnnotation+ RSQUARE
| (AT_NO_WS | AT_PRE_WS) LSQUARE unescapedAnnotation+ RSQUARE
;
annotationUseSiteTarget
: (AT_NO_WS | AT_PRE_WS) (FIELD | PROPERTY | GET | SET | RECEIVER | PARAM | SETPARAM | DELEGATE) NL* COLON
;
unescapedAnnotation
: constructorInvocation
| userType
;
// SECTION: identifiers
simpleIdentifier: Identifier
| ABSTRACT
| ANNOTATION
| BY
| CATCH
| COMPANION
| CONSTRUCTOR
| CROSSINLINE
| DATA
| DYNAMIC
| ENUM
| EXTERNAL
| FINAL
| FINALLY
| GET
| IMPORT
| INFIX
| INIT
| INLINE
| INNER
| INTERNAL
| LATEINIT
| NOINLINE
| OPEN
| OPERATOR
| OUT
| OVERRIDE
| PRIVATE
| PROTECTED
| PUBLIC
| REIFIED
| SEALED
| TAILREC
| SET
| VARARG
| WHERE
| FIELD
| PROPERTY
| RECEIVER
| PARAM
| SETPARAM
| DELEGATE
| FILE
| EXPECT
| ACTUAL
| CONST
| SUSPEND
;
identifier
: simpleIdentifier (NL* DOT simpleIdentifier)*
;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
UNICODE_CLASS_LL=1
UNICODE_CLASS_LM=2
UNICODE_CLASS_LO=3
UNICODE_CLASS_LT=4
UNICODE_CLASS_LU=5
UNICODE_CLASS_ND=6
UNICODE_CLASS_NL=7

View File

@@ -0,0 +1,76 @@
package org.openrndr.extra.kotlinparser
import org.antlr.v4.runtime.CharStreams
import org.antlr.v4.runtime.CommonTokenStream
import org.antlr.v4.runtime.ParserRuleContext
import org.antlr.v4.runtime.RuleContext
import org.antlr.v4.runtime.misc.Interval
import org.antlr.v4.runtime.tree.ParseTreeWalker
import org.openrndr.extra.kotlin.antlr.KotlinLexer
import org.openrndr.extra.kotlin.antlr.KotlinParser
import org.openrndr.extra.kotlin.antlr.KotlinParserBaseListener
fun ParserRuleContext.verbatimText(marginLeft: Int = 0, marginRight: Int = 0): String {
if (start == null || stop == null) {
return ""
}
val startIndex = start.startIndex + marginLeft
val stopIndex = stop.stopIndex - marginRight
val interval = Interval(startIndex, stopIndex)
return start.inputStream.getText(interval)
}
class PackageExtractor() : KotlinParserBaseListener() {
var result: String? = null
override fun enterPackageHeader(ctx: KotlinParser.PackageHeaderContext) {
result = ctx.verbatimText()
}
}
class ImportsExtractor(val ruleNames: List<String>) : KotlinParserBaseListener() {
var result: String? = null
override fun enterImportList(ctx: KotlinParser.ImportListContext) {
result = ctx.verbatimText()
}
}
class LambdaExtractor(val ruleNames: List<String>, val lambdaName: String) : KotlinParserBaseListener() {
fun RuleContext.named(): String {
return ruleNames[this.ruleIndex]
}
var result: String? = null
override fun enterAnnotatedLambda(ctx: KotlinParser.AnnotatedLambdaContext?) {
val puec = ctx?.parent?.parent?.parent as? KotlinParser.PostfixUnaryExpressionContext
if (puec != null) {
val identifier = puec.primaryExpression()?.simpleIdentifier()?.Identifier()?.text
if (identifier == lambdaName) {
if (result == null) {
result = ctx.verbatimText(1, 1)
}
}
}
}
}
class ProgramSource(val packageName: String?, val imports: String, val programLambda: String)
fun extractProgram(source: String, programIdentifier: String = "program"): ProgramSource {
val parser = KotlinParser(CommonTokenStream(KotlinLexer(CharStreams.fromString(source))))
val root = parser.kotlinFile()
// val rules = parser.ruleNames.toList()
// val pt = TreeUtils.toPrettyTree(root, rules)
val ruleNames = parser.ruleNames.toList()
val packageExtractor = PackageExtractor()
ParseTreeWalker.DEFAULT.walk(packageExtractor, root)
val importsExtractor = ImportsExtractor(ruleNames)
ParseTreeWalker.DEFAULT.walk(importsExtractor, root)
val lambdaExtractor = LambdaExtractor(ruleNames, programIdentifier)
ParseTreeWalker.DEFAULT.walk(lambdaExtractor, root)
return ProgramSource(packageExtractor.result, importsExtractor.result ?: "", lambdaExtractor.result ?: "")
}

View File

@@ -0,0 +1,49 @@
package org.openrndr.extra.kotlinparser
import org.antlr.v4.runtime.misc.Utils
import org.antlr.v4.runtime.tree.Tree
import org.antlr.v4.runtime.tree.Trees
object TreeUtils {
/** Platform dependent end-of-line marker */
val Eol = System.lineSeparator()
/** The literal indent char(s) used for pretty-printing */
const val Indents = " "
private var level = 0
/**
* Pretty print out a whole tree. [.getNodeText] is used on the node payloads to get the text
* for the nodes. (Derived from Trees.toStringTree(....))
*/
fun toPrettyTree(t: Tree, ruleNames: List<String>): String {
level = 0
return process(t, ruleNames).replace("(?m)^\\s+$".toRegex(), "").replace("\\r?\\n\\r?\\n".toRegex(), Eol)
}
private fun process(t: Tree, ruleNames: List<String>): String {
if (t.getChildCount() == 0) return Utils.escapeWhitespace(Trees.getNodeText(t, ruleNames), false)
val sb = StringBuilder()
sb.append(lead(level))
level++
val s: String = Utils.escapeWhitespace(Trees.getNodeText(t, ruleNames), false)
sb.append("$s ")
for (i in 0 until t.getChildCount()) {
sb.append(process(t.getChild(i), ruleNames))
}
level--
sb.append(lead(level))
return sb.toString()
}
private fun lead(level: Int): String {
val sb = StringBuilder()
if (level > 0) {
sb.append(Eol)
for (cnt in 0 until level) {
sb.append(Indents)
}
}
return sb.toString()
}
}