Design Pattern Examples
Overview of object-oriented design patterns
Interpreter_Interpreter.c
Go to the documentation of this file.
1
5
6#include <errno.h>
7#include <stdlib.h>
8#include <stdio.h>
9#include <string.h>
10#include <memory.h>
11
12#include "helpers/titlecase.h"
13
15
20static const char* _commonwords[] =
21{
22 "the",
23 "be",
24 "to",
25 "of",
26 "and",
27 "a",
28 "in",
29 "that",
30 "have",
31 "I",
32 "it",
33 "for",
34 "not",
35 "on",
36 "with",
37 "he",
38 "as",
39 "you",
40 "do",
41 "at",
42 "this",
43 "but",
44 "his",
45 "by",
46 "from",
47 "they",
48 "we",
49 "say",
50 "her",
51 "she",
52 "or",
53 "an",
54 "will",
55 "my",
56 "one",
57 "all",
58 "would",
59 "there",
60 "their",
61 "what",
62};
63
72static const char* _InterpretToken(int token)
73{
74 const char* tokenAsString = "";
75
76 // Rule 1: token is between 0 and the number of common words.
77 int numCommonWords = sizeof(_commonwords) / sizeof(_commonwords[0]);
78 if (token >= 0 && token < numCommonWords)
79 {
80 tokenAsString = _commonwords[token];
81 }
82 else
83 {
84 // Rule 1: token can also be a PERIOD
85 if (token == PERIOD)
86 {
87 tokenAsString = ".";
88 }
89 // Rule 1: or the token can also be a QUESTION
90 else if (token == QUESTION)
91 {
92 tokenAsString = "?";
93 }
94 else
95 {
96 static char buffer[32] = { 0 };
97 int num_chars = snprintf(buffer, sizeof(buffer), "<UNKNOWN TOKEN %d>", token);
98 if (num_chars >= 0)
99 {
100 // Rule 1: Invalid tokens returned as unknown.
101 tokenAsString = buffer;
102 }
103 else
104 {
105 int errorCode = errno;
106 printf(" Error(%d)! snprintf() failed: %s", errorCode, strerror(errorCode));
107 }
108 }
109 }
110 return tokenAsString;
111}
112
113
115// Interpreter_Interpret()
117bool Interpreter_Interpret(const int* tokenList, DynamicString* output)
118{
119 bool success = false;
120
121 if (tokenList != NULL && output != NULL)
122 {
123 success = true;
124 for (size_t tokenIndex = 0; tokenList[tokenIndex] != EOL; ++tokenIndex)
125 {
126 const char* tokenAsString = _InterpretToken(tokenList[tokenIndex]);
127 char* titleString = NULL;
128 if (tokenIndex == 0)
129 {
130 // Rule 2: First word in sentence gets capitalized according to local rules.
131 titleString = titlecase(tokenAsString); // Note: titleString must be freed
132 if (titleString == NULL)
133 {
134 printf(" Error! titlecase() in Interpreter_Interpret() encountered an out of memory condition!\n");
135 success = false;
136 break;
137 }
138 tokenAsString = titleString;
139 }
140 success = DynamicString_Append(output, tokenAsString);
141 free(titleString); // Free this now that we are done with it
142
143 if (success)
144 {
145 // Rule 4: No space between last two tokens (if the following expression is false)
146 if (tokenList[tokenIndex + 2] != EOL)
147 {
148 // Rule 3: Separate all words by a single space.
149 success = DynamicString_Append(output, " ");
150 if (!success)
151 {
152 printf(" Error! Out of memory condition adding space separator to output in Interpreter_Interpret()!\n");
153 break;
154 }
155 }
156 }
157 else
158 {
159 printf(" Error! Out of memory condition adding token to output in Interpreter_Interpret()!\n");
160 break;
161 }
162 }
163 }
164
165 return success;
166}
static const char * _commonwords[]
The 40 most common words in English (in order but that doesn't really matter here)....
static const char * _InterpretToken(int token)
Helper function to convert the token into its corresponding word or punctuation mark.
bool Interpreter_Interpret(const int *tokenList, DynamicString *output)
This function is a simple interpreter.
Declaration of the Interpreter_Interpret() function used in the Interpreter Pattern.
@ EOL
Marker for end of a token list.
@ QUESTION
Question mark.
@ PERIOD
Period.
bool DynamicString_Append(DynamicString *string, const char *s)
Append the specified string to the DynamicString object.
Definition: dynamicstring.c:39
Represents a string that can be grown dynamically.
Definition: dynamicstring.h:16
char * titlecase(const char *s)
Convert the first word (or only word) in the given string to lowercase then make the first letter upp...
Definition: titlecase.c:15