summaryrefslogtreecommitdiff
path: root/hyp2mat/lib/scan.ll
blob: 3e07902a3e66aa1487503f9011714d455820bc40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/*
 * hyp2mat - convert hyperlynx files to matlab scripts
 * Copyright 2012 Koen De Vleeschauwer.
 *
 * This file is part of hyp2mat.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

%option noyywrap nodefault yylineno debug

%{
#include <stdlib.h>
#include "parse.h"
#include "parser.h"

/* copy a string between quotes */
char *strunquote(const char *);

/* remember hyperlynx file section we're in */
int section = -1;

%}

 /*
  * The scanner knows five states: INITIAL, STATE_STRING, STATE_POSINT, STATE_FLOAT and STATE_COMMENT
  *
  * In state INITIAL the scanner recognizes:
  * - punctuation (such as {}()=, )
  * - keywords (such as VERSION, BOARD, NET), 
  * - strings (both between double quotes " and unquoted),
  * - and floating point numbers (with optional suffix, eg. 10 uF), 
  *
  * In STATE_STRING the scanner recognizes punctuation and strings only.
  * This avoids unquoted strings being interpreted as numbers, or keywords.
  *
  * In STATE_POSINT the scanner recognizes a positive integer.
  *
  * In STATE_FLOAT the scanner recognizes a floating point number (without suffix).
  *
  * In STATE_COMMENT the scanner discards all text up to the next 
  * right brace } , and then continues in state INITIAL.
  *
  */

%x STATE_STRING STATE_POSINT STATE_FLOAT STATE_COMMENT STATE_COMMENT_EOL

 /* whitespace: space, tab, vertical tab, form feed */
WS                  [ \t\v\f]

 /* accept windows and unix newlines */
NEWLINE             [\r\n]+

 /* 
  * lines with an asterisk in the first column are comments 
  */
COMMENT             ^\*[^\n\r]*[\n\r]+

 /* Left-hand side of an assignment: check whether next token is equals sign */
LHS                 [ \t\v\f]*"="

 /*
  * Positive integer
  */

POSINT              [0-9]+

 /*
  * Floating point numbers
  */

 /* ordinary floating point numbers */
SIMPLE_FLOAT        [-+]?([0-9]+"."[0-9]*|"."?[0-9]+)([Ee][-+]?[0-9]+)?

 /* floating point numbers with suffix, e,g. pF, nH */
FLOAT_SUFFIX        [A-Za-z]*{WS}+
FLOAT_YOTTA         {SIMPLE_FLOAT}{WS}*"Y"{FLOAT_SUFFIX}
FLOAT_ZETA          {SIMPLE_FLOAT}{WS}*"Z"{FLOAT_SUFFIX}
FLOAT_EXA           {SIMPLE_FLOAT}{WS}*"E"{FLOAT_SUFFIX}
FLOAT_PETA          {SIMPLE_FLOAT}{WS}*"P"{FLOAT_SUFFIX}
FLOAT_TERA          {SIMPLE_FLOAT}{WS}*"T"{FLOAT_SUFFIX}
FLOAT_GIGA          {SIMPLE_FLOAT}{WS}*"G"{FLOAT_SUFFIX}
FLOAT_MEGA          {SIMPLE_FLOAT}{WS}*"M"{FLOAT_SUFFIX}
FLOAT_KILO          {SIMPLE_FLOAT}{WS}*[Kk]{FLOAT_SUFFIX}
FLOAT_MILLI         {SIMPLE_FLOAT}{WS}*"m"{FLOAT_SUFFIX}
FLOAT_MICRO         {SIMPLE_FLOAT}{WS}*[uU]{FLOAT_SUFFIX}
FLOAT_NANO          {SIMPLE_FLOAT}{WS}*[nN]{FLOAT_SUFFIX}
FLOAT_PICO          {SIMPLE_FLOAT}{WS}*[pP]{FLOAT_SUFFIX}
FLOAT_FEMTO         {SIMPLE_FLOAT}{WS}*[fF]{FLOAT_SUFFIX}
FLOAT_ATTO          {SIMPLE_FLOAT}{WS}*"a"{FLOAT_SUFFIX}
FLOAT_ZEPTO         {SIMPLE_FLOAT}{WS}*"z"{FLOAT_SUFFIX}
FLOAT_YOCTO         {SIMPLE_FLOAT}{WS}*"y"{FLOAT_SUFFIX}
  
 /* 
  * Strings
  */

 /* an unquoted string */
STRING              [^ \t\v\f\r\n\{\}\(\)=\"]+

 /* a string enclosed in double quotes " */
QUOTED_STRING       \"([^\"\n]|\"\")*\"

%%

 /* When in STATE_COMMENT skip all comment until next right brace */
<STATE_COMMENT>{
[^\}]*              { BEGIN INITIAL; /* skip all comment until next right brace */ }
}

 /* When in STATE_COMMENT_EOL skip all comment until end-of-line */
<STATE_COMMENT_EOL>{
[^\r\n]*{NEWLINE}+ { BEGIN INITIAL; /* skip all comment until next end-of-line */ }
}


 /* skip comments and whitespace */
<*>{

  {COMMENT}           { /* skip comments */ }

  {WS}+               { /* skip whitespace */ }

  {NEWLINE}+          { /* skip newlines */ }

}

 /*
  * Hyperlynx keywords 
  */

 /* Sections */

"BOARD_FILE"        {section = BOARD_FILE; return BOARD_FILE;}
"VERSION"           {section = VERSION; return VERSION;}
"DATA_MODE"         {section = DATA_MODE; return DATA_MODE;}
"UNITS"             {section = UNITS; return UNITS;}
"PLANE_SEP"         {section = PLANE_SEP; return PLANE_SEP;}
"BOARD"             {section = BOARD; BEGIN STATE_COMMENT_EOL; return BOARD;}
"STACKUP"           {section = STACKUP; BEGIN STATE_COMMENT_EOL; return STACKUP;}
"DEVICES"           {section = DEVICES; BEGIN STATE_COMMENT_EOL; return DEVICES;}
"SUPPLIES"          {section = SUPPLIES; BEGIN STATE_COMMENT_EOL; return SUPPLIES;}
"PADSTACK"          {section = PADSTACK; BEGIN STATE_STRING; return PADSTACK;}
"NET"               {section = NET; BEGIN STATE_STRING; return NET;}
"NET_CLASS"         {section = NET_CLASS; return NET_CLASS;}
"END"               {section = END; return END;}
"KEY"               {section = KEY; return KEY;}

 /* Keywords */

"A"                 {return A;}
"ARC"               {return ARC;}
"COPPER"            {return COPPER;}
"CURVE"             {return CURVE;}
"DETAILED"          {if (section == DATA_MODE) BEGIN STATE_COMMENT; return DETAILED;}
"DIELECTRIC"        {return DIELECTRIC;}
"ENGLISH"           {return ENGLISH;}
"LENGTH"            {if (section == UNITS) BEGIN STATE_COMMENT; return LENGTH;}
"LINE"              {return LINE;}
"METRIC"            {return METRIC;}
"M"                 {return M;}
"N"                 {return N;}
"OPTIONS"           {return OPTIONS;}
"PAD"               {return PAD;}
"PERIMETER_ARC"     {return PERIMETER_ARC;}
"PERIMETER_SEGMENT" {return PERIMETER_SEGMENT;}
"PIN"               {return PIN;}
"PLANE"             {return PLANE;}
"POLYGON"           {return POLYGON;}
"POLYLINE"          {return POLYLINE;}
"POLYVOID"          {return POLYVOID;}
"POUR"              {return POUR;}
"S"                 {return S;}
"T"                 {return T;}
"SEG"               {return SEG;}
"SIGNAL"            {return SIGNAL;}
"SIMPLIFIED"        {if (section == DATA_MODE) BEGIN STATE_COMMENT; return SIMPLIFIED; }
"SIM_BOTH"          {return SIM_BOTH;}
"SIM_IN"            {return SIM_IN;}
"SIM_OUT"           {return SIM_OUT;}
"USEG"              {return USEG;}
"VIA"               {return VIA;}
"WEIGHT"            {if (section == UNITS) BEGIN STATE_COMMENT; return WEIGHT;}

 /* Assignments */

"A"/{LHS}           {return A;}
"A1"/{LHS}          {return A1;}
"A2"/{LHS}          {return A2;}
"BR"/{LHS}          {return BR;}
"C"/{LHS}           {return C;}
"C?"/{LHS}          {return C_QM;}
"CO?"/{LHS}         {return CO_QM;}
"D"/{LHS}           {return D;}
"ER"/{LHS}          {return ER;}
"F"/{LHS}           {return F;}
"ID"/{LHS}          {BEGIN STATE_POSINT; return ID;}
"L"/{LHS}           {BEGIN STATE_STRING; return L;}
"L1"/{LHS}          {BEGIN STATE_STRING; return L1;}
"L2"/{LHS}          {BEGIN STATE_STRING; return L2;}
"LPS"/{LHS}         {return LPS;}
"LT"/{LHS}          {return LT;}
"M"/{LHS}           {BEGIN STATE_STRING; return M;}
"N"/{LHS}           {BEGIN STATE_STRING; return N;}
"NAME"/{LHS}        {BEGIN STATE_STRING; return NAME;}
 /* P is used as "plating thickness" in "stackup/signal" and as "padstack" in "net/via" */
"P"/{LHS}           {if (section == NET) BEGIN STATE_STRING; return P;}
"PKG"/{LHS}         {BEGIN STATE_STRING; return PKG;}
"PR?"/{LHS}         {return PR_QM;}
"PS"/{LHS}          {return PS;}
"R"/{LHS}           {return R;}
"REF"/{LHS}         {BEGIN STATE_STRING; return REF;}
"S"/{LHS}           {BEGIN STATE_STRING; return S;}
"SX"/{LHS}          {return SX;}
"SY"/{LHS}          {return SY;}
"S1"/{LHS}          {BEGIN STATE_STRING; return S1;}
"S1X"/{LHS}         {return S1X;}
"S1Y"/{LHS}         {return S1Y;}
"S2"/{LHS}          {BEGIN STATE_STRING; return S2;}
"S2X"/{LHS}         {return S2X;}
"S2Y"/{LHS}         {return S2Y;}
"T"/{LHS}           {return T;}
"TC"/{LHS}          {return TC;}
"USE_DIE_FOR_METAL"/{LHS}           {return USE_DIE_FOR_METAL;}
"V"/{LHS}           {BEGIN STATE_STRING; return V;}
"V?"/{LHS}          {return V_QM;}
"VAL"/{LHS}         {return VAL;}
"W"/{LHS}           {return W;}
"X"/{LHS}           {return X;}
"X1"/{LHS}          {return X1;}
"X2"/{LHS}          {return X2;}
"XC"/{LHS}          {return XC;}
"Y"/{LHS}           {return Y;}
"Y1"/{LHS}          {return Y1;}
"Y2"/{LHS}          {return Y2;}
"YC"/{LHS}          {return YC;}
"Z"/{LHS}           {return Z;}
"ZL"/{LHS}          {return ZL;}
"ZLEN"/{LHS}        {return ZLEN;}
"ZW"/{LHS}          {return ZW;}
 
 /* Booleans */

"YES"|"yes"         {yylval.boolval = 1; return BOOL; }
"NO"|"no"           {yylval.boolval = 0; return BOOL; }

 /* Floats */

                    /* ordinary floating point numbers */
{SIMPLE_FLOAT}      {yylval.floatval = strtod(yytext, NULL); return FLOAT;}

                    /* floating point numbers with suffix, e,g. pF, nH */
{FLOAT_YOTTA}       {yylval.floatval = strtod(yytext, NULL) * 1e24; return FLOAT;}
{FLOAT_ZETA}        {yylval.floatval = strtod(yytext, NULL) * 1e21; return FLOAT;}
{FLOAT_EXA}         {yylval.floatval = strtod(yytext, NULL) * 1e18; return FLOAT;}
{FLOAT_PETA}        {yylval.floatval = strtod(yytext, NULL) * 1e15; return FLOAT;}
{FLOAT_TERA}        {yylval.floatval = strtod(yytext, NULL) * 1e12; return FLOAT;}
{FLOAT_GIGA}        {yylval.floatval = strtod(yytext, NULL) * 1e9; return FLOAT;}
{FLOAT_MEGA}        {yylval.floatval = strtod(yytext, NULL) * 1e6; return FLOAT;}
{FLOAT_KILO}        {yylval.floatval = strtod(yytext, NULL) * 1e3; return FLOAT;}
{FLOAT_MILLI}       {yylval.floatval = strtod(yytext, NULL) * 1e-3; return FLOAT;}
{FLOAT_MICRO}       {yylval.floatval = strtod(yytext, NULL) * 1e-6; return FLOAT;}
{FLOAT_NANO}        {yylval.floatval = strtod(yytext, NULL) * 1e-9; return FLOAT;}
{FLOAT_PICO}        {yylval.floatval = strtod(yytext, NULL) * 1e-12; return FLOAT;}
{FLOAT_FEMTO}       {yylval.floatval = strtod(yytext, NULL) * 1e-15; return FLOAT;}
{FLOAT_ATTO}        {yylval.floatval = strtod(yytext, NULL) * 1e-18; return FLOAT;}
{FLOAT_ZEPTO}       {yylval.floatval = strtod(yytext, NULL) * 1e-21; return FLOAT;}
{FLOAT_YOCTO}       {yylval.floatval = strtod(yytext, NULL) * 1e-24; return FLOAT;}

                    /* floating point numbers in VERSION and PLANE_SEP have no suffix and are followed by optional comments */
<STATE_FLOAT>{
{SIMPLE_FLOAT}      {yylval.floatval = strtod(yytext, NULL); BEGIN STATE_COMMENT; return FLOAT;}
}

                    /* A positive integer is used only in polygon/polyline/polyvoid "ID = posint" */
<STATE_POSINT>{
{POSINT}            { BEGIN INITIAL; yylval.intval = atoi(yytext); return POSINT; }
}

 
                    /* 
                     * This is a workaround for syntactically incorrect .hyp files.
                     * We accept the following constructs as representing an empty string:
                     * NAME= L1=somelayer
                     * NAME= )
                     * NAME= }
                     */
<STATE_STRING>{
([A-Z][A-Z1-2_]*{WS}*"="|")"|"}")  { yyless(0); BEGIN INITIAL; yylval.strval = strdup(""); return STRING; } /* emit empty string and reprocess */
}

<*>{

  "{"                 {return '{';}

  "}"                 {BEGIN STATE_COMMENT_EOL; return '}';}

  "("                 {if (section == PADSTACK) BEGIN STATE_STRING; return '(';}

                      /* allow for comment after the closing bracket ) */
  ")"                 {BEGIN STATE_COMMENT_EOL; return ')';}

  ","                 {return ',';}

  "="                 {if ((section == VERSION) || (section == PLANE_SEP)) BEGIN STATE_FLOAT; return '=';}

                      /* string */
  {STRING}            { 
                        /*
                         * Commas are not allowed in strings in the padstack section
                         * unless the string is enclosed in double quotes (").
                         */

                        if ((section == PADSTACK) && strchr(yytext, ','))
                          REJECT 
                        else 
                        { 
                          BEGIN INITIAL; 
                          yylval.strval = strdup(yytext); 
                          return STRING;
                        }
                      }

                      /* string in double quotes */
  {QUOTED_STRING}     {BEGIN INITIAL; yylval.strval = strunquote(yytext); return STRING;}

  <<EOF>>             {yyterminate();}

                      /* have bison catch all unrecognized characters with parse errors */
  .                   {return yytext[0];}

}

%%

 /* 
  * copy a quoted string.
  * e.g. "data 0" -> data 0
  * a double quote inside the string can be escaped by writing two consecutive double quotes
  * e.g. "net ""hi""" -> net "hi"
  */

 char *strunquote(const char *src) 
 {
   char* dst;
   size_t len = strlen(src) + 1;
   dst = (char *)malloc(len);
   if (dst != NULL) 
   {
     char* p = (char *)src + 1; /* first char after initial quote */
     char* q = dst;
     do 
       if (*p == '"') p++;
     while ((*q++ = *p++) != '\0');
   }
   return dst;
 }

 /* not truncated */