From 2fc56837d0addc6a32757bd4c0b08258f36319f7 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Fri, 15 Mar 2024 13:39:37 -0700 Subject: [PATCH 1/2] Support comments in headers --- core/src/main/scala/org/bykn/bosatsu/Package.scala | 12 ++++++++---- core/src/main/scala/org/bykn/bosatsu/Padding.scala | 6 ++++-- core/src/main/scala/org/bykn/bosatsu/Parser.scala | 6 +++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/core/src/main/scala/org/bykn/bosatsu/Package.scala b/core/src/main/scala/org/bykn/bosatsu/Package.scala index 3d1285c36..0e27081a3 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Package.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Package.scala @@ -191,11 +191,14 @@ object Package { } def headerParser(defaultPack: Option[PackageName]): P0[Header] = { - // TODO: support comments before the Statement + val spaceComment: P0[Unit] = + (Parser.spaces | (P.char('#') <* P.charsWhile0(_ != '\n'))).?.void + val eol = Parser.commentToEOL.void | Parser.toEOL val parsePack = Padding .parser( (P.string("package") - .soft ~ spaces) *> PackageName.parser <* Parser.toEOL + .soft ~ spaces) *> PackageName.parser <* eol, + spaceComment ) .map(_.padded) val pname: P0[PackageName] = @@ -204,12 +207,13 @@ object Package { case Some(p) => parsePack.?.map(_.getOrElse(p)) } - val im = Padding.parser(Import.parser <* Parser.toEOL).map(_.padded).rep0 + val im = Padding.parser(Import.parser <* eol, spaceComment).map(_.padded).rep0 val ex = Padding .parser( (P.string("export") .soft ~ spaces) *> ExportedName.parser.itemsMaybeParens - .map(_._2) <* Parser.toEOL + .map(_._2) <* eol, + spaceComment ) .map(_.padded) diff --git a/core/src/main/scala/org/bykn/bosatsu/Padding.scala b/core/src/main/scala/org/bykn/bosatsu/Padding.scala index f9286d121..231dbc061 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Padding.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Padding.scala @@ -22,13 +22,15 @@ object Padding { /** This allows an empty padding */ - def parser[T](p: P[T]): P[Padding[T]] = { - val spacing = (maybeSpace.with1.soft ~ Parser.newline).void.rep0 + def parser[T](p: P[T], space: P0[Unit]): P[Padding[T]] = { + val spacing = (space.with1.soft ~ Parser.newline).void.rep0 (spacing.with1.soft ~ p) .map { case (vec, t) => Padding(vec.size, t) } } + def parser[T](p: P[T]): P[Padding[T]] = parser(p, maybeSpace) + /** Parses a padding of length 1 or more, then p */ def parser1[T](p: P0[T]): P[Padding[T]] = diff --git a/core/src/main/scala/org/bykn/bosatsu/Parser.scala b/core/src/main/scala/org/bykn/bosatsu/Parser.scala index 89c9db043..f93731ffb 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Parser.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Parser.scala @@ -448,7 +448,11 @@ object Parser { (P.char('(') ~ ws) *> pa <* (ws ~ P.char(')')) val newline: P[Unit] = P.char('\n') - val toEOL: P0[Unit] = maybeSpace *> newline.orElse(P.end) + // The comment excluding the leading # up to the EOL or EOF + val termination: P0[Unit] = newline.orElse(P.end) + val commentToEOL: P[String] = + P.char('#') *> P.charsWhile0(_ != '\n') <* termination + val toEOL: P0[Unit] = maybeSpace *> termination val toEOL1: P[Unit] = maybeSpace.with1 *> newline def optionParse[A](pa: P0[A], str: String): Option[A] = From 6e9219aec4270a5261d1bde1df26f64683e86e23 Mon Sep 17 00:00:00 2001 From: Patrick Oscar Boykin Date: Fri, 15 Mar 2024 14:40:54 -1000 Subject: [PATCH 2/2] share more code --- core/src/main/scala/org/bykn/bosatsu/CommentStatement.scala | 4 ++-- core/src/main/scala/org/bykn/bosatsu/Package.scala | 6 ++++-- core/src/main/scala/org/bykn/bosatsu/Parser.scala | 3 --- core/src/test/scala/org/bykn/bosatsu/ParserTest.scala | 5 ++++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/core/src/main/scala/org/bykn/bosatsu/CommentStatement.scala b/core/src/main/scala/org/bykn/bosatsu/CommentStatement.scala index 042acdd98..d5adc46be 100644 --- a/core/src/main/scala/org/bykn/bosatsu/CommentStatement.scala +++ b/core/src/main/scala/org/bykn/bosatsu/CommentStatement.scala @@ -31,12 +31,12 @@ object CommentStatement { val commentBlock: P[NonEmptyList[String]] = // if the next line is part of the comment until we see the # or not (Parser.maybeSpace.with1.soft *> commentPart) - .repSep(sep = sep) <* Parser.newline.orElse(P.end) + .repSep(sep = sep) <* Parser.termination (commentBlock ~ onP(indent)) .map { case (m, on) => CommentStatement(m, on) } } val commentPart: P[String] = - P.char('#') *> P.until0(P.char('\n')) + P.char('#') *> P.until0(Parser.termination) } diff --git a/core/src/main/scala/org/bykn/bosatsu/Package.scala b/core/src/main/scala/org/bykn/bosatsu/Package.scala index 0e27081a3..5ed481ff1 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Package.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Package.scala @@ -190,10 +190,12 @@ object Package { Doc.intercalate(Doc.empty, p :: i :: e :: b) } + def headerParser(defaultPack: Option[PackageName]): P0[Header] = { val spaceComment: P0[Unit] = - (Parser.spaces | (P.char('#') <* P.charsWhile0(_ != '\n'))).?.void - val eol = Parser.commentToEOL.void | Parser.toEOL + (Parser.spaces.? ~ CommentStatement.commentPart.?).void + + val eol = spaceComment <* Parser.termination val parsePack = Padding .parser( (P.string("package") diff --git a/core/src/main/scala/org/bykn/bosatsu/Parser.scala b/core/src/main/scala/org/bykn/bosatsu/Parser.scala index f93731ffb..3bb3e3a7e 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Parser.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Parser.scala @@ -448,10 +448,7 @@ object Parser { (P.char('(') ~ ws) *> pa <* (ws ~ P.char(')')) val newline: P[Unit] = P.char('\n') - // The comment excluding the leading # up to the EOL or EOF val termination: P0[Unit] = newline.orElse(P.end) - val commentToEOL: P[String] = - P.char('#') *> P.charsWhile0(_ != '\n') <* termination val toEOL: P0[Unit] = maybeSpace *> termination val toEOL1: P[Unit] = maybeSpace.with1 *> newline diff --git a/core/src/test/scala/org/bykn/bosatsu/ParserTest.scala b/core/src/test/scala/org/bykn/bosatsu/ParserTest.scala index 4d1929f5d..4f0507613 100644 --- a/core/src/test/scala/org/bykn/bosatsu/ParserTest.scala +++ b/core/src/test/scala/org/bykn/bosatsu/ParserTest.scala @@ -1722,9 +1722,12 @@ external def foo2(i: Integer, b: a) -> String roundTrip( Package.parser(None), """ +# we can comment the package package Foo/Bar +# comments are allowed from Baz import Bippy -export foo +# even here +export foo # or here foo = 1 """