packages feed

hydra-kernel-0.17.3: src/main/haskell/Hydra/Print/Pcre/Regex.hs

-- Note: this is an automatically generated file. Do not edit.

-- | Per-dialect printer rendering the hydra.regex AST into the PCRE / java.util.regex / ECMA family syntax (Java, Scala, Clojure, Python, Common Lisp, TypeScript). Differs from the canonical hydra.print.regex in exactly one place: Hydra's . (any character INCLUDING newline) renders as [\s\S] rather than a bare . (whose native meaning excludes newline in these engines). All other productions match the canonical form. See docs/specification/regex.md and issue #567.

module Hydra.Print.Pcre.Regex where

import qualified Hydra.Ast as Ast
import qualified Hydra.Coders as Coders
import qualified Hydra.Core as Core
import qualified Hydra.Docs as Docs
import qualified Hydra.Error.Checking as Checking
import qualified Hydra.Error.Core as ErrorCore
import qualified Hydra.Error.File as ErrorFile
import qualified Hydra.Error.Packaging as ErrorPackaging
import qualified Hydra.Error.System as ErrorSystem
import qualified Hydra.Errors as Errors
import qualified Hydra.File as File
import qualified Hydra.Graph as Graph
import qualified Hydra.Json.Model as Model
import qualified Hydra.Overlay.Haskell.Lib.Equality as Equality
import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
import qualified Hydra.Overlay.Haskell.Lib.Literals as Literals
import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
import qualified Hydra.Packaging as Packaging
import qualified Hydra.Parsing as Parsing
import qualified Hydra.Paths as Paths
import qualified Hydra.Query as Query
import qualified Hydra.Regex as Regex
import qualified Hydra.Relational as Relational
import qualified Hydra.System as System
import qualified Hydra.Tabular as Tabular
import qualified Hydra.Testing as Testing
import qualified Hydra.Time as Time
import qualified Hydra.Topology as Topology
import qualified Hydra.Typed as Typed
import qualified Hydra.Typing as Typing
import qualified Hydra.Util as Util
import qualified Hydra.Validation as Validation
import qualified Hydra.Variants as Variants
import Prelude hiding  (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
import qualified Data.Scientific as Sci

-- | Render an alternation, joining its branches with the | operator.
alternation :: [[Regex.Quantified]] -> String
alternation alt = Strings.join "|" (Lists.map regexSequence alt)

-- | Render a single atom; the . metacharacter renders as [\s\S] to preserve newline-inclusive 'any'.
atom :: Regex.Atom -> String
atom a =
    case a of
      Regex.AtomLiteral v0 -> escapeLiteral v0
      Regex.AtomAny -> "[\\s\\S]"
      Regex.AtomAnchorStart -> "^"
      Regex.AtomAnchorEnd -> "$"
      Regex.AtomGroup v0 -> Strings.concat [
        "(",
        (alternation v0),
        ")"]
      Regex.AtomClass v0 -> characterClass v0

-- | Render a character class, including the leading ^ for a negated class.
characterClass :: Regex.CharacterClass -> String
characterClass cc =
    Strings.concat [
      "[",
      (Logic.ifElse (Regex.characterClassNegated cc) "^" ""),
      (Strings.concat (Lists.map classItem (Regex.characterClassItems cc))),
      "]"]

-- | Render one character-class member (a single character or an inclusive range).
classItem :: Regex.ClassItem -> String
classItem item =
    case item of
      Regex.ClassItemCharacter v0 -> escapeClassChar v0
      Regex.ClassItemRange v0 -> Strings.concat [
        escapeClassChar (Regex.characterRangeFrom v0),
        "-",
        (escapeClassChar (Regex.characterRangeTo v0))]

-- | Render a code point inside a character class, uniformly escaping the class metacharacters \ ] ^ -.
escapeClassChar :: Int -> String
escapeClassChar c =

      let isMeta =
              Lists.foldl (\acc -> \m -> Logic.or acc (Equality.equal c m)) False [
                92,
                93,
                94,
                45]
      in (Logic.ifElse isMeta (Strings.concat2 "\\" (showCodePoint c)) (showCodePoint c))

-- | Render a literal code point in top-level context, backslash-escaping PCRE/ECMA metacharacters.
escapeLiteral :: Int -> String
escapeLiteral c =

      let isMeta =
              Lists.foldl (\acc -> \m -> Logic.or acc (Equality.equal c m)) False [
                46,
                94,
                36,
                42,
                43,
                63,
                40,
                41,
                91,
                93,
                123,
                125,
                124,
                92]
      in (Logic.ifElse isMeta (Strings.concat2 "\\" (showCodePoint c)) (showCodePoint c))

-- | Render a hydra.regex AST into PCRE / java.util.regex / ECMA syntax. Identical to the canonical printer except that . (any incl. newline) becomes [\s\S].
printRegex :: [[Regex.Quantified]] -> String
printRegex r = alternation r

-- | Render an atom followed by its quantifier suffix.
quantified :: Regex.Quantified -> String
quantified qa = Strings.concat2 (atom (Regex.quantifiedAtom qa)) (quantifier (Regex.quantifiedQuantifier qa))

-- | Render a quantifier suffix; the 'one' quantifier renders as the empty string.
quantifier :: Regex.Quantifier -> String
quantifier q =
    case q of
      Regex.QuantifierOne -> ""
      Regex.QuantifierZeroOrOne -> "?"
      Regex.QuantifierZeroOrMore -> "*"
      Regex.QuantifierOneOrMore -> "+"
      Regex.QuantifierExactly v0 -> Strings.concat [
        "{",
        (Literals.showInt32 v0),
        "}"]
      Regex.QuantifierAtLeast v0 -> Strings.concat [
        "{",
        (Literals.showInt32 v0),
        ",}"]
      Regex.QuantifierRange_ v0 -> Strings.concat [
        "{",
        (Literals.showInt32 (Regex.quantifierRangeMin v0)),
        ",",
        (Literals.showInt32 (Regex.quantifierRangeMax v0)),
        "}"]

-- | Render a sequence of quantified atoms by concatenation.
regexSequence :: [Regex.Quantified] -> String
regexSequence s = Strings.concat (Lists.map quantified s)

-- | Render a single Unicode code point as a one-character string.
showCodePoint :: Int -> String
showCodePoint c = Strings.fromList [
  c]