From c95ff6e18836b64a87beef9aaace2cab0b1a3953 Mon Sep 17 00:00:00 2001 From: Louis Burke Date: Mon, 16 Sep 2024 12:53:44 -0400 Subject: [PATCH] Started adding DMs --- dictionary.nim | 6 +- dsl.nim | 480 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 336 insertions(+), 150 deletions(-) diff --git a/dictionary.nim b/dictionary.nim index 3566bc8..4042dac 100644 --- a/dictionary.nim +++ b/dictionary.nim @@ -1,4 +1,5 @@ import dsl +import std/tables # Tips: in python run # @@ -80,7 +81,7 @@ dictionary: # verb "be" penta "n x", "Pronouns": - extremes i="Fully proximal", u="Fully distal" + extremes(i="Fully proximal", u="Fully distal") i: pronoun "I/me" e: pronoun "this" @@ -88,6 +89,9 @@ dictionary: o: pronoun "it" u: pronoun "that" + icosapenta "n t x", "Tests": + ii: noun "foo" + # TODO: Consider hepta scales as well? how? when isMainModule: diff --git a/dsl.nim b/dsl.nim index 3dd3917..7f87a33 100644 --- a/dsl.nim +++ b/dsl.nim @@ -41,6 +41,7 @@ type Word* = ref object spelling*: string definitions*: Table[PartOfSpeech, Definition] + derivations*: seq[Derivation] Extremes* = object i*: Option[string] @@ -63,12 +64,21 @@ type first*: array[V, Penta] second*: array[V, Penta] + DerivationalMorphology* = ref object + spelling*: string + definitions*: Table[PartOfSpeech, Definition] + + Derivation* = ref object + root*: Word + dm*: DerivationalMorphology + Dictionary* = object glyphs*: seq[Glyph] dialects*: Table[string, seq[Replacement]] - words*: seq[Word] - pentas*: seq[Penta] - icosipentas*: seq[Icosapenta] + words*: Table[string, Word] + pentas*: Table[string, Penta] + icosapentas*: Table[string, Icosapenta] + dms*: Table[string, DerivationalMorphology] const Vowel2Char*: array[V, char] = [ @@ -94,166 +104,294 @@ macro makeposprocs(): untyped = for pos in PartOfSpeech: let w = ident("w") - let defns = ident("definitions") let name = ident(($pos).toLowerAscii) let vpos = pos.newLit result.add quote do: proc `name`(short: string) {.used.} = - `w`.`defns`[`vpos`] = Definition(brief: short, long: string.none) + `w`.definitions[`vpos`] = Definition(brief: short, long: string.none) proc `name`(short: string, long: string) {.used.} = - `w`.`defns`[`vpos`] = Definition(brief: short, long: long.some) + `w`.definitions[`vpos`] = Definition(brief: short, long: long.some) + +macro makepentaprocs(): untyped = + result = nnkStmtList.newNimNode + + for v in V: + let p = ident("p") + let name = ident("" & ($v).toLowerAscii[^1]) + let val = v.newLit + + result.add quote do: + template `name`(defns2: untyped) {.used.} = + edit_word `p`.elems[`val`]: defns2 + +macro make_icosaprocs(): untyped = + result = nnkStmtList.newNimNode + let ip = ident("ip") + + # -x and x- templates + for v in V: + let namex = ident(($v).toLowerAscii[^1] & "x") + let xname = ident("x" & ($v).toLowerAscii[^1]) + let val = v.newLit + + result.add quote do: + template `namex`(defns2: untyped) {.used.} = + edit_penta `ip`.first[`val`]: defns2 + template `xname`(defns2: untyped) {.used.} = + edit_penta `ip`.second[`val`]: defns2 + + # -- templates + for v1 in V: + for v2 in V: + let name = ident(($v1).toLowerAscii[^1] & ($v2).toLowerAscii[^1]) + let val1 = v1.newLit + let name2 = ident("" & ($v2).toLowerAscii[^1]) + + result.add quote do: + template `name`(defns2: untyped) {.used.} = + edit_penta(`ip`.first[`val1`]): + `name2`: defns2 + +template glyph_dsl(dict: var Dictionary, gbody: untyped) = + block: + proc vowel(spelling: string, attrs: varargs[GlyphAttribute]) = + var v: Glyph = Glyph(spelling: spelling, kind: Vowel) + for attr in attrs: + v.attrs.incl attr + dict.glyphs.add v + + proc cluster(spelling: string, attrs: varargs[GlyphAttribute]) = + var c: Glyph = Glyph(spelling: spelling, kind: Cluster) + for attr in attrs: + c.attrs.incl attr + dict.glyphs.add c + + proc punctuation(spelling: string, attrs: varargs[GlyphAttribute]) = + var p: Glyph = Glyph(spelling: spelling, kind: Punctuation) + for attr in attrs: + p.attrs.incl attr + dict.glyphs.add p + + proc numeric(spelling: string, attrs: varargs[GlyphAttribute]) = + var n: Glyph = Glyph(spelling: spelling, kind: Numeric) + for attr in attrs: + n.attrs.incl attr + dict.glyphs.add n + + proc syllables() = + var newglyphs: seq[Glyph] + for v in dict.glyphs: + if v.kind != Vowel: + continue + + for c in dict.glyphs: + if c.kind != Cluster: + continue + + newglyphs.add Glyph( + spelling: c.spelling & v.spelling, + kind: Syllable, + attrs: v.attrs + c.attrs + ) + + dict.glyphs.add newglyphs + + gbody + + +template dialect_dsl(dict: var Dictionary, name: string, dbody: untyped) = + block: + var dial: seq[Replacement] + proc replace(orig: string, by: string) = + dial.add Replacement(original: orig, replaced: by) + + dbody + + dict.dialects[name] = dial + + +template edit_word_dsl(theword: Word, defns: untyped) = + block: + var w {.inject.}: Word = theword + + makeposprocs() + + defns + +template edit_dm_dsl(thedm: DerivationalMorphology, defns: untyped) = + block: + var w {.inject.}: DerivationalMorphology = thedm + + makeposprocs() + + defns + +template words_dsl(dict: var Dictionary, wbody: untyped) = + block: + template edit_word(theword: Word, defns: untyped) = + edit_word_dsl(theword): + defns + + template word(ortho: string, defns: untyped) = + block: + var w {.inject.} = Word(spelling: ortho) + + proc via(root: string, dm: string) {.inject, used.} = + w.derivations.add Derivation(root: dict.words[root], dm: dict.dms[dm]) + + edit_word(w): defns + + dict.words[w.spelling] = w + + + template edit_penta(thepenta: Penta, defns: untyped) = + block: + var p {.inject.}: Penta = thepenta + + proc extremes(i {.inject.}: string, u {.inject.}: string) {.used.} = + p.exts.i = some(i) + p.exts.u = some(u) + + makepentaprocs() + + defns + + template penta(ortho: string, pname: string, defns: untyped) = + block: + var p {.inject.}: Penta = Penta( + spelling: ortho, + name: pname, + exts: Extremes(i: string.none, u: string.none) + ) + for v in V: + let spelling = ortho.replaceFirst(' ', Vowel2Char[v]) + if spelling in dict.words: + p.elems[v] = dict.words[spelling] + else: + word ortho.replaceFirst(' ', Vowel2Char[v]): + p.elems[v] = w + + edit_penta(p): defns + + dict.pentas[ortho] = p + + template edit_icosapenta(theicosa: Icosapenta, idefns: untyped) = + block: + var ip {.inject.}: Icosapenta = theicosa + + proc firsts(i {.inject.}: string, u {.inject.}: string) {.used.} = + ip.exts.first.i = some(i) + ip.exts.first.u = some(u) + + proc seconds(i {.inject.}: string, u {.inject.}: string) {.used.} = + ip.exts.second.i = some(i) + ip.exts.second.u = some(u) + + template ix(defns2: untyped) {.used.} = + edit_penta ip.first[V_I]: defns2 + + template ex(defns2: untyped) {.used.} = + edit_penta ip.first[V_E]: defns2 + + template ax(defns2: untyped) {.used.} = + edit_penta ip.first[V_A]: defns2 + + template ox(defns2: untyped) {.used.} = + edit_penta ip.first[V_O]: defns2 + + template ux(defns2: untyped) {.used.} = + edit_penta ip.first[V_U]: defns2 + + template xi(defns2: untyped) {.used.} = + edit_penta ip.second[V_I]: defns2 + + template xe(defns2: untyped) {.used.} = + edit_penta ip.second[V_E]: defns2 + + template xa(defns2: untyped) {.used.} = + edit_penta ip.second[V_A]: defns2 + + template xo(defns2: untyped) {.used.} = + edit_penta ip.second[V_O]: defns2 + + template xu(defns2: untyped) {.used.} = + edit_penta ip.second[V_U]: defns2 + + make_icosaprocs() + + # NOTE: first extremes is exts, second extremes is elems[*].exts + idefns + + + template icosapenta(iortho: string, iname: string, idefns: untyped) = + block: + var ip {.inject.}: Icosapenta = Icosapenta( + spelling: iortho, + name: iname, + exts: BiExtremes( + first: Extremes(i: string.none, u: string.none), + second: Extremes(i: string.none, u: string.none) + ) + ) + for v in V: + penta iortho.replaceFirst(' ', Vowel2Char[v]), Vowel2Char[v] & "x " & iname: + ip.first[v] = p + + penta iortho.replaceLast(' ', Vowel2Char[v]), "x" & Vowel2Char[v] & " " & iname: + ip.second[v] = p + + edit_icosapenta(ip): idefns + + dict.icosapentas[iortho] = ip + + template edit_dm(thedm: DerivationalMorphology, dmbody: untyped) = + edit_dm_dsl(thedm): + dmbody + + template dm(ortho: string, defns: untyped) = + block: + var w {.inject.} = DerivationalMorphology(spelling: ortho) + + edit_dm(w): defns + + dict.dms[ortho] = w + + wbody + + + + template dictionary*(body: untyped) = var dict {.inject.}: Dictionary dict.glyphs = @[] template glyphs(gbody: untyped) = - block: - proc vowel(spelling: string, attrs: varargs[GlyphAttribute]) = - var v: Glyph = Glyph(spelling: spelling, kind: Vowel) - for attr in attrs: - v.attrs.incl attr - dict.glyphs.add v - - proc cluster(spelling: string, attrs: varargs[GlyphAttribute]) = - var c: Glyph = Glyph(spelling: spelling, kind: Cluster) - for attr in attrs: - c.attrs.incl attr - dict.glyphs.add c - - proc punctuation(spelling: string, attrs: varargs[GlyphAttribute]) = - var p: Glyph = Glyph(spelling: spelling, kind: Punctuation) - for attr in attrs: - p.attrs.incl attr - dict.glyphs.add p - - proc numeric(spelling: string, attrs: varargs[GlyphAttribute]) = - var n: Glyph = Glyph(spelling: spelling, kind: Numeric) - for attr in attrs: - n.attrs.incl attr - dict.glyphs.add n - - proc syllables() = - var newglyphs: seq[Glyph] - for v in dict.glyphs: - if v.kind != Vowel: - continue - - for c in dict.glyphs: - if c.kind != Cluster: - continue - - newglyphs.add Glyph( - spelling: c.spelling & v.spelling, - kind: Syllable, - attrs: v.attrs + c.attrs - ) - - dict.glyphs.add newglyphs - + glyph_dsl(dict): gbody template dialect(name: string, dbody: untyped) = - block: - var dial: seq[Replacement] - proc replace(orig: string, by: string) = - dial.add Replacement(original: orig, replaced: by) - + dialect_dsl(dict, name): dbody - dict.dialects[name] = dial + # TODO: add a words: proc to create and return a dm, so that within words + # you can use it + # e.g. + # + # words: + # let foo = dm "example-": + # noun "does something to nouns" + # + # word "example1": + # noun "does something once to nouns" + # by "1" via foo + # # or maybe? + # foo["1"] template words(wbody: untyped) = - block: - template word(ortho: string, defns: untyped) = - block: - var w {.inject.} = Word(spelling: ortho) - - makeposprocs() - - defns - - dict.words.add w - - template edit_word(theword: Word, defns: untyped) = - block: - var w {.inject.}: Word = theword - - makeposprocs() - - defns - - template penta(ortho: string, pname: string, defns: untyped) = - block: - var p {.inject.}: Penta = Penta( - spelling: ortho, - name: pname, - exts: Extremes(i: string.none, u: string.none) - ) - for v in V: - word ortho.replaceFirst(' ', Vowel2Char[v]): - p.elems[v] = w - - proc extremes(i {.inject.}: string, u {.inject.}: string) {.used.} = - p.exts.i = some(i) - p.exts.u = some(u) - - template i(defns2: untyped) {.used.} = - edit_word p.elems[V_I]: defns2 - template e(defns2: untyped) {.used.} = - edit_word p.elems[V_E]: defns2 - template a(defns2: untyped) {.used.} = - edit_word p.elems[V_A]: defns2 - template o(defns2: untyped) {.used.} = - edit_word p.elems[V_O]: defns2 - template u(defns2: untyped) {.used.} = - edit_word p.elems[V_U]: defns2 - - defns - - dict.pentas.add p - - template icosipenta(iortho: string, iname: string, idefns: untyped) = - block: - var i {.inject.}: Icosapenta = Icosapenta( - spelling: iortho, - name: iname, - exts: BiExtremes( - first: Extremes(i: string.none, u: string.none), - second: Extremes(i: string.none, u: string.none) - ) - ) - for v in V: - penta iortho.replaceFirst(' ', Vowel2Char[v]), Vowel2Char[v] & "x " & iname: - i.first[v] = p - - penta iortho.replaceLast(' ', Vowel2Char[v]), "x" & Vowel2Char[v] & " " & iname: - i.second[v] = p - - proc firsts(i {.inject.}: string, u {.inject.}: string) {.used.} = - i.exts.first.i = some(i) - i.exts.first.u = some(u) - - proc seconds(i {.inject.}: string, u {.inject.}: string) {.used.} = - i.exts.second.i = some(i) - i.exts.second.u = some(u) - - template ix(defns2: untyped) {.used.} = - edit_penta i.first[V_I]: defns2 - - # TODO: rest of the -x and x-, plus write edit_penta - - template ii(defns2: untyped) {.used.} = - edit_word i.first[V_I].elems[V_I]: defns2 - # TODO: check that this also edits i.second[V_I].elems[V_I] - - # TODO: rest of the -- - - # NOTE: first extremes is exts, second extremes is elems[*].exts - - + words_dsl(dict): wbody body @@ -287,19 +425,45 @@ proc toJsonHook(exts: Extremes): JsonNode = result["u"] = newJString(exts.u.get) -proc toJson(penta: Penta, dict: Dictionary): JsonNode = +proc toJson(penta: Penta): JsonNode = result = newJObject() result["extremes"] = penta.exts.toJson result["name"] = newJString(penta.name) - # TODO: Consider looking up i/e/a/o/u in dict -proc toJson(pentas: seq[Penta], dict: Dictionary): JsonNode = +proc toJson(pentas: seq[Penta]): JsonNode = result = newJObject() for penta in pentas: - result[penta.spelling] = penta.toJson(dict) + result[penta.spelling] = penta.toJson + + +proc toJson(exts: BiExtremes): JsonNode = + result = newJObject() + + if exts.first.i.isSome: + result["ix"] = newJString(exts.first.i.get) + if exts.first.u.isSome: + result["ux"] = newJString(exts.first.u.get) + if exts.second.i.isSome: + result["xi"] = newJString(exts.second.i.get) + if exts.second.u.isSome: + result["xu"] = newJString(exts.second.u.get) + + +proc toJson(icosa: Icosapenta): JsonNode = + result = newJObject() + + result["extremes"] = icosa.exts.toJson + result["name"] = newJString(icosa.name) + + +proc toJson(icosas: seq[Icosapenta]): JsonNode = + result = newJObject() + + for icosa in icosas: + result[icosa.spelling] = icosa.toJson proc toJsonHook(dict: Dictionary): JsonNode = @@ -307,12 +471,18 @@ proc toJsonHook(dict: Dictionary): JsonNode = result["glyphs"] = dict.glyphs.toJson result["dialects"] = dict.dialects.toJson - result["words"] = dict.words.toJson - result["pentas"] = dict.pentas.toJson(dict) + result["words"] = dict.words.values.toSeq.toJson + result["pentas"] = dict.pentas.toJson + result["icosas"] = dict.icosapentas.toJson proc jsonify*(dict: Dictionary): string = return $(dict.toJson) +proc `$`*(word: Word): string = + if word.definitions.len > 0: + return word.spelling & "(" & word.definitions.pairs.toSeq.map(proc(p: (PartOfSpeech, Definition)): string = $p[0] & ":" & p[1].brief).join(",") & ")" + return word.spelling + when isMainModule: dictionary: glyphs: @@ -335,6 +505,9 @@ when isMainModule: replace "k", "g" words: + dm "foo-": + noun "fooish" + word "t": noun "thing", "See t - dmPenta for better meaning." # verb "be" @@ -344,4 +517,13 @@ when isMainModule: i: pronoun "I/me" + icosapenta "n t t", "Tests": + ii: verb "foo" + + word "foot": + noun "fooish thing" + + via("t", "foo-") + # "t".via "foo-" + echo dict.jsonify