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

miksilo.modularLanguages.deltas.json.JsonObjectLiteralDelta.scala Maven / Gradle / Ivy

The newest version!
package miksilo.modularLanguages.deltas.json

import miksilo.modularLanguages.core.bigrammar.grammars.{Colorize, Delimiter, Keyword, Parse, RegexGrammar}
import miksilo.modularLanguages.core.deltas.grammars.LanguageGrammars
import miksilo.modularLanguages.core.deltas.path.NodePath
import miksilo.modularLanguages.core.deltas.{Delta, DeltaWithGrammar}
import miksilo.languageServer.core.language.exceptions.BadInputException
import miksilo.modularLanguages.core.node._
import miksilo.languageServer.core.language.{Compilation, Language}
import miksilo.editorParser.parsers.editorParsers.History
import miksilo.languageServer.core.smarts.ConstraintBuilder
import miksilo.languageServer.core.smarts.scopes.objects.Scope
import miksilo.languageServer.core.smarts.types.objects.Type
import miksilo.modularLanguages.deltas.expression.{ExpressionDelta, ExpressionInstance}
import miksilo.modularLanguages.deltas.json.JsonObjectLiteralDelta.ObjectLiteralMember
import miksilo.modularLanguages.deltas.json.JsonStringLiteralDelta.{dropPrefix, stringInnerRegex}

case class DuplicateObjectLiteralKeys(duplicates: Seq[String]) extends BadInputException

object JsonObjectLiteralDelta extends DeltaWithGrammar with ExpressionInstance with Delta {

  override def description: String = "Adds the JSON object literal to expressions"

  def neww(entries: Map[String, Node]): Node = Shape.create(Members -> entries.map(entry =>
    MemberShape.create(MemberKey -> entry._1, MemberValue -> entry._2)))

  override def transformGrammars(_grammars: LanguageGrammars, language: Language): Unit = {
    import _grammars._
    val grammars = _grammars

    val keyGrammar = {
      import miksilo.modularLanguages.core.bigrammar.DefaultBiGrammarWriter._
      val regexGrammar = RegexGrammar(stringInnerRegex, "object member key", verifyWhenPrinting = false, Some("\""))
      dropPrefix(grammars, regexGrammar, MemberKey, "\"") ~< "\""
    }
    val expressionGrammar = find(ExpressionDelta.FirstPrecedenceGrammar)

    val member = (Colorize(create(MemberKey, keyGrammar), "string.quoted.double") ~< ":") ~~ expressionGrammar.as(MemberValue) asNode MemberShape
    val optionalTrailingComma = Parse(Keyword(",") | value(()))
    val inner = Delimiter("{", History.missingInputPenalty * 2) %> (member.manySeparatedVertical(",").as(Members) ~< optionalTrailingComma).indent() %< "}"

    val grammar = inner.asLabelledNode(Shape)
    expressionGrammar.addAlternative(grammar)
  }

  object MemberShape extends TypedShape {
    type Typed[T <: NodeLike] = ObjectLiteralMember[T]

    override def neww[T <: NodeLike](value: T) = ObjectLiteralMember(value)

    override def toString = "Member"
  }

  object MemberKey extends NodeField {
    override def toString = "Key"
  }
  object MemberValue extends NodeField {
    override def toString = "Value"
  }

  object Members extends NodeField {
    override def toString = "Member"
  }

  object Shape extends TypedShape {
    type Typed[T <: NodeLike] = ObjectLiteral[T]

    override def neww[T <: NodeLike](value: T): ObjectLiteral[T] = ObjectLiteral(value)

    override def toString = "Object"
  }

  override def shape: NodeShape = Shape

  override def constraints(compilation: Compilation, builder: ConstraintBuilder, expression: NodePath, _type: Type, parentScope: Scope): Unit = {

  }

  implicit class ObjectLiteralMember[T <: NodeLike](val node: T) extends NodeWrapper[T] {
    def key: String = node.getValue(MemberKey).asInstanceOf[String]
    def value: T = node(MemberValue).asInstanceOf[T]
  }

  implicit class ObjectLiteral[T <: NodeLike](val node: T) extends NodeWrapper[T] {
    def getValue(key: String): T = get(key).get
    def getObject(key: String): Option[ObjectLiteral[T]] = get(key).
      flatMap(v => if (v.shape == Shape) Some(ObjectLiteral(v)) else None)

    def get(key: String): Option[T] = members.find(member => member.key == key).map(x => x.value)
    def members: Seq[ObjectLiteralMember[T]] = NodeWrapper.wrapList(node(Members).asInstanceOf[Seq[T]])
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy