root/src/noit_tokenizer.re

Revision 37cf7d8f9e336376dc0ecdb1b80e4776721a950b, 4.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 7 years ago)

A 'simple' tokenizer to help us with the console

  • Property mode set to 100644
Line 
1 #include <stdlib.h>
2 #include <string.h>
3
4 struct token {
5   char *token;
6   const char *start;
7   const char *end;
8   const char *next;
9   enum { NT_IDENT, NT_DQSTRING, NT_SPACE, NT_UNKNOWN, NT_EOF } type;
10 };
11 #define SET_TOKEN(t,a) (t)->next = (a)
12
13 static void c_unescape(char *p, char *only) {
14   char *bt = p;
15 #define ASSIGN(a) *(bt++) = (a)
16   while(p[0] != '\0') {
17     if(p[0] == '\\' && p[1] != '\0' && (!only || p[1] == *only)) {
18       switch(p[1]) {
19         case ' ': ASSIGN(' '); p+=2; break;
20         case '"': ASSIGN('"'); p+=2; break;
21         case 'n': ASSIGN('\n'); p+=2; break;
22         case 'r': ASSIGN('\r'); p+=2; break;
23         case 't': ASSIGN('\t'); p+=2; break;
24         case 'a': ASSIGN('\a'); p+=2; break;
25         case 'b': ASSIGN('\b'); p+=2; break;
26         case 'v': ASSIGN('\v'); p+=2; break;
27         case 'f': ASSIGN('\f'); p+=2; break;
28         case '0': ASSIGN('\0'); p+=2; break;
29         case '\\': ASSIGN('\\'); p+=2; break;
30         default: ASSIGN(*p); p++; ASSIGN(*p); p++; break;
31       }
32     }
33     else {
34       ASSIGN(*p); p++;
35     }
36   }
37   *bt = '\0';
38 }
39
40 #define BAIL_UNKNOWN do { t->type = NT_UNKNOWN; return -1; } while(0)
41 static int token_scan(struct token *t)
42 {
43   t->start = t->end = t->next;
44
45  mainpattern:
46 /*!re2c
47     re2c:define:YYCTYPE  = "unsigned char";
48     re2c:define:YYCURSOR = t->next;
49     re2c:yyfill:enable   = 0;
50     re2c:yych:conversion = 1;
51     re2c:indent:top      = 1;
52
53     [ \t\r\n]+      { t->token = NULL;
54                       t->end = t->next;
55                       t->type = NT_SPACE;
56                       return 1; }
57     ["]             { t->type = NT_DQSTRING;
58                       if(t->start != t->end) {
59                         t->start++;
60                         t->end = t->next - 1;
61                         t->token = malloc(t->end-t->start + 1);
62                         strlcpy(t->token, t->start, t->end-t->start + 1);
63                         c_unescape(t->token, NULL);
64                         return 1;
65                       }
66                       else
67                         goto dqstring;
68                     }
69     "'"             { t->type = NT_IDENT;
70                       if(t->start != t->end) {
71                         t->start++;
72                         t->end = t->next - 1;
73                         t->token = malloc(t->end-t->start + 1);
74                         strlcpy(t->token, t->start, t->end-t->start + 1);
75                         return 1;
76                       }
77                       else
78                         goto sqstring;
79                     }
80     [^\000'" \t\r\n] ([^\000 \t\r\n]|[\\][ ])*
81                     { char only = ' ';
82                       t->end = t->next;
83                       t->type = NT_IDENT;
84                       t->token = malloc(t->end-t->start + 1);
85                       strlcpy(t->token, t->start, t->end-t->start + 1);
86                       c_unescape(t->token, &only);
87                       return 1;
88                     }
89     [\000]          { t->token = NULL;
90                       t->type = NT_EOF;
91                       return 0;
92                     }
93     [\000-\377]     { BAIL_UNKNOWN; }
94 */
95
96  sqstring:
97 /*!re2c
98     [^'\000]*       { t->end = t->next;
99                       goto mainpattern; }
100     [\000]          { BAIL_UNKNOWN; }
101 */
102
103  dqstring:
104 /*!re2c
105     [\\][nrtabvf0"\\]
106                     { goto dqstring; }
107     "\\" ( [^\000] \ [nrtabvf0"\\] )
108                     { goto dqstring; }
109     ["]             { t->end = t->next--;
110                       goto mainpattern;
111                     }
112     [^"\000]\[\\"]  { goto dqstring; }
113     [\000]          { BAIL_UNKNOWN; }
114 */
115 }
116
117 int noit_tokenize(const char *input, char **vector, int *cnt) {
118   struct token t;
119   int i = 0;
120
121   SET_TOKEN(&t, input);
122   while(token_scan(&t) != -1) {
123     switch(t.type) {
124       case NT_IDENT:
125       case NT_DQSTRING:
126         if(i<*cnt) vector[i] = t.token;
127         i++;
128         break;
129       case NT_SPACE:
130         break;
131       case NT_EOF:
132         if(i<*cnt) *cnt = i;
133         return i;
134       case NT_UNKNOWN:
135         /* UNREACHED */
136         goto failure;
137     }
138   }
139  failure:
140   if(i<*cnt) *cnt = i;
141   return input - t.next;
142 }
Note: See TracBrowser for help on using the browser.