import std/macros import std/tables import std/options import std/strutils type GlyphAttribute* = enum # Vowel Attributes outer, slashed, inner, # Cluster/Punctuation Attributes left, center, right, top, middle, bottom, tall, wide, both, # Numeric Attributes circle, dash, vee, hump, dot, GlyphKind* = enum Vowel, Cluster, Punctuation, Syllable, Numeric Glyph* = object spelling*: string kind*: GlyphKind attrs*: set[GlyphAttribute] Replacement* = object original*: string replaced*: string PartOfSpeech* = enum Noun, Pronoun, Verb, Adjective, Adverb, Syntactic Definition* = object brief*: string long*: Option[string] Word* = object spelling*: string definitions*: Table[PartOfSpeech, Definition] Extremes* = object i*: Option[string] u*: Option[string] Penta*[T] = object spelling*: string name*: string exts*: Extremes i*: ptr T e*: ptr T a*: ptr T o*: ptr T u*: ptr T Dictionary* = object glyphs*: seq[Glyph] dialects*: Table[string, seq[Replacement]] words*: seq[Word] pentas*: seq[Penta[Word]] proc replaceFirst(haystack: string, needle: char, content: char): string = let idx = haystack.find(needle) result = haystack result[idx] = content macro makeposprocs(): untyped = result = nnkStmtList.newNimNode 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) proc `name`(short: string, long: string) {.used.} = `w`.`defns`[`vpos`] = Definition(brief: short, long: long.some) 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 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) dbody dict.dialects[name] = dial template words(wbody: untyped) = block: template word(ortho: string, defns: untyped) = block: var w {.inject.}: Word = Word(spelling: ortho) makeposprocs() defns dict.words.add w template penta(ortho: string, pname: string, defns: untyped) = block: var p {.inject.}: Penta[Word] p.spelling = ortho proc extremes(i {.inject.}: string, u {.inject.}: string) {.used.} = p.exts.i = some(i) p.exts.u = some(u) template i(defns2: untyped) {.used.} = word ortho.replaceFirst(' ', 'i'): defns2; p.i = w.addr template e(defns2: untyped) {.used.} = word ortho.replaceFirst(' ', 'e'): defns2; p.e = w.addr template a(defns2: untyped) {.used.} = word ortho.replaceFirst(' ', 'a'): defns2; p.a = w.addr template o(defns2: untyped) {.used.} = word ortho.replaceFirst(' ', 'o'): defns2; p.o = w.addr template u(defns2: untyped) {.used.} = word ortho.replaceFirst(' ', 'u'): defns2; p.u = w.addr p.spelling = ortho p.name = pname defns dict.pentas.add p wbody # TODO: penta[X]s body proc toJSON*(dict: Dictionary): string = return $dict # TODO: stringify to JSON when isMainModule: dictionary: glyphs: vowel "i", outer vowel "y", both cluster "θ", left, top cluster "∫", left, middle syllables() punctuation "«", left numeric "0", circle dialect "jukashenikan": replace "x", "ç" dialect "gazhenigan": replace "k", "g" words: word "t": noun "thing", "See t - dmPenta for better meaning." # verb "be" penta "n x", "Pronouns": extremes(i="Fully proximal", u="Fully distal") i: pronoun "I/me" echo dict.toJSON