From 1c27f9234b5d98f3800ab4e611cfede85439fddf Mon Sep 17 00:00:00 2001 From: Nishant Aanjaney Jalan Date: Wed, 3 Jul 2024 01:33:16 +0100 Subject: [PATCH] feat: added single and multiline comments to the dsl --- .../parkour/lexer/LexerBuilder.kt | 58 +++++++++++++- .../parkour/lexer/internal/Lexer.kt | 6 +- .../parkour/lexer/LexerBuilderTest.kt | 32 ++++++++ .../-lexer/-defaults/escape-sequences.html | 2 +- .../-lexer/-defaults/floating-literals.html | 2 +- .../-lexer/-defaults/identifiers.html | 2 +- .../-lexer/-defaults/index.html | 30 ++++++++ .../-lexer/-defaults/integer-literals.html | 2 +- .../-lexer/-defaults/multiline-comments.html | 76 +++++++++++++++++++ .../-defaults/single-line-comments.html | 76 +++++++++++++++++++ .../-lexer/-defaults/single-line-string.html | 2 +- .../-lexer-builder/ignore-pattern.html | 2 +- .../-lexer-builder/index.html | 30 ++++++++ .../-lexer-builder/multi-line-comments.html | 76 +++++++++++++++++++ .../-lexer-builder/single-line-comments.html | 76 +++++++++++++++++++ .../lexer.html | 2 +- docs/scripts/pages.json | 2 +- 17 files changed, 465 insertions(+), 11 deletions(-) create mode 100644 docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/multiline-comments.html create mode 100644 docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/single-line-comments.html create mode 100644 docs/core/io.github.cybercodernaj.parkour.lexer/-lexer-builder/multi-line-comments.html create mode 100644 docs/core/io.github.cybercodernaj.parkour.lexer/-lexer-builder/single-line-comments.html diff --git a/core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/LexerBuilder.kt b/core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/LexerBuilder.kt index f79f932..ba0e100 100644 --- a/core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/LexerBuilder.kt +++ b/core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/LexerBuilder.kt @@ -14,10 +14,22 @@ class LexerBuilder internal constructor() { internal var ignorePattern: Regex = Lexer.Defaults.ignorePattern private set + internal var singleLineComments: Regex? = Lexer.Defaults.singleLineComments + private set + + internal var multilineComments: Pair? = Lexer.Defaults.multilineComments + private set + /** * The lexer will skip over any strings that match this regex. * This acts like a token separator. * + * ```kt + * val myLexer = lexer { + * ignorePatterns(Regex("""\s+""")) + * } + * ``` + * * @param regex regex of the pattern the lexer will not tokenize. * * @see Lexer.Defaults.ignorePattern @@ -27,6 +39,48 @@ class LexerBuilder internal constructor() { fun ignorePattern(regex: Regex) { ignorePattern = regex } + + /** + * When the lexer identifies a [singleLineComments] pattern, it will skip to the next line + * and return the next token. + * + * ```kt + * val myLexer = lexer { + * singleLineComments(Regex("//")) + * } + * ``` + * + * @param singleLineComments regex of the pattern the lexer will skip over to the next line. + * + * @see Lexer.Defaults.singleLineComments + * @author Nishant Aanjaney Jalan + * @since 0.2.0 + */ + fun singleLineComments(singleLineComments: Regex) { + this.singleLineComments = singleLineComments + } + + /** + * There are two parts to [multilineComments]: the starting and the ending pattern. + * When the lexer identifies the starting pattern, it will continue to skip to the next possible token + * until it meets the ending pattern. + * + * ```kt + * val myLexer = lexer { + * // You don't need the square brackets but KDoc doesn't like it... + * multiLineComments(Regex("[/][*]") to Regex("[*][/]")) + * } + * ``` + * + * @param singleLineComments regex of the pattern the lexer will skip over to the next line. + * + * @see Lexer.Defaults.singleLineComments + * @author Nishant Aanjaney Jalan + * @since 0.2.0 + */ + fun multiLineComments(multilineComments: Pair) { + this.multilineComments = multilineComments + } } /** @@ -52,6 +106,8 @@ fun lexer(init: LexerBuilder.() -> Unit): Lexer { val builder = LexerBuilder() builder.init() return Lexer( - ignorePattern = builder.ignorePattern + ignorePattern = builder.ignorePattern, + singleLineComments = builder.singleLineComments, + multilineComments = builder.multilineComments ) } \ No newline at end of file diff --git a/core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/internal/Lexer.kt b/core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/internal/Lexer.kt index 6bf734d..6461458 100644 --- a/core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/internal/Lexer.kt +++ b/core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/internal/Lexer.kt @@ -45,8 +45,8 @@ import io.github.cybercodernaj.parkour.utils.Position */ class Lexer internal constructor( private val ignorePattern: Regex = Defaults.ignorePattern, - private val singleLineComments: Regex? = null, - private val multilineComments: Pair? = null, + private val singleLineComments: Regex? = Defaults.singleLineComments, + private val multilineComments: Pair? = Defaults.multilineComments, private val identifiers: Regex = Defaults.identifiers, private val hardKeywords: Set = emptySet(), private val operators: Set = emptySet(), @@ -72,6 +72,8 @@ class Lexer internal constructor( * @since 0.2.0 */ val ignorePattern = Regex("""\s+""") + val singleLineComments: Regex? = null + val multilineComments: Pair? = null val identifiers = Regex("""[a-zA-Z_]\w*""") val integerLiterals = Regex("""[-+]?[0-9_]+""") val floatingLiterals = Regex("""[-+]?[0-9_]*\.[0-9_]+(?:[eE][-+]?[0-9_]+)?""") diff --git a/core/src/test/kotlin/io/github/cybercodernaj/parkour/lexer/LexerBuilderTest.kt b/core/src/test/kotlin/io/github/cybercodernaj/parkour/lexer/LexerBuilderTest.kt index 424d8c3..9a7b5a8 100644 --- a/core/src/test/kotlin/io/github/cybercodernaj/parkour/lexer/LexerBuilderTest.kt +++ b/core/src/test/kotlin/io/github/cybercodernaj/parkour/lexer/LexerBuilderTest.kt @@ -27,5 +27,37 @@ class LexerBuilderTest { ) ) } + + @Test + fun `sets single line comments`() { + val myLexer = lexer { + singleLineComments(Regex("//")) + } + + myLexer.source = StringSource("hi // hello\nhru") + assertTokens( + myLexer, + listOf( + Token.Identifier("hi", Position(0, 0), Position(0, 1)), + Token.Identifier("hru", Position(1, 0), Position(1, 2)) + ) + ) + } + + @Test + fun `sets multiline comments`() { + val myLexer = lexer { + multiLineComments(Regex("/\\*") to Regex("\\*/")) + } + + myLexer.source = StringSource("hi /* hello */\nhru") + assertTokens( + myLexer, + listOf( + Token.Identifier("hi", Position(0, 0), Position(0, 1)), + Token.Identifier("hru", Position(1, 0), Position(1, 2)) + ) + ) + } } diff --git a/docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/escape-sequences.html b/docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/escape-sequences.html index fa0ee52..616d128 100644 --- a/docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/escape-sequences.html +++ b/docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/escape-sequences.html @@ -63,7 +63,7 @@

escapeSequences

- + + +
+
+
+ + +
Link copied to clipboard
+
+
+
+ +
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+ +
+
+
+
diff --git a/docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/integer-literals.html b/docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/integer-literals.html index d06b06c..9bb0b11 100644 --- a/docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/integer-literals.html +++ b/docs/core/io.github.cybercodernaj.parkour.lexer.internal/-lexer/-defaults/integer-literals.html @@ -63,7 +63,7 @@

integerLiterals

- +
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun multiLineComments(multilineComments: Pair<Regex, Regex>)

There are two parts to multilineComments: the starting and the ending pattern. When the lexer identifies the starting pattern, it will continue to skip to the next possible token until it meets the ending pattern.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun singleLineComments(singleLineComments: Regex)

When the lexer identifies a singleLineComments pattern, it will skip to the next line and return the next token.

+
+
+
+
diff --git a/docs/core/io.github.cybercodernaj.parkour.lexer/-lexer-builder/multi-line-comments.html b/docs/core/io.github.cybercodernaj.parkour.lexer/-lexer-builder/multi-line-comments.html new file mode 100644 index 0000000..c24a662 --- /dev/null +++ b/docs/core/io.github.cybercodernaj.parkour.lexer/-lexer-builder/multi-line-comments.html @@ -0,0 +1,76 @@ + + + + + multiLineComments + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

multiLineComments

+
+
fun multiLineComments(multilineComments: Pair<Regex, Regex>)(source)

There are two parts to multilineComments: the starting and the ending pattern. When the lexer identifies the starting pattern, it will continue to skip to the next possible token until it meets the ending pattern.

val myLexer = lexer {
// You don't need the square brackets but KDoc doesn't like it...
multiLineComments(Regex("[/][*]") to Regex("[*][/]"))
}

Author

Nishant Aanjaney Jalan

Since

0.2.0

Parameters

singleLineComments

regex of the pattern the lexer will skip over to the next line.

See also

+
+ +
+
+
+ + + diff --git a/docs/core/io.github.cybercodernaj.parkour.lexer/-lexer-builder/single-line-comments.html b/docs/core/io.github.cybercodernaj.parkour.lexer/-lexer-builder/single-line-comments.html new file mode 100644 index 0000000..59eff1b --- /dev/null +++ b/docs/core/io.github.cybercodernaj.parkour.lexer/-lexer-builder/single-line-comments.html @@ -0,0 +1,76 @@ + + + + + singleLineComments + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

singleLineComments

+
+
fun singleLineComments(singleLineComments: Regex)(source)

When the lexer identifies a singleLineComments pattern, it will skip to the next line and return the next token.

val myLexer = lexer {
singleLineComments(Regex("//"))
}

Author

Nishant Aanjaney Jalan

Since

0.2.0

Parameters

singleLineComments

regex of the pattern the lexer will skip over to the next line.

See also

+
+ +
+
+
+ + + diff --git a/docs/core/io.github.cybercodernaj.parkour.lexer/lexer.html b/docs/core/io.github.cybercodernaj.parkour.lexer/lexer.html index 3d03036..45e7e5d 100644 --- a/docs/core/io.github.cybercodernaj.parkour.lexer/lexer.html +++ b/docs/core/io.github.cybercodernaj.parkour.lexer/lexer.html @@ -63,7 +63,7 @@

lexer

-
fun lexer(init: LexerBuilder.() -> Unit): Lexer(source)

Build a lexer in a DSL. Accepts a function with LexerBuilder as a receiver and returns a lexer of that configuration.

Sample

val myLexer = lexer {
/* Add your lexer configuration here. */
}

Return

the configured Lexer to be used in the parser.

Author

Nishant Aanjaney Jalan

Since

0.2.0

Parameters

init

the execution block in context of LexerBuilder

See also

+
fun lexer(init: LexerBuilder.() -> Unit): Lexer(source)

Build a lexer in a DSL. Accepts a function with LexerBuilder as a receiver and returns a lexer of that configuration.

Sample

val myLexer = lexer {
/* Add your lexer configuration here. */
}

Return

the configured Lexer to be used in the parser.

Author

Nishant Aanjaney Jalan

Since

0.2.0

Parameters

init

the execution block in context of LexerBuilder

See also