thy

pseudo-elizabethan context-free grammar
git clone git@git.kloet.net/thy.git
Download | Log | Files | Refs | LICENSE

thy.c (9359B)


      1 /* See LICENSE file for copyright and license details.
      2  *
      3  * thy: a pseudo-elizabethan context-free grammar
      4  * This program constructs fragments using a "Mad Libs"-like text engine.
      5  */
      6 #include <stdarg.h>
      7 #include <stdlib.h>
      8 #include <time.h>
      9 #include <unistd.h>
     10 
     11 #define W(s, l) do { if (write(1, s, l)) {} } while (0)
     12 
     13 void
     14 tiny_printf(const char *fmt, ...) {
     15 	va_list args;
     16 	va_start(args, fmt);
     17 
     18 	while (*fmt) {
     19 	    if (*fmt == '%' && *(fmt + 1) == 's') {
     20 		const char *s = va_arg(args, const char *);
     21 		if (s) {
     22 		    int len = 0;
     23 		    while (s[len]) len++;
     24 		    W(s, len);
     25 		}
     26 		fmt += 2;
     27 	    } else {
     28 		W(fmt++, 1);
     29 	    }
     30 	}
     31 	va_end(args);
     32 }
     33 
     34 const char *Noun[] = {
     35     "mirror", "furnace", "skeleton", "biscuit", "mountain", "delusion",
     36     "microcosm", "jelly", "ocean", "truth", "science", "product", "insect",
     37     "tyranny", "creature", "theory", "life", "beast", "breast", "hope", "gland",
     38     "convexity", "concavity", "doom", "season", "corrosion", "passion", "fate",
     39     "vessel", "pain", "chemical", "mandible", "ray", "spirit", "feeling",
     40     "radiance", "dirt", "vacuum", "art", "homunculus", "engine", "text",
     41     "wheel", "vent", "lard", "memory", "apparel", "domicile", "behavior",
     42     "government", "sound", "prison", "being", "sustenance", "death", "worm",
     43     "stone", "color", "crystal", "gastropod", "flesh", "fire"
     44 };
     45 const char *Verb1[] = {
     46     "indulge", "lament", "caress", "exalt", "destroy", "avenge", "batter",
     47     "stretch", "deceive", "shun", "manifest", "witness", "actualize", "embrace",
     48     "levitate", "pardon", "sniff", "banish", "falsify", "pilot", "hark",
     49     "consider", "render", "forget", "remember", "approach", "castigate",
     50     "liquify", "debase", "sing", "hydrate", "chill", "rescue", "hoist",
     51     "extrude", "desire", "impede", "thrum", "suffer", "texturize", "bungle",
     52     "dance", "beat", "bleed", "soak", "work", "calm", "tether", "blast",
     53     "digest", "smear", "rock", "roll", "sustain", "gather", "exhume",
     54     "rehydrate", "prepare", "purify"
     55 };
     56 const char *Verb2[] = {
     57     "yearns for", "is like", "appears as", "reveals", "extracts", "is"
     58 };
     59 const char *Adj[] = {
     60     "mortal", "shining", "joyful", "austere", "melancholy", "small", "lordly",
     61     "massive", "effulgent", "wandering", "gentle", "weaponized", "sentimental",
     62     "correct", "motile", "youthful", "incomplete", "haughty", "furtive",
     63     "vital", "offending", "pungent", "shriveled", "noisome", "hallowed",
     64     "flabby", "zesty", "mechanized", "little", "burning", "fatal", "elusive",
     65     "merry", "plastic", "juicy", "televised", "sphere-like", "modified",
     66     "augmented", "noble", "pneumatic", "hylic", "psychic", "bad", "pupigerous",
     67     "nodulous", "cycloid", "forbidden", "lurid", "fine", "platinum", "blue",
     68     "monochrome", "spreading", "mutant", "revolving", "corporeal", "hideous",
     69     "mild", "shrunken", "glum", "petty", "clean", "mutable", "leather", "scaly",
     70     "spongy", "tendrillar", "refulgent", "porcelein"
     71 };
     72 const char *Adv[] = {
     73     "thinly", "strongly", "invisibly", "slowly", "woozily", "grimly", "greatly",
     74     "mostly", "partially", "totally", "blatantly", "pleasantly", "luxuriously",
     75     "expansively", "utterly", "rapidly", "crudely", "mercifully", "delicately",
     76     "wrongfully", "arrogantly", "horribly", "wonderfully", "ostensibly",
     77     "remarkably", "miraculously", "accidentally"
     78 };
     79 const char *Prep[] = {
     80     "above", "below", "amidst", "near", "far beyond", "inside", "thanks to",
     81     "outside", "out of", "despite", "astride", "in", "beside", "of"
     82 };
     83 const char *Sense[] = {
     84     "shiver", "pressure", "texture", "friction", "warmth", "chill", "weight",
     85     "echo", "resonance", "murmur", "thrum", "discord", "silence", "cadence",
     86     "glow", "shadow", "radiance", "glimmer", "shimmer", "haze", "aura", "scent",
     87     "stink", "perfume", "savor", "aftertaste", "pungency", "breath",
     88     "intuition", "dread", "premonition", "vertigo", "ache", "yearning", "sting"
     89 };
     90 const char *Det[] = {
     91     "his", "her", "its", "our", "their", "the", "thy", "this", "that", "thine",
     92     "another", "a", "an", "some", "every", "my", "mine", "those", "these"
     93 };
     94 const char *Question[] = {
     95     "who", "what", "where"
     96 };
     97 const char *SubjPronoun[] = {
     98     "he", "she", "it", "they", "we", "who", "naught", "someone"
     99 };
    100 const char *ObjPronoun[] = {
    101     "him", "her", "it", "them", "us", "whom", "thee", "nothing", "thou"
    102 };
    103 const char *SortOf[] = {
    104     "sort of", "kind of", "like", "almost"
    105 };
    106 const char *Condition[] = {
    107     "if", "when", "though", "while", "whenever", "since", "unless", "once"
    108 };
    109 const char *Vocative[] = {
    110     "o", "alas,", "behold,", "hail,", "farewell,", "stay,", "hark,"
    111 };
    112 const char *Coord[] = {
    113     "and", "but", "for", "yet", "or", "nor", "so"
    114 };
    115 const char *WillDoth[] = {
    116     "doth", "may", "can", "will", "shall", "must", "hath", "might"
    117 };
    118 const char *PosPronoun[] = {
    119     "hers", "his", "yours", "theirs", "ours", "its"
    120 };
    121 const char *Conj2[] = {
    122     "but", "though", "yet"
    123 };
    124 const char *REEZ[] = {
    125     "and ease", "and chronologies", "and grease", "and debris",
    126     "with expertise", "and TVs", "and bourgeoisies", "and industries",
    127     "without cease", "in three", "in twos and threes", "by degrees", "and ZZZs",
    128     "and memories", "breeze", "trees", "seas", "crease", "lees", "fleece",
    129     "police", "freeze"
    130 };
    131 const char *IRE[] = {
    132     "fire", "ire", "wire", "mire", "things expire'd", "desire", "spire",
    133     "attire", "pyre", "higher", "liar", "dire", "prior", "cypher"
    134 };
    135 const char *ACE[] = {
    136     "face", "grace", "suitcase", "pace", "solace", "base", "case", "trace"
    137 };
    138 const char *ISS[] = {
    139     "terrace", "space", "populace", "surface", "waste", "place"
    140 };
    141 const char *AND[] = {
    142     "land", "hand", "sand", "strand", "brand", "unmanned", "planned",
    143     "command", "grand", "unplanned", "fanned", "bland", "banned",
    144     "contraband", "expand", "reprimand", "unhand", "demand"
    145 };
    146 
    147 #define PICK(arr) (arr[rand() % (sizeof(arr) / sizeof(arr[0]))])
    148 
    149 void
    150 generate_prose(void) {
    151 	int template_choice = rand() % 17;
    152 
    153 	switch (template_choice) {
    154 	case 0: /* Transitive Metaphor */
    155 	    tiny_printf("%s %s %s %s %s\n",
    156 		 PICK(Det), PICK(Noun), PICK(Verb2),
    157 		 PICK(Adj), PICK(Noun));
    158 	    break;
    159 
    160 	case 1: /* Auxiliary Question */
    161 	    tiny_printf("%s %s %s %s %s %s?\n",
    162 		 PICK(Question), PICK(WillDoth), PICK(Adv),
    163 		 PICK(Verb1),PICK(Det), PICK(Noun));
    164 	    break;
    165 
    166 	case 2: /* Attributive Approximation */
    167 	    tiny_printf("%s %s %s %s %s\n",
    168 		 PICK(SubjPronoun), PICK(Verb2), PICK(SortOf),
    169 		 PICK(Adj), PICK(Noun));
    170 	    break;
    171 
    172 	case 3: /* Vocative */
    173 	    tiny_printf("%s %s, %s %s %s %s\n",
    174 		 PICK(Vocative), PICK(Noun), PICK(Det),
    175 		 PICK(Noun), PICK(Verb1), PICK(ObjPronoun));
    176 	    break;
    177 
    178 	case 4: /* Relative */
    179 	    tiny_printf("%s %s %s, %s %s %s %s?\n",
    180 		 PICK(Question), PICK(Adj), PICK(Noun),
    181 		 PICK(Verb1), PICK(SortOf), PICK(Det),
    182 		 PICK(Noun));
    183 	    break;
    184 
    185 	case 5: /* Paradox */
    186 	    tiny_printf("%s %s %s %s %s %s\n",
    187 		 PICK(Det), PICK(Noun), PICK(Verb2),
    188 		 PICK(Det), PICK(Adj), PICK(Noun));
    189 	    break;
    190 
    191 	case 6: /* Modal Adverbial */
    192 	    tiny_printf("%s %s %s %s %s %s\n",
    193 		 PICK(SubjPronoun), PICK(WillDoth), PICK(Adv),
    194 		 PICK(Verb1), PICK(Det), PICK(Noun));
    195 	    break;
    196 
    197 	case 7: /* Prepositional Opener */
    198 	    tiny_printf("%s %s %s, %s %s %s\n",
    199 		 PICK(Prep), PICK(Det), PICK(Noun),
    200 		 PICK(Det), PICK(Noun), PICK(Verb1));
    201 	    break;
    202 
    203 	case 8: /* Conditional */
    204 	    tiny_printf("%s %s %s %s, %s %s %s %s\n",
    205 		 PICK(Condition), PICK(SubjPronoun), PICK(WillDoth),
    206 		 PICK(Verb1), PICK(Det), PICK(Noun), PICK(WillDoth),
    207 		 PICK(Verb1));
    208 	    break;
    209 
    210 	case 9: /* Inverse Conditional */
    211 	    tiny_printf("%s %s %s %s %s %s %s %s\n",
    212 		 PICK(Det), PICK(Noun), PICK(WillDoth),
    213 		 PICK(Verb1), PICK(Condition), PICK(SubjPronoun),
    214 		 PICK(WillDoth), PICK(Verb1));
    215 	    break;
    216 
    217 	case 10: /* Possessive Existential */
    218 	    tiny_printf("%s %s's %s %s %s %s\n",
    219 		 PICK(Det), PICK(Noun), PICK(Noun),
    220 		 PICK(Verb2), PICK(Det), PICK(Noun));
    221 	    break;
    222 
    223 	case 11: /* Sensory Attestation */
    224 	    tiny_printf("%s %s %s of %s %s %s %s\n",
    225 		 PICK(Det), PICK(Adj), PICK(Sense),
    226 		 PICK(Noun), PICK(Verb2), PICK(Det),
    227 		 PICK(Noun));
    228 	    break;
    229 
    230 	case 12: /* Negative Sensory */
    231 	    tiny_printf("no %s %s %s %s %s %s %s %s\n",
    232 		 PICK(Sense), PICK(Prep), PICK(Det),
    233 		 PICK(Noun), PICK(WillDoth), PICK(Verb1),
    234 		 PICK(Det), PICK(Noun));
    235 	    break;
    236 
    237 	case 13:
    238 	    tiny_printf("%s %s %s %s\n",
    239 		 PICK(Det), PICK(Noun), PICK(Verb2),
    240 		 PICK(AND));
    241 	    tiny_printf("%s %s %s %s\n",
    242 		 PICK(Det), PICK(Adj), PICK(Noun),
    243 		 PICK(AND));
    244 	    break;
    245 
    246 	case 14:
    247 	    tiny_printf("%s %s %s %s\n",
    248 		PICK(Det), PICK(Noun), PICK(Verb1),
    249 		PICK(REEZ));
    250 	    tiny_printf("%s %s %s %s %s\n",
    251 		PICK(Prep), PICK(Det), PICK(Adj),
    252 		PICK(Noun), PICK(REEZ));
    253 	    break;
    254 
    255 	case 15:
    256 	    tiny_printf("%s %s %s %s\n",
    257 		PICK(Vocative), PICK(Noun), PICK(Verb2),
    258 		PICK(IRE));
    259 	    tiny_printf("%s %s %s %s\n",
    260 		PICK(Det), PICK(Noun), PICK(WillDoth),
    261 		PICK(IRE));
    262 	    break;
    263 
    264 	case 16:
    265 	    tiny_printf("%s %s %s %s %s\n",
    266 		PICK(SubjPronoun), PICK(Adv), PICK(Verb1),
    267 		PICK(Det), PICK(ACE));
    268 	    tiny_printf("%s %s %s %s\n",
    269 		PICK(Coord), PICK(Verb1), PICK(Det),
    270 		PICK(ISS));
    271 	    break;
    272 	default: break;
    273 	}
    274 }
    275 
    276 int
    277 main(void) {
    278 	srand((unsigned int)time(NULL));
    279 	int lines = (rand() % 2) + 1;
    280 	for (int i = 0; i < lines; i++)
    281 	    generate_prose();
    282 	return 0;
    283 }