Added proper copyright notice.
[gedcom-parse.git] / gedcom_hilo.lex
1 /*  This program is free software; you can redistribute it and/or modify  *
2  *  it under the terms of the GNU General Public License as published by  *
3  *  the Free Software Foundation; either version 2 of the License, or     *
4  *  (at your option) any later version.                                   *
5
6  (C) 2001 by The Genes Development Team
7  Original author: Peter Verthez (Peter.Verthez@advalvas.be)
8 */
9
10 /* $Id$ */
11 /* $Name$ */
12
13 /* In high-low order, a space is encoded as 0x00 0x20 */
14 /* i.e. this is utf-16-be */
15
16 %{
17 #include "gedcom.tab.h"
18 #include "gedcom.h"
19 #include "multilex.h"
20 #include "encoding.h"
21
22 #define YY_NO_UNPUT
23 %}
24
25 %s NORMAL
26 %s EXPECT_TAG
27
28 alpha        \x00[A-Za-z_]
29 digit        \x00[0-9]
30 delim        \x00\x20
31 tab          \x00[\t]
32 hash         \x00#
33 literal_at   \x00@\x00@
34 otherchar    \x00[\x21-\x22\x24-\x2F\x3A-\x3F\x5B-\x5E\x60\x7B-\x7E\x80-\xFF]|[\x01-\xFF][\x00-\xFF]
35 terminator   \x00\x0D|\x00\x0A|\x00\x0D\x00\x0A|\x00\x0A\x00\x0D
36
37 any_char     {alpha}|{digit}|{otherchar}|{delim}|{hash}|{literal_at}
38 any_but_delim {alpha}|{digit}|{otherchar}|{hash}|{literal_at}
39 non_at       {alpha}|{digit}|{otherchar}|{delim}|{hash}
40 alphanum     {alpha}|{digit}
41 gen_delim    {delim}|{tab}
42
43 escape       \x00@\x00#{any_char}+\x00@
44 pointer      \x00@{alphanum}{non_at}+\x00@
45
46 %{
47 static int current_level=-1;
48 static int level_diff=MAXGEDCLEVEL;
49  
50 #ifdef LEXER_TEST 
51 YYSTYPE gedcom_lval;
52 int line_no = 1; 
53 #endif
54 %} 
55
56 %%
57
58     /* The GEDCOM level number is converted into a sequence of opening
59        and closing brackets.  Simply put, the following GEDCOM fragment:
60
61          0 HEAD
62          1 SOUR genes
63          2 VERS 1.6
64          2 NAME Genes
65          1 DATE 07 OCT 2001
66          ...
67          0 TRLR
68
69        is converted into:
70
71          { HEAD                     (initial)  
72          { SOUR genes               (1 higher: no closing brackets)
73          { VERS 1.6                 (1 higher: no closing brackets)
74          } { NAME Genes             (same level: 1 closing bracket)
75          } } { DATE 07 OCT 2001     (1 lower: 2 closing brackets)
76          ...
77          } { TRLR }
78
79        or more clearly:
80
81          { HEAD
82            { SOUR genes
83              { VERS 1.6 }
84              { NAME Genes } }
85            { DATE 07 OCT 2001
86          ... }
87          { TRLR }
88
89        But because this means that one token is converted into a series
90        of tokens, there is some initial code following immediately here
91        that returns "pending" tokens. */
92
93 %{
94 char string_buf[MAXGEDCLINELEN+1];
95  
96 if (level_diff < 1) {
97   level_diff++;
98   return CLOSE;
99 }
100 else if (level_diff == 1) {
101   level_diff++;
102   return OPEN;
103 }
104 else {
105   /* out of brackets... */
106 }
107
108 #define TO_INTERNAL(str) to_internal(str, yyleng) 
109
110 #define MKTAGACTION(tag) \
111   { gedcom_lval.string = TO_INTERNAL(yytext); \
112     BEGIN(NORMAL); \
113     return TAG_##tag; }
114
115 %}
116
117 <INITIAL>{gen_delim}* /* ignore leading whitespace (also tabs) */
118
119 <INITIAL>\x00[0]{digit}+ { gedcom_error ("Level number with leading zero");
120                            return BADTOKEN;
121                          }
122
123 <INITIAL>{digit}+ { int level = atoi(TO_INTERNAL(yytext));
124                     if ((level < 0) || (level > MAXGEDCLEVEL)) {
125                       gedcom_error ("Level number out of range [0..%d]",
126                                     MAXGEDCLEVEL);
127                       return BADTOKEN;
128                     }
129                     level_diff = level - current_level;
130                     BEGIN(EXPECT_TAG);
131                     current_level = level;
132                     if (level_diff < 1) {
133                       level_diff++;
134                       return CLOSE;
135                     }
136                     else if (level_diff == 1) {
137                       level_diff++;
138                       return OPEN;
139                     }
140                     else {
141                       /* should never happen (error to GEDCOM spec) */
142                       gedcom_error ("GEDCOM level number is %d higher than "
143                                     "previous",
144                                     level_diff);
145                       return BADTOKEN;
146                     }
147                   }
148
149 <EXPECT_TAG>\x00A\x00B\x00B\x00R  MKTAGACTION(ABBR)
150 <EXPECT_TAG>\x00A\x00D\x00D\x00R  MKTAGACTION(ADDR)
151 <EXPECT_TAG>\x00A\x00D\x00R\x001  MKTAGACTION(ADR1)
152 <EXPECT_TAG>\x00A\x00D\x00R\x002  MKTAGACTION(ADR2)
153 <EXPECT_TAG>\x00A\x00D\x00O\x00P  MKTAGACTION(ADOP)
154 <EXPECT_TAG>\x00A\x00F\x00N   MKTAGACTION(AFN)
155 <EXPECT_TAG>\x00A\x00G\x00E   MKTAGACTION(AGE)
156 <EXPECT_TAG>\x00A\x00G\x00N\x00C  MKTAGACTION(AGNC)
157 <EXPECT_TAG>\x00A\x00L\x00I\x00A  MKTAGACTION(ALIA)
158 <EXPECT_TAG>\x00A\x00N\x00C\x00E  MKTAGACTION(ANCE)
159 <EXPECT_TAG>\x00A\x00N\x00C\x00I  MKTAGACTION(ANCI)
160 <EXPECT_TAG>\x00A\x00N\x00U\x00L  MKTAGACTION(ANUL)
161 <EXPECT_TAG>\x00A\x00S\x00S\x00O  MKTAGACTION(ASSO)
162 <EXPECT_TAG>\x00A\x00U\x00T\x00H  MKTAGACTION(AUTH)
163 <EXPECT_TAG>\x00B\x00A\x00P\x00L  MKTAGACTION(BAPL)
164 <EXPECT_TAG>\x00B\x00A\x00P\x00M  MKTAGACTION(BAPM)
165 <EXPECT_TAG>\x00B\x00A\x00R\x00M  MKTAGACTION(BARM)
166 <EXPECT_TAG>\x00B\x00A\x00S\x00M  MKTAGACTION(BASM)
167 <EXPECT_TAG>\x00B\x00I\x00R\x00T  MKTAGACTION(BIRT)
168 <EXPECT_TAG>\x00B\x00L\x00E\x00S  MKTAGACTION(BLES)
169 <EXPECT_TAG>\x00B\x00L\x00O\x00B  MKTAGACTION(BLOB)
170 <EXPECT_TAG>\x00B\x00U\x00R\x00I  MKTAGACTION(BURI)
171 <EXPECT_TAG>\x00C\x00A\x00L\x00N  MKTAGACTION(CALN)
172 <EXPECT_TAG>\x00C\x00A\x00S\x00T  MKTAGACTION(CAST)
173 <EXPECT_TAG>\x00C\x00A\x00U\x00S  MKTAGACTION(CAUS)
174 <EXPECT_TAG>\x00C\x00E\x00N\x00S  MKTAGACTION(CENS)
175 <EXPECT_TAG>\x00C\x00H\x00A\x00N  MKTAGACTION(CHAN)
176 <EXPECT_TAG>\x00C\x00H\x00A\x00R  MKTAGACTION(CHAR)
177 <EXPECT_TAG>\x00C\x00H\x00I\x00L  MKTAGACTION(CHIL)
178 <EXPECT_TAG>\x00C\x00H\x00R   MKTAGACTION(CHR)
179 <EXPECT_TAG>\x00C\x00H\x00R\x00A  MKTAGACTION(CHRA)
180 <EXPECT_TAG>\x00C\x00I\x00T\x00Y  MKTAGACTION(CITY)
181 <EXPECT_TAG>\x00C\x00O\x00N\x00C  MKTAGACTION(CONC)
182 <EXPECT_TAG>\x00C\x00O\x00N\x00F  MKTAGACTION(CONF)
183 <EXPECT_TAG>\x00C\x00O\x00N\x00L  MKTAGACTION(CONL)
184 <EXPECT_TAG>\x00C\x00O\x00N\x00T  MKTAGACTION(CONT)
185 <EXPECT_TAG>\x00C\x00O\x00P\x00R  MKTAGACTION(COPR)
186 <EXPECT_TAG>\x00C\x00O\x00R\x00P  MKTAGACTION(CORP)
187 <EXPECT_TAG>\x00C\x00R\x00E\x00M  MKTAGACTION(CREM)
188 <EXPECT_TAG>\x00C\x00T\x00R\x00Y  MKTAGACTION(CTRY)
189 <EXPECT_TAG>\x00D\x00A\x00T\x00A  MKTAGACTION(DATA)
190 <EXPECT_TAG>\x00D\x00A\x00T\x00E  MKTAGACTION(DATE)
191 <EXPECT_TAG>\x00D\x00E\x00A\x00T  MKTAGACTION(DEAT)
192 <EXPECT_TAG>\x00D\x00E\x00S\x00C  MKTAGACTION(DESC)
193 <EXPECT_TAG>\x00D\x00E\x00S\x00I  MKTAGACTION(DESI)
194 <EXPECT_TAG>\x00D\x00E\x00S\x00T  MKTAGACTION(DEST)
195 <EXPECT_TAG>\x00D\x00I\x00V   MKTAGACTION(DIV)
196 <EXPECT_TAG>\x00D\x00I\x00V\x00F  MKTAGACTION(DIVF)
197 <EXPECT_TAG>\x00D\x00S\x00C\x00R  MKTAGACTION(DSCR)
198 <EXPECT_TAG>\x00E\x00D\x00U\x00C  MKTAGACTION(EDUC)
199 <EXPECT_TAG>\x00E\x00M\x00I\x00G  MKTAGACTION(EMIG)
200 <EXPECT_TAG>\x00E\x00N\x00D\x00L  MKTAGACTION(ENDL)
201 <EXPECT_TAG>\x00E\x00N\x00G\x00A  MKTAGACTION(ENGA)
202 <EXPECT_TAG>\x00E\x00V\x00E\x00N  MKTAGACTION(EVEN)
203 <EXPECT_TAG>\x00F\x00A\x00M   MKTAGACTION(FAM)
204 <EXPECT_TAG>\x00F\x00A\x00M\x00C  MKTAGACTION(FAMC)
205 <EXPECT_TAG>\x00F\x00A\x00M\x00F  MKTAGACTION(FAMF)
206 <EXPECT_TAG>\x00F\x00A\x00M\x00S  MKTAGACTION(FAMS)
207 <EXPECT_TAG>\x00F\x00C\x00O\x00M  MKTAGACTION(FCOM)
208 <EXPECT_TAG>\x00F\x00I\x00L\x00E  MKTAGACTION(FILE)
209 <EXPECT_TAG>\x00F\x00O\x00R\x00M  MKTAGACTION(FORM)
210 <EXPECT_TAG>\x00G\x00E\x00D\x00C  MKTAGACTION(GEDC)
211 <EXPECT_TAG>\x00G\x00I\x00V\x00N  MKTAGACTION(GIVN)
212 <EXPECT_TAG>\x00G\x00R\x00A\x00D  MKTAGACTION(GRAD)
213 <EXPECT_TAG>\x00H\x00E\x00A\x00D  MKTAGACTION(HEAD)
214 <EXPECT_TAG>\x00H\x00U\x00S\x00B  MKTAGACTION(HUSB)
215 <EXPECT_TAG>\x00I\x00D\x00N\x00O  MKTAGACTION(IDNO)
216 <EXPECT_TAG>\x00I\x00M\x00M\x00I  MKTAGACTION(IMMI)
217 <EXPECT_TAG>\x00I\x00N\x00D\x00I  MKTAGACTION(INDI)
218 <EXPECT_TAG>\x00L\x00A\x00N\x00G  MKTAGACTION(LANG)
219 <EXPECT_TAG>\x00L\x00E\x00G\x00A  MKTAGACTION(LEGA)
220 <EXPECT_TAG>\x00M\x00A\x00R\x00B  MKTAGACTION(MARB)
221 <EXPECT_TAG>\x00M\x00A\x00R\x00C  MKTAGACTION(MARC)
222 <EXPECT_TAG>\x00M\x00A\x00R\x00L  MKTAGACTION(MARL)
223 <EXPECT_TAG>\x00M\x00A\x00R\x00R  MKTAGACTION(MARR)
224 <EXPECT_TAG>\x00M\x00A\x00R\x00S  MKTAGACTION(MARS)
225 <EXPECT_TAG>\x00M\x00E\x00D\x00I  MKTAGACTION(MEDI)
226 <EXPECT_TAG>\x00N\x00A\x00M\x00E  MKTAGACTION(NAME)
227 <EXPECT_TAG>\x00N\x00A\x00T\x00I  MKTAGACTION(NATI)
228 <EXPECT_TAG>\x00N\x00A\x00T\x00U  MKTAGACTION(NATU)
229 <EXPECT_TAG>\x00N\x00C\x00H\x00I  MKTAGACTION(NCHI)
230 <EXPECT_TAG>\x00N\x00I\x00C\x00K  MKTAGACTION(NICK)
231 <EXPECT_TAG>\x00N\x00M\x00R   MKTAGACTION(NMR)
232 <EXPECT_TAG>\x00N\x00O\x00T\x00E  MKTAGACTION(NOTE)
233 <EXPECT_TAG>\x00N\x00P\x00F\x00X  MKTAGACTION(NPFX)
234 <EXPECT_TAG>\x00N\x00S\x00F\x00X  MKTAGACTION(NSFX)
235 <EXPECT_TAG>\x00O\x00B\x00J\x00E  MKTAGACTION(OBJE)
236 <EXPECT_TAG>\x00O\x00C\x00C\x00U  MKTAGACTION(OCCU)
237 <EXPECT_TAG>\x00O\x00R\x00D\x00I  MKTAGACTION(ORDI)
238 <EXPECT_TAG>\x00O\x00R\x00D\x00N  MKTAGACTION(ORDN)
239 <EXPECT_TAG>\x00P\x00A\x00G\x00E  MKTAGACTION(PAGE)
240 <EXPECT_TAG>\x00P\x00E\x00D\x00I  MKTAGACTION(PEDI)
241 <EXPECT_TAG>\x00P\x00H\x00O\x00N  MKTAGACTION(PHON)
242 <EXPECT_TAG>\x00P\x00L\x00A\x00C  MKTAGACTION(PLAC)
243 <EXPECT_TAG>\x00P\x00O\x00S\x00T  MKTAGACTION(POST)
244 <EXPECT_TAG>\x00P\x00R\x00O\x00B  MKTAGACTION(PROB)
245 <EXPECT_TAG>\x00P\x00R\x00O\x00P  MKTAGACTION(PROP)
246 <EXPECT_TAG>\x00P\x00U\x00B\x00L  MKTAGACTION(PUBL)
247 <EXPECT_TAG>\x00Q\x00U\x00A\x00Y  MKTAGACTION(QUAY)
248 <EXPECT_TAG>\x00R\x00E\x00F\x00N  MKTAGACTION(REFN)
249 <EXPECT_TAG>\x00R\x00E\x00L\x00A  MKTAGACTION(RELA)
250 <EXPECT_TAG>\x00R\x00E\x00L\x00I  MKTAGACTION(RELI)
251 <EXPECT_TAG>\x00R\x00E\x00P\x00O  MKTAGACTION(REPO)
252 <EXPECT_TAG>\x00R\x00E\x00S\x00I  MKTAGACTION(RESI)
253 <EXPECT_TAG>\x00R\x00E\x00S\x00N  MKTAGACTION(RESN)
254 <EXPECT_TAG>\x00R\x00E\x00T\x00I  MKTAGACTION(RETI)
255 <EXPECT_TAG>\x00R\x00F\x00N   MKTAGACTION(RFN)
256 <EXPECT_TAG>\x00R\x00I\x00N   MKTAGACTION(RIN)
257 <EXPECT_TAG>\x00R\x00O\x00L\x00E  MKTAGACTION(ROLE)
258 <EXPECT_TAG>\x00S\x00E\x00X   MKTAGACTION(SEX)
259 <EXPECT_TAG>\x00S\x00L\x00G\x00C  MKTAGACTION(SLGC)
260 <EXPECT_TAG>\x00S\x00L\x00G\x00S  MKTAGACTION(SLGS)
261 <EXPECT_TAG>\x00S\x00O\x00U\x00R  MKTAGACTION(SOUR)
262 <EXPECT_TAG>\x00S\x00P\x00F\x00X  MKTAGACTION(SPFX)
263 <EXPECT_TAG>\x00S\x00S\x00N   MKTAGACTION(SSN)
264 <EXPECT_TAG>\x00S\x00T\x00A\x00E  MKTAGACTION(STAE)
265 <EXPECT_TAG>\x00S\x00T\x00A\x00T  MKTAGACTION(STAT)
266 <EXPECT_TAG>\x00S\x00U\x00B\x00M  MKTAGACTION(SUBM)
267 <EXPECT_TAG>\x00S\x00U\x00B\x00N  MKTAGACTION(SUBN)
268 <EXPECT_TAG>\x00S\x00U\x00R\x00N  MKTAGACTION(SURN)
269 <EXPECT_TAG>\x00T\x00E\x00M\x00P  MKTAGACTION(TEMP)
270 <EXPECT_TAG>\x00T\x00E\x00X\x00T  MKTAGACTION(TEXT)
271 <EXPECT_TAG>\x00T\x00I\x00M\x00E  MKTAGACTION(TIME)
272 <EXPECT_TAG>\x00T\x00I\x00T\x00L  MKTAGACTION(TITL)
273 <EXPECT_TAG>\x00T\x00R\x00L\x00R  MKTAGACTION(TRLR)
274 <EXPECT_TAG>\x00T\x00Y\x00P\x00E  MKTAGACTION(TYPE)
275 <EXPECT_TAG>\x00V\x00E\x00R\x00S  MKTAGACTION(VERS)
276 <EXPECT_TAG>\x00W\x00I\x00F\x00E  MKTAGACTION(WIFE)
277 <EXPECT_TAG>\x00W\x00I\x00L\x00L  MKTAGACTION(WILL)
278      
279 <EXPECT_TAG>{alphanum}+ { if (strlen(yytext) > MAXGEDCTAGLEN) {
280                             gedcom_error("Tag '%s' too long, max %d chars");
281                             return BADTOKEN;
282                           }
283                           strncpy(string_buf, yytext, MAXGEDCTAGLEN+1);
284                           gedcom_lval.string = TO_INTERNAL(string_buf);
285                           BEGIN(NORMAL);
286                           return USERTAG;
287                         }
288
289 {delim}      { gedcom_lval.string = TO_INTERNAL(yytext);
290                return DELIM;
291              }
292
293 {any_but_delim} { gedcom_lval.string = TO_INTERNAL(yytext);
294                   return ANYCHAR;
295                 }
296
297 {escape}/{non_at}  { gedcom_lval.string = TO_INTERNAL(yytext);
298                      return ESCAPE;
299                    }
300
301 {pointer}    { gedcom_lval.string = TO_INTERNAL(yytext);
302                return POINTER;
303              }
304
305    /* Due to the conversion of level numbers into brackets, the
306       terminator is not important, so no token is returned here.
307       Although not strictly according to the GEDCOM spec, we'll ignore
308       whitespace just before the terminator.
309    */
310
311 {gen_delim}*{terminator} { line_no++; BEGIN(INITIAL); }
312
313    /* Eventually we have to return 1 closing bracket (for the trailer).
314       We can detect whether we have sent the closing bracket using the
315       level_diff (at eof, first it is 2, then we increment it ourselves) */
316
317 <<EOF>> { if (level_diff == 2) {
318             level_diff++;
319             return CLOSE;
320           }
321           else {
322             yyterminate();
323           }
324         } 
325
326 .  { gedcom_error("Unexpected character: '%s' (0x%02x)",
327                   yytext, yytext[0]);
328      return BADTOKEN;
329    }
330
331 %%
332
333 int yywrap()
334 {
335   return 1;
336 }
337
338 #ifdef LEXER_TEST
339
340 int main()
341 {
342   int tok, res;
343   init_encodings();
344   set_encoding_width(TWO_BYTE_HILO);
345   res = open_conv_to_internal("UNICODE");
346   if (!res) {
347     gedcom_error("Unable to open conversion context: %s",
348                  strerror(errno));
349     return 1;
350   }
351   tok = gedcom_hilo_lex();
352   while (tok) {
353     switch(tok) {
354       case BADTOKEN: printf("BADTOKEN "); break;
355       case OPEN: printf("OPEN "); break;
356       case CLOSE: printf("CLOSE "); break;
357       case ESCAPE: printf("ESCAPE(%s) ", gedcom_lval.string); break;
358       case DELIM: printf("DELIM "); break;
359       case ANYCHAR: printf("%s ", gedcom_lval.string); break;
360       case POINTER: printf("POINTER(%s) ", gedcom_lval.string); break;
361       case USERTAG: printf("USERTAG(%s) ", gedcom_lval.string); break;
362       default: printf("TAG(%s) ", gedcom_lval.string); break;
363     }
364     tok = gedcom_hilo_lex();
365   }
366   printf("\n");
367   close_conv_to_internal();
368   return 0;
369 }
370 #endif