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

izumi.idealingua.il.parser.DefStructure.scala Maven / Gradle / Ivy

The newest version!
package izumi.idealingua.il.parser

import izumi.idealingua.il.parser.structure.syntax.Literals
import izumi.idealingua.il.parser.structure.{Separators, aggregates, ids, kw}
import izumi.idealingua.model.il.ast.raw.defns
import izumi.idealingua.model.il.ast.raw.defns.RawAdt.Member
import izumi.idealingua.model.il.ast.raw.defns.RawEnum.EnumOp
import izumi.idealingua.model.il.ast.raw.defns.RawStructure.StructOp
import izumi.idealingua.model.il.ast.raw.defns.RawTopLevelDefn.{TLDDeclared, TLDNewtype}
import izumi.idealingua.model.il.ast.raw.defns.RawTypeDef._
import izumi.idealingua.model.il.ast.raw.defns._
import izumi.idealingua.model.il.ast.raw.domains.ImportedId
import izumi.idealingua.model.il.ast.raw.typeid.ParsedId
import fastparse.NoWhitespace._
import fastparse._

class DefStructure(context: IDLParserContext) extends Separators {

  import context._

  def field[$: P]: P[RawField] = P(metaAgg.withMeta((ids.symbol | P("_" | "").map(_ => "")) ~ inline ~ ":" ~/ inline ~ ids.idGeneric))
    .map {
      case (meta, (name, tpe)) if name.isEmpty =>
        defns.RawField(tpe, None, meta)

      case (meta, (name, tpe)) =>
        defns.RawField(tpe, Some(name), meta)
    }

  object Struct {
    def plus[$: P]: P[StructOp.Extend] = P(("&" ~ "&&".?) ~/ (inline ~ ids.identifier)).map(_.toParentId).map(StructOp.Extend.apply)

    def embed[$: P]: P[StructOp.Mix] = P((("+" ~ "++".?) | "...") ~/ (inline ~ ids.identifier)).map(_.toMixinId).map(StructOp.Mix.apply)

    def minus[$: P]: P[StructOp] = P(("-" ~ "--".?) ~/ (inline ~ (field | ids.identifier))).map {
      id =>
        (id: @unchecked) match {
          case v: RawField =>
            StructOp.RemoveField(v)
          case i: ParsedId =>
            StructOp.Drop(i.toMixinId)
        }
    }

    def plusField[$: P]: P[StructOp.AddField] = field.map(StructOp.AddField.apply)

    def anyPart[$: P]: P[StructOp] = P(plusField | plus | embed | minus)

    def struct[$: P]: P[RawStructure.Aux] = {

      P((inline ~ anyPart ~ inline).rep(sep = sepStruct))
        .map(RawStructure.Aux.apply)
    }
  }

  object SimpleStruct {
    def embed[$: P]: P[StructOp.Mix] = P((("+" ~ "++".?) | "...") ~/ (any ~ ids.identifier)).map(_.toMixinId).map(StructOp.Mix.apply)

    def plusField[$: P]: P[StructOp.AddField] = field.map(StructOp.AddField.apply)

    def anyPart[$: P]: P[StructOp] = P(plusField | embed)

    def sepInlineStruct[$: P]: P[Unit] = any ~ ",".? ~ any

    def simpleStruct[$: P]: P[RawSimpleStructure] = {
      P((any ~ anyPart ~ any).rep(sep = sepInlineStruct) ~ sepInlineStruct.?)
        .map(RawStructure.Aux.apply)
        .map(s => RawSimpleStructure(s.structure.concepts, s.structure.fields))
    }

  }

  def inlineStruct[$: P]: P[RawSimpleStructure] = aggregates.enclosed(SimpleStruct.simpleStruct)

  def adtOut[$: P]: P[RawAdt] = aggregates.enclosed(adt(sepAdtFreeForm))

  def aggregate[$: P]: P[Seq[RawField]] = P((inline ~ field ~ inline)
    .rep(sep = sepStruct))

  def nestedAdtMember[$: P]: P[Member.NestedDefn] = P(defMember.baseTypeMember)
    .map {
      m =>
        Member.NestedDefn(m.v)
    }


  def adtMember[$: P]: P[Member.TypeRef] = P(metaAgg.withMeta(ids.identifier ~ (inline ~ "as" ~/ (inline ~ ids.symbol)).?))
    .map {
      case (meta, (tpe, alias)) =>
        Member.TypeRef(tpe.toIndefinite, alias, meta)
    }

  def importMember[$: P]: P[ImportedId] = P(ids.symbol ~ (inline ~ "as" ~/ (inline ~ ids.symbol)).?).map {
    case (tpe, alias) =>
      ImportedId(tpe, alias)
  }

  def adt[$: P](sep: => P[Unit]): P[RawAdt] = P((nestedAdtMember | adtMember).rep(min = 1, sep = sep))
    .map(_.toList).map(RawAdt.apply)

  object Enum {
    def embed[$: P]: P[EnumOp.Extend] = P((("+" ~ "++".?) | "...") ~/ (inline ~ ids.identifier)).map(_.toEnumId).map(EnumOp.Extend.apply)

    def enumMember[$: P]: P[EnumOp.AddMember] = P(metaAgg.withMeta(ids.symbol ~ (inline ~ "=" ~/ inline ~ defConst.constValue).?)).map {
      case (meta, (name, const)) =>
        EnumOp.AddMember(RawEnumMember(name, const.map(_.value), meta))
    }

    def minus[$: P]: P[EnumOp.RemoveMember] = P(("-" ~ "--".?) ~/ (inline ~ ids.symbol)).map(EnumOp.RemoveMember.apply)

    def anyPart[$: P]: P[EnumOp] = P(enumMember | minus | embed)

    def `enum`[$: P](sep: => P[Unit]): P[RawEnum] = P(anyPart.rep(min = 1, sep = sep)).map(RawEnum.Aux.apply).map(_.structure)
  }

  def imports[$: P](sep: => P[Unit]): P[Seq[ImportedId]] = P(importMember.rep(min = 1, sep = sep))

  def mixinBlock[$: P]: P[Interface] = P(metaAgg.cblock(kw.mixin, Struct.struct)).map {
    case (c, i, v) => v.toInterface(i.toInterfaceId, c)
  }

  def dtoBlock[$: P]: P[DTO] = P(metaAgg.cblock(kw.data, Struct.struct))
    .map {
      case (c, i, v) => v.toDto(i.toDataId, c)
    }

  def stringPair[$: P]: P[(String, InterpContext)] = P(Literals.Literals.Str ~ any ~ ":" ~ any ~ ids.typeInterp)

  def foreignLinks[$: P]: P[Map[String, InterpContext]] = P(aggregates.enclosed(stringPair.rep(min = 1, sep = sepEnum))).map(_.toMap)

  def foreignBlock[$: P]: P[RawTopLevelDefn.TLDForeignType] = P(metaAgg.withMeta(kw(kw.foreign, ids.idGeneric ~ inline ~ foreignLinks)))
    .map {
      case (meta, (i, v)) =>
        ForeignType(i, v, meta)
    }
    .map(RawTopLevelDefn.TLDForeignType.apply)

  def idBlock[$: P]: P[Identifier] = P(metaAgg.cblock(kw.id, aggregate))
    .map {
      case (c, i, v) => Identifier(i.toIdId, v.toList, c)
    }

  def aliasBlock[$: P]: P[Alias] = P(metaAgg.cstarting(kw.alias, "=" ~/ (inline ~ ids.identifier)))
    .map {
      case (c, i, v) => Alias(i.toAliasId, v.toIndefinite, c)
    }

  def declaredBlock[$: P]: P[TLDDeclared] = P(metaAgg.cstarting(kw.declared, inline))
    .map {
      case (meta, id, _) =>
        TLDDeclared(DeclaredType(id.toIndefinite, meta))
  }

  def cloneBlock[$: P]: P[TLDNewtype] = P(metaAgg.cstarting(kw.newtype, "into" ~/ (inline ~ ids.idShort ~ inline ~ aggregates.enclosed(Struct.struct).?)))
    .map {
      case (c, src, (target, struct)) =>
        NewType(target, src.toIndefinite, struct.map(_.structure), c)
    }
    .map(TLDNewtype.apply)

  def adtFreeForm[$: P]: P[RawAdt] = P(any ~ "=" ~/ any ~ sepAdtFreeForm.? ~ any ~ adt(sepAdtFreeForm))

  def adtEnclosed[$: P]: P[RawAdt] = P(NoCut(aggregates.enclosed(adt(sepAdt) ~ sepAdt.?)) | aggregates.enclosed(adt(sepAdtFreeForm)))

  def adtBlock[$: P]: P[Adt] = P(metaAgg.cstarting(kw.adt, adtEnclosed | adtFreeForm))
    .map {
      case (c, i, v) =>
        Adt(i.toAdtId, v.alternatives, c)
    }

  def enumFreeForm[$: P]: P[RawEnum] = P(any ~ "=" ~/ any ~ sepEnumFreeForm.? ~ any ~ Enum.`enum`(sepEnumFreeForm))

  def enumEnclosed[$: P]: P[RawEnum] = P(NoCut(aggregates.enclosed(Enum.`enum`(sepEnum) ~ sepEnum.?)) | aggregates.enclosed(Enum.`enum`(sepEnumFreeForm)))


  def enumBlock[$: P]: P[Enumeration] = P(metaAgg.cstarting(kw.`enum`, enumEnclosed | enumFreeForm))
    .map {
      case (c, i, v) =>
        Enumeration(i.toEnumId, v, c)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy