added more items.
[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 store(enum type_t type, int line, int column, char*text, int length)
33 {
34     struct token_t token;
35     string_t tmp;
36     token.type = type;
37     token.line = line;
38     token.column = column;
39     //printf("->%d(%s) %s\n", type, type_names[type], text);fflush(stdout);
40
41     token.text = 0;
42     switch(type) {
43         case END:
44             string_set2(&tmp, "", 0);
45             token.text = (char*)mem_putstring(&strings, tmp);
46         break;
47         case STRING:
48             string_set2(&tmp, text+1, length-2);
49             token.text = (char*)mem_putstring(&strings, tmp);
50         break;
51         case TWIP: 
52         case NUMBER: 
53         case IDENTIFIER:
54             string_set2(&tmp, text, length);
55             if(prefix) {
56                 //strcat
57                 token.text = (char*)mem_put(&strings, prefix, strlen(prefix));
58                 mem_putstring(&strings, tmp);
59             } else {
60                 token.text = (char*)mem_putstring(&strings, tmp);
61             }
62             prefix = 0;
63         break;
64         case LABEL:
65             string_set2(&tmp, text, length-1);
66             token.text = (char*)mem_putstring(&strings, tmp);
67         break;
68         case COMMAND:
69             string_set2(&tmp, text+1, length-1);
70             token.text = (char*)mem_putstring(&strings, tmp);
71         break;
72         case ASSIGNMENT: {
73             char*x = &text[length-1];
74             if(x[-1] == '-' || x[-1] == '+')
75                 x--;
76             do{x--;} while(*x==32 || *x==10 || *x==13 || *x=='\t');
77             x++; //first space
78             string_set2(&tmp, text, x-text);
79             token.text = (char*)mem_putstring(&strings, tmp);
80             /*char*y,*x = strchr(text, '=');
81             if(!x) exit(1);
82             y=x;
83             do{y--;} while(*y==32 || *y==10 || *y==13 || *y=='\t');
84             do{x++;} while(*x==32 || *x==10 || *x==13 || *x=='\t');
85             token.text1 = (char*)put(&strings, text, y-text + 1, 1);
86             token.text2 = (char*)put(&strings, x, length-(x-text), 1);*/
87         } break;
88     }
89
90     mem_put(&tokens, &token, sizeof(struct token_t));
91     prefix = 0;
92 }
93
94 #define c() {count(yytext, yyleng, YY_START);}
95 #define s(type) {store(type, line, column, yytext, yyleng);}
96 %}
97
98 %s R
99 %x BINARY
100
101 NAME     [a-zA-Z_./](-*[a-zA-Z0-9_./])*
102 TWIP     ([0-9]+(\.([0-9]([05])?)?)?)
103 NUMBER   [0-9]+(\.[0-9]*)?
104 PERCENT  {NUMBER}%
105 STRING   (\\.|[^\\"\n])*
106 S        [ \n\r\t]
107 RVALUE   \"{STRING}\"|([^ \n\r\t]+)
108
109 %%
110
111 <BINARY>\] {c();BEGIN(0);}
112 <BINARY>.  {c();}
113 <BINARY>\n {c();}
114 {TWIP}/[ \n\r\t]            {s(TWIP);c();BEGIN(0);}
115 {NUMBER}/[ \n\r\t]          {s(NUMBER);c();BEGIN(0);}
116 ^#[^\n]*\n                  {c();}
117 [ \t\r]#[^\n]*\n            {c();}
118 \"{STRING}\"                {s(STRING);c();BEGIN(0);}
119 \"{STRING}$                 {c();printf("unterminated string in line %d: %s\n", line, yytext);exit(1);yyterminate();}
120 {NAME}{S}*\+=               {s(ASSIGNMENT);prefix="<plus>";c();BEGIN(R);}
121 {NAME}{S}*-=                {s(ASSIGNMENT);prefix="<minus>";c();BEGIN(R);}
122 {NAME}{S}*=                 {s(ASSIGNMENT);c();BEGIN(R);}
123 <R>{ /* values which appear only on the right-hand side of assignments, like: x=50% */
124     [^ \n\t\r]*             {s(IDENTIFIER);c();BEGIN(0);}
125 }
126 \.{NAME}                    {s(COMMAND);c();}
127 {NAME}{S}*:                 {s(LABEL);c();}
128 {NAME}                      {s(IDENTIFIER);c();}
129 "["                         {c();BEGIN(BINARY);}
130 {S}                         {c();}
131 .                           {char c,c1=0;
132                              printf("Syntax error in line %d, %d: %s", line, column, yytext);
133                              while(1) {
134                                  c=input();
135                                  if(!c1) c1=c;
136                                  if(c=='\n' || c==EOF) 
137                                      break;
138                                 printf("%c", c);
139                              }
140                              if(c1>='0' && c1<='9')
141                                  printf(" (identifiers must not start with a digit)");
142                              printf("\n");
143                              exit(1);
144                              yyterminate();
145                             }
146 <<EOF>>                     {c();s(END);yyterminate();}
147 %%
148
149 int yywrap()
150 {
151     return 1;
152 }
153
154 void freeTokens(struct token_t*file)
155 {
156     mem_clear(&strings);
157     mem_clear(&tokens);
158 }
159
160 struct token_t* generateTokens(char*filename)
161 {
162     FILE*fi = fopen(filename, "rb");
163     int t;
164     struct token_t*result;
165     int num;
166     if(!fi) {
167         printf("Couldn't find file %s\n", filename);
168         return 0;
169     }
170     yyin = fi;
171
172     mem_init(&strings);
173     mem_init(&tokens);
174     mem_put(&strings, &t, 1); //hack- make all valid strings start at position >0
175
176     line=1;
177     column=1;
178
179     yylex();
180     yy_delete_buffer(yy_current_buffer);
181
182     result = (struct token_t*)tokens.buffer;
183     num = tokens.pos/sizeof(struct token_t);
184
185     for(t=0;t<tokens.pos/sizeof(struct token_t);t++) {
186         if(result[t].text)
187             result[t].text += (int)strings.buffer;
188     }
189
190     fclose(fi);
191     return result;
192 }
193