2 * fadot.c: example usage of finite automata library
4 * Copyright (C) 2009, Francis Giraldeau
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Author: Francis Giraldeau <francis.giraldeau@usherbrooke.ca>
24 * The purpose of this example is to show the usage of libfa
36 #define UCHAR_NUM (UCHAR_MAX+1)
40 static const char *const escape_chars = "\"\a\b\t\n\v\f\r\\";
41 static const char *const escape_names = "\"abtnvfr\\";
43 __attribute__((noreturn))
44 static void usage(void) {
45 fprintf(stderr, "\nUsage: %s [OPTIONS] REGEXP\n", progname);
46 fprintf(stderr, "\nCompile REGEXP and apply operation to them. By default, just print\n");
47 fprintf(stderr, "the minimized regexp.\n");
48 fprintf(stderr, "\nOptions:\n\n");
49 fprintf(stderr, " -o OPERATION one of : show concat union intersect json\n");
50 fprintf(stderr, " complement minus example print\n");
51 fprintf(stderr, " -f DOT_FILE Path of output .dot file\n");
52 fprintf(stderr, " -n do not minimize resulting finite automaton\n");
57 int main (int argc, char **argv) {
62 char *file_output = NULL;
63 const char *operation = NULL;
70 while ((c = getopt (argc, argv, "nhf:o:")) != -1)
86 if (optopt == 'o' || optopt == 'f')
87 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
88 else if (isprint (optopt))
89 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
92 "Unknown option character `\\x%x'.\n",
101 //printf ("reduce = %d, file_output = %s, operation = %s\n",
102 // reduce, file_output, operation);
104 if (operation == NULL)
107 for (int i = optind; i < argc; i++) {
111 if (nb_regexp == 0) {
112 printf("Please specify regexp to process.\n");
116 struct fa* fa_result = NULL;
118 if (!strcmp(operation,"show")) {
119 fa_compile(argv[optind], strlen(argv[optind]), &fa_result);
120 } else if (!strcmp(operation,"concat")) {
123 fprintf(stderr,"Please specify 2 or more regexp to concat");
127 fa_result = fa_make_basic(FA_EPSILON);
129 for (int i = optind; i < argc; i++) {
130 fa_compile(argv[i], strlen(argv[i]), &fa_tmp);
131 fa_result = fa_concat(fa_result, fa_tmp);
134 } else if (!strcmp(operation, "union")) {
137 fprintf(stderr,"Please specify 2 or more regexp to union");
141 fa_result = fa_make_basic(FA_EMPTY);
144 for (int i = optind; i < argc; i++) {
145 fa_compile(argv[i], strlen(argv[i]), &fa_tmp);
146 fa_result = fa_union(fa_result, fa_tmp);
149 } else if (!strcmp(operation, "intersect")) {
152 fprintf(stderr,"Please specify 2 or more regexp to intersect");
156 fa_compile(argv[optind], strlen(argv[optind]), &fa_result);
159 for (int i = optind+1; i < argc; i++) {
160 fa_compile(argv[i], strlen(argv[i]), &fa_tmp);
161 fa_result = fa_intersect(fa_result, fa_tmp);
164 } else if (!strcmp(operation, "complement")) {
166 if (nb_regexp >= 2) {
167 fprintf(stderr,"Please specify one regexp to complement");
171 fa_compile(argv[optind], strlen(argv[optind]), &fa_result);
172 fa_result = fa_complement(fa_result);
174 } else if (!strcmp(operation, "minus")) {
176 if (nb_regexp != 2) {
177 fprintf(stderr,"Please specify 2 regexp for operation minus");
183 fa_compile(argv[optind], strlen(argv[optind]), &fa_tmp1);
184 fa_compile(argv[optind+1], strlen(argv[optind+1]), &fa_tmp2);
185 fa_result = fa_minus(fa_tmp1, fa_tmp2);
187 } else if (!strcmp(operation, "example")) {
189 if (nb_regexp != 1) {
190 fprintf(stderr,"Please specify one regexp for operation example");
196 fa_compile(argv[optind], strlen(argv[optind]), &fa_result);
197 fa_example(fa_result, &word, &word_len);
198 printf("Example word = %s\n", word);
200 } else if (!strcmp(operation, "json")) {
201 if (nb_regexp != 1) {
202 fprintf(stderr,"Please specify one regexp for operation example");
206 fa_compile(argv[optind], strlen(argv[optind]), &fa_result);
209 fa_minimize(fa_result);
212 if (file_output != NULL) {
213 if ((fd = fopen(file_output, "w")) == NULL) {
214 fprintf(stderr, "Error while opening file %s \n", file_output);
218 fa_json(fd, fa_result);
221 fa_json(stdout, fa_result);
226 } else if (!strcmp(operation, "print")) {
227 if (nb_regexp != 1) {
228 fprintf(stderr,"Please specify one regexp for operation example");
232 fa_compile(argv[optind], strlen(argv[optind]), &fa_result);
235 fa_minimize(fa_result);
238 struct state *st, *st2;
239 uint32_t num_trans, i;
240 unsigned char begin, end;
242 st = fa_state_initial(fa_result);
244 printf("%s. Initial state: %p", fa_is_deterministic(fa_result) ? "DFA" : "NFA", fa_result);
247 num_trans = fa_state_num_trans(st);
248 printf("\nFrom state %p (final = %s):\n", st, fa_state_is_accepting(st) == 1 ? "true" : "false");
249 for (i = 0; i < num_trans; i++) {
250 if (fa_state_trans(st, i, &st2, &begin, &end) < 0) {
251 printf("Some error occur. \n");
254 printf(" to: %p, label: %d\n", st2, begin);
256 printf(" to: %p, label: %d-%d\n", st2, begin, end);
258 st = fa_state_next(st);
266 fa_minimize(fa_result);
269 if (file_output != NULL) {
270 if ((fd = fopen(file_output, "w")) == NULL) {
271 fprintf(stderr, "Error while opening file %s \n", file_output);
275 fa_dot(fd, fa_result);
282 r = fa_as_regexp(fa_result, &rx, &rx_len);
284 fprintf(stderr, "Converting FA to regexp failed\n");
288 for (size_t i=0; i < rx_len; i++) {
290 if (rx[i] && ((p = strchr(escape_chars, rx[i])) != NULL)) {
291 printf("\\%c", escape_names[p - escape_chars]);
292 } else if (! isprint(rx[i])) {
293 printf("\\%030o", (unsigned char) rx[i]);