Commit | Line | Data |
---|---|---|
ee2abe03 C |
1 | WART |
2 | ||
3 | Wart is a program that implements a small subset of the Unix 'lex' lexical | |
4 | analyzer generator. Unlike lex, wart may be distributed without requirement | |
5 | for a Unix license. Wart was written by Jeff Damens at the Columbia University | |
6 | Center of Computing Activities to facilitate development of Unix Kermit. | |
7 | ||
8 | Wart is intended for production of state table switchers. It allows a set of | |
9 | states to be defined, along with a function for getting input, and a table of | |
10 | state transitions. A C program is generated which performs actions and | |
11 | switches states based on the current state and the input. | |
12 | ||
13 | The following short program demonstrates some of the capabilities and | |
14 | limitations of Wart. The program accepts from the command line a binary | |
15 | number, preceded by an optional minus sign, and optionally containing a | |
16 | fractional part. It prints the decimal equivalent. | |
17 | ||
18 | #include <stdio.h> | |
19 | ||
20 | int state, s = 1, m = 0, d; | |
21 | float f; | |
22 | char *b; | |
23 | ||
24 | %states sign mantissa fraction /* Declare wart states */ | |
25 | ||
26 | %% /* Begin state table */ | |
27 | <sign>- { s = -1; BEGIN mantissa; } /* Look for sign */ | |
28 | <sign>0 { m = 0; BEGIN mantissa; } /* Got digit, start mantissa */ | |
29 | <sign>1 { m = 1; BEGIN mantissa; } | |
30 | <sign>. { fatal("bad input"); } /* Detect bad format */ | |
31 | <mantissa>0 { m *= 2; } /* Accumulate mantissa */ | |
32 | <mantissa>1 { m = 2 * m + 1; } | |
33 | <mantissa>$ { printf("%d\n", s * m); return; } | |
34 | <mantissa>. { f = 0.0; d = 1; BEGIN fraction; } /* Start fraction */ | |
35 | <fraction>0 { d *= 2; } /* Accumulate fraction */ | |
36 | <fraction>1 { d *= 2; f += 1.0 / d; } | |
37 | <fraction>$ { printf("%f\n", s * (m + f) ); return; } | |
38 | <fraction>. { fatal("bad input"); } | |
39 | %% | |
40 | ||
41 | input() { /* Define input() function */ | |
42 | int x; | |
43 | return(((x = *b++) == '\0') ? '$' : x ); | |
44 | } | |
45 | ||
46 | fatal(s) char *s; { /* Error exit */ | |
47 | fprintf(stderr,"fatal - %s\n",s); | |
48 | exit(1); | |
49 | } | |
50 | ||
51 | main(argc,argv) int argc; char **argv; { /* Main program */ | |
52 | if (argc < 1) exit(1); | |
53 | b = *++argv; | |
54 | state = sign; /* Initialize state */ | |
55 | wart(); /* Invoke state switcher */ | |
56 | exit(0); /* Done */ | |
57 | } | |
58 | ||
59 | The wart program accepts as input a C program containing lines that start | |
60 | with "%" or sections delimited by "%%". The directive "%states" declares | |
61 | the program's states. The section enclosed by "%%" markers is the state | |
62 | table, with entries of the form | |
63 | ||
64 | <state>X { action } | |
65 | ||
66 | which is read as "if in state <state> with input X perform { action }" | |
67 | ||
68 | The optional <state> field tells the current state or states the program must | |
69 | be in to perform the indicated action. If no state is specified, then it | |
70 | means the action will be performed regardless of the current state. If more | |
71 | than one state is specifed, then the action will be performed in any of the | |
72 | listed states. Multiple states are separated by commas. | |
73 | ||
74 | The required input field consists of a single literal character. When in | |
75 | the indicated state, if the input is the specified character, then the | |
76 | associated action will be performed. The character '.' matches any input | |
77 | character. No pattern matching or range notation is provided. The input | |
78 | character is obtained from the input() function, which you must define. It | |
79 | should be alphanumeric, or else one of the characters ".% -$@" (quotes not | |
80 | included). Note that the program above recognize the binary point '.' | |
81 | through a ruse. | |
82 | ||
83 | The action is a series of zero or more C language statements, enclosed in | |
84 | curly braces. | |
85 | ||
86 | The BEGIN macro is defined simply to be "state = ", as in lex. | |
87 | ||
88 | The wart() function is generated by the wart program based on the state | |
89 | declarations and the state transition table. It loops through calls to | |
90 | input(), using the result to index into a big case statement it has created | |
91 | from the state table. | |
92 | ||
93 | Wart is invoked as follows: | |
94 | ||
95 | wart (Input from stdin, output to stdout) | |
96 | ||
97 | wart fn1 (Input from fn1, output to stdout) | |
98 | ||
99 | wart fn1 fn2 (Input from fn1, output to fn2. Example: wart a.w a.c) | |
100 | ||
101 | Wart programs have the conventional filetype '.w'. |