four06% cat -n arith0.c
1 /* arith0.c: simple parser -- no output
2 * grammar:
3 * P ---> E '#'
4 * E ---> T {('+'|'-') T}
5 * T ---> S {('*'|'/') S}
6 * S ---> F '^' S | F
7 * F ---> char | '(' E ')'
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <ctype.h>
12 char next;
13 void E(void);
14 void T(void);
15 void S(void);
16 void F(void);
17 void error(int);
18 void scan(void);
19 void enter(char);
20 void leave(char);
21 void spaces(int);
22 int level = 0;
23
24 void main(void)
25 {
26 scan();
27 E();
28 if (next != '#') error(1);
29 else printf("Successful parse\n");
30 }
31
32 void E(void)
33 {
34 enter('E');
35 T();
36 while (next == '+' || next == '-') {
37 scan();
38 T();
39 }
40 leave('E');
41 }
42
43 void T(void)
44 {
45 enter('T');
46 S();
47 while (next == '*' || next == '/') {
48 scan();
49 S();
50 }
51 leave('T');
52 }
53 void S(void)
54 {
55 enter('S');
56 F();
57 if (next == '^') {
58 scan();
59 S();
60 }
61 leave('S');
62 }
63 void F(void)
64 {
65 enter('F');
66 if (isalpha(next)) {
67 scan();
68 }
69 else if (next == '(') {
70 scan();
71 E();
72 if (next == ')') scan();
73 else error(2);
74 }
75 else {
76 error(3);
77 }
78 leave('F');
79 }
80 void scan(void)
81 {
82 while (isspace(next = getchar()))
83 ;
84 }
85 void error(int n)
86 {
87 printf("\n*** ERROR: %i\n", n);
88 exit(1);
89 }
90 void enter(char name)
91 {
92 spaces(level++);
93 printf("+-%c: Enter, \t", name);
94 printf("Next == %c\n", next);
95 }
96 void leave(char name)
97 {
98 spaces(--level);
99 printf("+-%c: Leave, \t", name);
100 printf("Next == %c\n", next);
101 }
102
103 void spaces(int local_level)
104 {
105 while (local_level-- > 0)
106 printf("| ");
107 }
four06% arith0
a + b + c #
+-E: Enter, Next == a
| +-T: Enter, Next == a
| | +-S: Enter, Next == a
| | | +-F: Enter, Next == a
| | | +-F: Leave, Next == +
| | +-S: Leave, Next == +
| +-T: Leave, Next == +
| +-T: Enter, Next == b
| | +-S: Enter, Next == b
| | | +-F: Enter, Next == b
| | | +-F: Leave, Next == +
| | +-S: Leave, Next == +
| +-T: Leave, Next == +
| +-T: Enter, Next == c
| | +-S: Enter, Next == c
| | | +-F: Enter, Next == c
| | | +-F: Leave, Next == #
| | +-S: Leave, Next == #
| +-T: Leave, Next == #
+-E: Leave, Next == #
Successful parse
four06% arith0
a ^ b ^ c #
+-E: Enter, Next == a
| +-T: Enter, Next == a
| | +-S: Enter, Next == a
| | | +-F: Enter, Next == a
| | | +-F: Leave, Next == ^
| | | +-S: Enter, Next == b
| | | | +-F: Enter, Next == b
| | | | +-F: Leave, Next == ^
| | | | +-S: Enter, Next == c
| | | | | +-F: Enter, Next == c
| | | | | +-F: Leave, Next == #
| | | | +-S: Leave, Next == #
| | | +-S: Leave, Next == #
| | +-S: Leave, Next == #
| +-T: Leave, Next == #
+-E: Leave, Next == #
Successful parse
four06% arith0
( a * b #
+-E: Enter, Next == (
| +-T: Enter, Next == (
| | +-S: Enter, Next == (
| | | +-F: Enter, Next == (
| | | | +-E: Enter, Next == a
| | | | | +-T: Enter, Next == a
| | | | | | +-S: Enter, Next == a
| | | | | | | +-F: Enter, Next == a
| | | | | | | +-F: Leave, Next == *
| | | | | | +-S: Leave, Next == *
| | | | | | +-S: Enter, Next == b
| | | | | | | +-F: Enter, Next == b
| | | | | | | +-F: Leave, Next == #
| | | | | | +-S: Leave, Next == #
| | | | | +-T: Leave, Next == #
| | | | +-E: Leave, Next == #
*** ERROR: 2
four06% arith0
(a + b) * c #
+-E: Enter, Next == (
| +-T: Enter, Next == (
| | +-S: Enter, Next == (
| | | +-F: Enter, Next == (
| | | | +-E: Enter, Next == a
| | | | | +-T: Enter, Next == a
| | | | | | +-S: Enter, Next == a
| | | | | | | +-F: Enter, Next == a
| | | | | | | +-F: Leave, Next == +
| | | | | | +-S: Leave, Next == +
| | | | | +-T: Leave, Next == +
| | | | | +-T: Enter, Next == b
| | | | | | +-S: Enter, Next == b
| | | | | | | +-F: Enter, Next == b
| | | | | | | +-F: Leave, Next == )
| | | | | | +-S: Leave, Next == )
| | | | | +-T: Leave, Next == )
| | | | +-E: Leave, Next == )
| | | +-F: Leave, Next == *
| | +-S: Leave, Next == *
| | +-S: Enter, Next == c
| | | +-F: Enter, Next == c
| | | +-F: Leave, Next == #
| | +-S: Leave, Next == #
| +-T: Leave, Next == #
+-E: Leave, Next == #
Successful parse