All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalaParser.Core.scala Maven / Gradle / Ivy

The newest version!
package scalaParser
import acyclic.file
import org.parboiled2._

import scala.language.implicitConversions


abstract class Core extends Parser
                       with syntax.Basic
                       with syntax.Literals
                       with syntax.Identifiers
                       with RulesOps
                       with Switches
                       with Settings {

  // Aliases for common things. These things are used in almost every parser
  // in the file, so it makes sense to keep them short.
  type R0 = Rule0
  /**
   * Parses all whitespace, excluding newlines. This is only
   * really useful in e.g. {} blocks, where we want to avoid
   * capturing newlines so semicolon-inference would work
   */

  def WSOneR0      : R0 = rule (Basic.WSChar | Literals.CommentR0)

  def WSOneOrMoreR0: R0 = rule (WSOneR0+)
  def WSR0         : R0 = rule (WSOneR0*)
  def WS           : R1 = rule( capture(WSR0) )

  /**
   * Parses whitespace, including newlines.
   * This is the default for most things
   */
  def WLOneR0      : R0 = rule( Basic.WSChar | Literals.CommentR0 | Basic.Newline     )

  def WLOneOrMoreR0: R0 = rule( WLOneR0+      )
  def WLR0         : R0 = rule( WLOneR0*      )
  def WL           : R1 = rule( capture(WLR0) )


  /**
   * By default, all strings and characters greedily
   * capture all whitespace immediately before the token.
   */
  private implicit def wspStr(s: String): R1 = rule( WL ~ capture(str(s)) ~> Concat )
  private implicit def wspCh (s: Char  ): R1 = rule( WL ~ capture(ch (s)) ~> Concat )
  /**
   * Most keywords don't just require the correct characters to match,
   * they have to ensure that subsequent characters *don't* match in
   * order for it to be a keyword. This enforces that rule for key-words
   * (W) and key-operators (O) which have different non-match criteria.
   */
  object KeyWordOperators {
    def WR0(s: String): Rule0 = rule( WLR0 ~ Key.W(s) )

    // def W(s: String): R1 = rule( WL ~ capture(Key.W(s)) ~> Concat )
    def W(s: String): R1 = rule( capture(WR0(s)) )
    def O(s: String): R1 = rule( WL ~ capture(Key.O(s)) ~> Concat )
  }
  import KeyWordOperators._
  // R0 versions of certain keywords
  def `withR0` = WR0("with")

  // Keywords that match themselves and nothing else
  def `=>` = rule( O("=>") | O("⇒") )
  def `<-` = rule( O("<-") | O("←") )
  def `:` = O(":")
  def `=` = O("=")
  def `@` = O("@")
  def `_` = W("_")
  def `this` = W("this")
  def `type` = W("type")
  def `val` = W("val")
  def `var` = W("var")
  def `def` = W("def")
  def `with` = W("with")
  def `package` = W("package")
  def `object` = W("object")
  def `class` = W("class")
  def `case` = W("case")
  def `trait` = W("trait")
  def `extends` = W("extends")
  def `implicit` = W("implicit")
  def `try` = W("try")
  def `new` = W("new")
  def `macro` = W("macro")
  def `import` = W("import")
  def `else` = W("else")
  def `super` = W("super")
  def `catch` = W("catch")
  def `finally` = W("finally")
  def `do` = W("do")
  def `yield` = W("yield")
  def `while` = W("while")
  def `<%` = O("<%")
  def `override` = W("override")
  def `#` = O("#")
  def `forSome` = W("forSome")
  def `for` = W("for")
  def `abstract` = W("abstract")
  def `throw` = W("throw")
  def `return` = W("return")
  def `lazy` = W("lazy")
  def `if` = W("if")
  def `match` = W("match")
  def `>:` = O(">:")
  def `<:` = O("<:")
  def `final` =  W("final")
  def `sealed` = W("sealed")
  def `private` = W("private")
  def `protected` = W("protected")

  // SubScript
  def `then` = W("then")

  // kinda-sorta keywords that are common patterns even if not
  // really-truly keywords
  def `_*`: R1 = rule( `_` ~ "*" ~> Concat )
  def `}` : R1 = rule( Semis.? ~> ExtractOpt ~ '}' ~> Concat )
  def `{` : R1 = rule( '{' ~ (Semis.? ~> ExtractOpt) ~> Concat )
  /**
   * helper printing function
   */
  def pr(s: String) = rule( run(println(s"LOGGING $cursor: $s")) )

  def SemiR0 : R0 = rule( WSR0 ~ Basic.Semi )
  def SemisR0: R0 = rule( SemiR0.+ )

  def SSKeyword: R1

  object IdBank extends ScopeBank[String] {
    import ScopeSwitch._

    def StandardId = rule ( WL ~ capture(Identifiers.Id) ~> Concat )

    def Forbidden(rle: () => Rule1[_]): R1 = rule {!(rle()) ~ StandardId}

    def NormalInScriptTerminator = rule(
      SSKeyword
    | "*}"  
    | "?}"  
    | "!}"  
    | ".}"  
    | "...}"
    | ">>"
    | "==>"
    )

    def LaunchAnchorTerminator = rule (SSKeyword | "**]")
    def LaunchTerminator       = rule (SSKeyword | "*]")

    def ruleMap = Map(
      NORMAL           -> {() => StandardId}
    , NORMAL_IN_SCRIPT -> {() => Forbidden {() => NormalInScriptTerminator}}
    , LAUNCH_ANCHOR    -> {() => Forbidden {() => LaunchAnchorTerminator}}
    , LAUNCH           -> {() => Forbidden {() => LaunchTerminator}}
    , PATTERN          -> NORMAL_IN_SCRIPT
    )
  }
  def Id     : R1 = IdBank().apply()

  def VarId  : R1 = rule( WL ~ capture(Identifiers.VarId) ~> Concat )
  def Literal: R1 = rule( WL ~ Literals.Literal           ~> Concat )
  // def Semi   : R1 = rule( WS ~ capture(Basic.Semi)        ~> Concat )
  // def Semis  : R1 = rule( Semi.+                          ~> ConcatSeqNoDelim )
  def Semi   : R1 = rule( capture(SemiR0 ) )
  def Semis  : R1 = rule( capture(SemisR0) )   
  def Newline: R1 = rule( WL ~ capture(Basic.Newline)     ~> Concat )

  def QualId: R1 = rule( WL ~ OneOrMore(() => Id, () => '.') ~> Concat )
  def Ids   : R1 = rule( OneOrMore(() => Id, () => ',') )

  def NotNewline: R1 = rule( capture(&( WS ~ !Basic.Newline )) )
  def OneNLMax: R1 = {
    def WSChar: R1 = rule( capture(Basic.WSChar.*) )
    def ConsumeComments: R1 = rule( (WSChar ~ Literals.Comment ~ WSChar ~ capture(Basic.Newline) ~> Concat4).* ~> ConcatSeqNoDelim )
    rule( WS ~ capture(Basic.Newline.?) ~ ConsumeComments ~ NotNewline ~> Concat4 )
  }

  def StableId: R1 = {
    def ClassQualifier: R1 = rule( '[' ~ Id ~ ']' ~> Concat3 )
    def ThisSuper     : R1 = rule( `this` | `super` ~ (ClassQualifier.? ~> ExtractOpt) ~> Concat )
    
    object PathDelimiterBank extends ScopeBank[String] {
      import ScopeSwitch._

      override val default = SCRIPT

      def ruleMap = Map(
        NORMAL -> {() => rule           ('.')                   }
      , SCRIPT -> {() => rule(capture(ch('.')) ~ !WLOneOrMoreR0)}

      , NORMAL_IN_SCRIPT -> NORMAL
      , ASSIGNMENT       -> NORMAL
      , PATTERN          -> NORMAL
      )
    }
    def PathDelimiter   = PathDelimiterBank().apply()

    def IdsTail         = rule { (PathDelimiter ~ Id ~> Concat).* ~> ConcatSeqNoDelim }
    def ThisSuperTailed = rule { ThisSuper ~ IdsTail    ~> Concat           }

    rule(
        (Id ~ PathDelimiter ~> Concat).* ~> ConcatSeqNoDelim ~ ThisSuperTailed ~> Concat
      | Id ~ IdsTail ~> Concat
    )
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy