Minor changes.
[egate.git] / fml / fmltoken.c
1 /*
2  * FML interpreter. Europagate, 1995
3  *
4  * fmltoken.c,v
5  * Revision 1.4  1995/02/10  18:15:53  adam
6  * FML function 'strcmp' implemented. This function can be used to
7  * test for existence of MARC fields.
8  *
9  * Revision 1.3  1995/02/10  15:50:57  adam
10  * MARC interface implemented. Minor bugs fixed. fmltest can
11  * be used to format single MARC records. New function '\list'
12  * implemented.
13  *
14  * Revision 1.2  1995/02/07  16:09:24  adam
15  * The \ character is no longer INCLUDED when terminating a token.
16  * Major changes in tokenization routines. Bug fixes in expressions
17  * with lists (fml_sub0).
18  *
19  * Revision 1.1.1.1  1995/02/06  13:48:10  adam
20  * First version of the FML interpreter. It's slow and memory isn't
21  * freed properly. In particular, the FML nodes aren't released yet.
22  *
23  */
24 #include <string.h>
25 #include <assert.h>
26 #include <stdio.h>
27
28 #include "fmlp.h"
29
30 static int look_char;
31 static int look_type;
32 static char lex_buf[FML_MAX_TOKEN];
33
34 static void lexer (Fml fml);
35
36 struct fml_node *fml_group (Fml fml);
37
38 struct fml_node *fml_tokenize (Fml fml)
39 {
40     struct fml_node *p;
41
42     look_char = (*fml->read_func)();
43     p = fml_group (fml);
44     if (fml->debug)
45     {
46         fml_pr_list (p);
47         printf ("\n");
48     }
49     if (look_char != fml->eof_mark)
50     {
51         fprintf (stderr, "Ill formed parantheses");
52         exit (1);
53     }
54     return p;
55 }
56
57 void fml_pr_list (struct fml_node *p)
58 {
59     printf ("{");
60
61     while (p)
62     {
63         if (p->is_atom)
64         {
65             char buf[100];
66             fml_atom_str (p->p[0], buf);
67             printf (" %s", buf);
68         }
69         else
70         {
71             printf (" ");
72             fml_pr_list (p->p[0]);
73         }
74         p = p->p[1];
75     }
76     printf (" }");         
77 }
78
79 struct fml_node *fml_group (Fml fml)
80 {
81     struct fml_node *ptr0 = NULL, *ptr1, *ptr2;
82
83     lexer (fml);
84     if (look_type == 0)
85         return NULL;
86     while (1)
87     {
88         if (look_type == 'a')
89         {
90             ptr2 = fml_node_alloc (fml);
91             if (!ptr0)
92                 ptr0 = ptr2;
93             else
94                 ptr1->p[1] = ptr2;
95             ptr2->p[0] = fml_atom_alloc (fml, lex_buf);
96             ptr2->is_atom = 1;
97         }
98         else if (look_type == '{')
99         {
100             struct fml_node *sptr = fml_group (fml);
101             if (sptr)
102             {
103                 ptr2 = fml_node_alloc (fml);
104                 if (!ptr0)
105                     ptr0 = ptr2;
106                 else
107                         ptr1->p[1] = ptr2;
108                 ptr2->p[0] = sptr;
109                 ptr2->is_atom = 0;
110             }
111             else
112             {
113                 ptr2 = fml_node_alloc (fml);
114                 if (!ptr0)
115                     ptr0 = ptr2;
116                 else
117                     ptr1->p[1] = ptr2;
118                 ptr2->is_atom = 0;
119             }
120         }
121         else
122             break;
123         lexer (fml);
124         ptr1 = ptr2;
125     }
126     return ptr0;
127 }
128
129 static void lexer (Fml fml)
130 {
131     int off;
132     while (1) 
133     {
134         if (look_char == fml->eof_mark)
135         {
136             look_type = 0;
137             return;
138         }
139         else if (look_char == fml->comment_char)
140         {
141             do
142                 look_char = (*fml->read_func)();
143             while (look_char != '\n' && look_char != fml->eof_mark);
144         }
145         else
146         {
147             if (!strchr (fml->white_chars, look_char))
148                 break;
149             look_char = (*fml->read_func)();
150         }
151     }
152     if (look_char == '{')
153     {
154         look_type = '{';
155         look_char = (*fml->read_func)();
156     }
157     else if (look_char == '}')
158     {
159         look_type = '}';
160         look_char = (*fml->read_func)();
161     }        
162     else if (look_char == '\'')
163     {
164         off = 0;
165         look_char = (*fml->read_func)();
166         while (look_char != fml->eof_mark && look_char != '\'')
167         {
168             lex_buf[off++] = look_char;
169             if (look_char == '\\')
170             {
171                 look_char = (*fml->read_func)();
172                 switch (look_char)
173                 {
174                 case 'n':
175                     lex_buf[off-1] = '\n';
176                     break;
177                 case 't':
178                     lex_buf[off-1] = '\n';
179                     break;
180                 case '\'':
181                     lex_buf[off-1] = '\''; 
182                     break;
183                 default:
184                     lex_buf[off-1] = look_char;
185                 }
186             }
187             look_char = (*fml->read_func)();
188         } 
189         lex_buf[off] = '\0';
190         look_type = 'a';
191         if (look_char == '\'')
192             look_char = (*fml->read_func)();
193     }
194     else
195     {
196         off = 0;
197         do
198         {
199             lex_buf[off++] = look_char;
200             look_char = (*fml->read_func)();
201         } while (look_char != fml->eof_mark
202                  && !strchr (fml->white_chars, look_char)
203                  && look_char != '{' && look_char != '}');
204         lex_buf[off] = '\0';
205         look_type = 'a';
206     }
207 #if 0
208     if (fml->debug)
209     {
210         if (look_type == 'a')
211             printf ("[%s]", lex_buf);
212         else
213             printf ("[%c]", look_type);
214     }
215 #endif
216 }