added ringbuffer routines.
[swftools.git] / src / parser.lex
1 %{
2
3 #include <string.h>
4 #include "q.h"
5 #include "parser.h"
6
7 //RVALUE         {NUMBER}|{PERCENT}|{NAME}|\"{STRING}\"|{DIM}
8 //<a>.                {printf("<a>%s\n", yytext);}
9 // %x: exclusive, %s: inclusive
10 char*type_names[] = {"twip","number","command","string","assignment","identifier","label","end"};
11 static int line=1;
12 static int column=1;
13
14 mem_t strings;
15 mem_t tokens;
16
17 static void count(char*text, int len, int condition)
18 {
19     int t;
20     for(t=0;t<len;t++) {
21         if(text[t]=='\n') {
22             line++;
23             column=1;
24         } else {
25             column++;
26         }
27     }
28 }
29
30 static char*prefix = 0;
31
32 static void unescapeString(string_t * tmp)
33 {
34     char *p, *p1;
35     /* fixme - this routine expects the string to be
36        null-terminated */
37
38     for (p1=tmp->str; (p=strchr(p1, '\\')); p1 = p+1) 
39     {
40         switch(p[1])
41         {
42             case '\\': p[1] = '\\'; tmp->len--; break;
43             case '"': p[1] = '"'; tmp->len--; break;
44             case 'b': p[1] = '\b'; tmp->len--; break;
45             case 'f': p[1] = '\f'; tmp->len--; break;
46             case 'n': p[1] = '\n'; tmp->len--; break;
47             case 'r': p[1] = '\r'; tmp->len--; break;
48             case 't': p[1] = '\t'; tmp->len--; break;
49             default:
50                 continue;
51         }
52         strcpy(p, p+1);
53     }
54 }
55
56 static void store(enum type_t type, int line, int column, char*text, int length)
57 {
58     struct token_t token;
59     string_t tmp;
60     token.type = type;
61     token.line = line;
62     token.column = column;
63     //printf("->%d(%s) %s\n", type, type_names[type], text);fflush(stdout);
64
65     token.text = 0;
66     switch(type) {
67         case END:
68             string_set2(&tmp, "", 0);
69             token.text = (char*)mem_putstring(&strings, tmp);
70         break;
71         case STRING:
72             string_set2(&tmp, text+1, length-2);
73             unescapeString(&tmp);
74             token.text = (char*)mem_putstring(&strings, tmp);
75         break;
76         case TWIP: 
77         case NUMBER: 
78         case IDENTIFIER:
79             string_set2(&tmp, text, length);
80             if(prefix) {
81                 //strcat
82                 token.text = (char*)mem_put(&strings, prefix, strlen(prefix));
83                 mem_putstring(&strings, tmp);
84             } else {
85                 token.text = (char*)mem_putstring(&strings, tmp);
86             }
87             prefix = 0;
88         break;
89         case LABEL:
90             string_set2(&tmp, text, length-1);
91             token.text = (char*)mem_putstring(&strings, tmp);
92         break;
93         case COMMAND:
94             string_set2(&tmp, text+1, length-1);
95             token.text = (char*)mem_putstring(&strings, tmp);
96         break;
97         case ASSIGNMENT: {
98             char*x = &text[length-1];
99             if(x[-1] == '-' || x[-1] == '+')
100                 x--;
101             do{x--;} while(*x==32 || *x==10 || *x==13 || *x=='\t');
102             x++; //first space
103             string_set2(&tmp, text, x-text);
104             token.text = (char*)mem_putstring(&strings, tmp);
105             /*char*y,*x = strchr(text, '=');
106             if(!x) exit(1);
107             y=x;
108             do{y--;} while(*y==32 || *y==10 || *y==13 || *y=='\t');
109             do{x++;} while(*x==32 || *x==10 || *x==13 || *x=='\t');
110             token.text1 = (char*)put(&strings, text, y-text + 1, 1);
111             token.text2 = (char*)put(&strings, x, length-(x-text), 1);*/
112         } break;
113     }
114
115     mem_put(&tokens, &token, sizeof(struct token_t));
116     prefix = 0;
117 }
118
119 #define c() {count(yytext, yyleng, YY_START);}
120 #define s(type) {store(type, line, column, yytext, yyleng);}
121 %}
122
123 %s R
124 %x BINARY
125
126 NAME     [a-zA-Z_./](-*[a-zA-Z0-9_./])*
127 TWIP     ([0-9]+(\.([0-9]([05])?)?)?)
128 NUMBER   [0-9]+(\.[0-9]*)?
129 PERCENT  {NUMBER}%
130 STRING   (\\.|[^\\"\n])*
131 S        [ \n\r\t]
132 RVALUE   \"{STRING}\"|([^ \n\r\t]+)
133
134 %%
135
136 <BINARY>\] {c();BEGIN(0);}
137 <BINARY>.  {c();}
138 <BINARY>\n {c();}
139 {TWIP}/[ \n\r\t]            {s(TWIP);c();BEGIN(0);}
140 {NUMBER}/[ \n\r\t]          {s(NUMBER);c();BEGIN(0);}
141 ^#[^\n]*\n                  {c();}
142 [ \t\r]#[^\n]*\n            {c();}
143 \"{STRING}\"                {s(STRING);c();BEGIN(0);}
144 \"{STRING}$                 {c();printf("unterminated string in line %d: %s\n", line, yytext);exit(1);yyterminate();}
145 {NAME}{S}*\+=               {s(ASSIGNMENT);prefix="<plus>";c();BEGIN(R);}
146 {NAME}{S}*-=                {s(ASSIGNMENT);prefix="<minus>";c();BEGIN(R);}
147 {NAME}{S}*=                 {s(ASSIGNMENT);c();BEGIN(R);}
148 <R>{ /* values which appear only on the right-hand side of assignments, like: x=50% */
149     [^ \n\t\r]*             {s(IDENTIFIER);c();BEGIN(0);}
150 }
151 \.{NAME}                    {s(COMMAND);c();}
152 {NAME}{S}*:                 {s(LABEL);c();}
153 {NAME}                      {s(IDENTIFIER);c();}
154 "["                         {c();BEGIN(BINARY);}
155 {S}                         {c();}
156 .                           {char c,c1=yytext[0];
157                              printf("Syntax error in line %d, %d: %s", line, column, yytext);
158                              while(1) {
159                                  c=input();
160                                  if(c=='\n' || c==EOF) 
161                                      break;
162                                 printf("%c", c);
163                              }
164                              if(c1>='0' && c1<='9')
165                                  printf(" (identifiers must not start with a digit)");
166                              printf("\n");
167                              exit(1);
168                              yyterminate();
169                             }
170 <<EOF>>                     {c();s(END);yyterminate();}
171 %%
172
173 int yywrap()
174 {
175     return 1;
176 }
177
178 void freeTokens(struct token_t*file)
179 {
180     mem_clear(&strings);
181     mem_clear(&tokens);
182 }
183
184 struct token_t* generateTokens(char*filename)
185 {
186     FILE*fi = fopen(filename, "rb");
187     int t;
188     struct token_t*result;
189     int num;
190     if(!fi) {
191         printf("Couldn't find file %s\n", filename);
192         return 0;
193     }
194     yyin = fi;
195
196     mem_init(&strings);
197     mem_init(&tokens);
198     mem_put(&strings, &t, 1); //hack- make all valid strings start at position >0
199
200     line=1;
201     column=1;
202
203     yylex();
204     yy_delete_buffer(yy_current_buffer);
205
206     result = (struct token_t*)tokens.buffer;
207     num = tokens.pos/sizeof(struct token_t);
208
209     for(t=0;t<tokens.pos/sizeof(struct token_t);t++) {
210         if(result[t].text)
211             result[t].text += (int)strings.buffer;
212     }
213
214     fclose(fi);
215     return result;
216 }
217