Merged revisions 141094 via svnmerge from
authorSteve Murphy <murf@digium.com>
Thu, 4 Sep 2008 23:31:41 +0000 (23:31 +0000)
committerSteve Murphy <murf@digium.com>
Thu, 4 Sep 2008 23:31:41 +0000 (23:31 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r141094 | murf | 2008-09-04 17:15:07 -0600 (Thu, 04 Sep 2008) | 70 lines

(closes issue #13357)
Reported by: pj
Tested by: murf

(closes issue #13416)
Reported by: yarns
Tested by: murf

If you find this message overly verbose, relax, it's probably
not meant for you. This message is meant for probably only
two people in the whole world: me, or the poor schnook that
has to maintain this code because I'm either dead or unavailable
at the moment.

This fix solves two reports, both having to do with embedding
a function call in a ${} construct. It was tricky because the
funccall syntax has parenthesis () in it. And up till now,
the 'word' token in the flex stuff didn't allow that, because
it would tend to steal the LP and RP tokens. To be truthful,
the "word" token was the trickiest, most unstable thing in
the whole lexer. I was lucky it made this long without complaints.
I had to choose every character in the pattern with extreme
care, and I knew that someday I'd have to revisit it. Well,
the day has come.

So, my brilliant idea (and I'm being modest), was to use the
surrounding ${} construct to make a state machine and capture
everything in it, no matter what it contains. But, I have to now
treat the word token like I did with comments, in that I turn
the whole thing into a state-machine sort of spec, with new
contexts "curlystate", "wordstate", and "brackstate".

Wait a minute, "brackstate"? Yes, well, it didn't take very many
regression tests to point out if I do this for ${} constructs,
I also have to do it with the $[] constructs, too.

I had to create a separate pcbstack2 and pcbstack3 because
these constructs can occur inside macro argument lists, and
when we have two state machines operating on the same structures
we'd get problems otherwise. I guess I could have stopped at
pcbstack2 and had the brackstate stuff share it, but it doesn't
hurt to be safe. So, the pcbpush and pcbpop routines also now
have versions for "2" and "3".

I had to add the {KEYWORD} construct to the initial pattern for
"word", because previously word would match stuff like "default7",
because it was a longer match than the keyword "default". But,
not any more, because the word pattern only matches only one or
two characters now, and it will always lose. So, I made it the
winner again by making an optional match on any of the keywords
before it's normal pattern.

I added another regression test to make sure we don't
lose this in future edits, and had to fix just one regression,
where it no longer reports a 'cascaded' error, which I guess
is a plus.

I've given some thought as to whether to apply these fixes to
1.4 and the 1.6.x releases, vs trunk; I decided to put it in
1.4 because one of the bug reports was against 1.4; and it
is unexpected that AEL cannot handle this situation. It actually
reduced the amount of useless "cascade" error messages that
appeared in the regressions (by one line, ehhem). There is
a possible side-effect in that it does now do more careful
checking of what's in those ${} constructs, as far as matching
parens, and brackets are concerned. Some users may find a an
insidious problem and correct it this way. This should be
exceedingly rare, I hope.

........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@141115 65c4cc65-6c06-0410-ace0-fbb531ad65f3

pbx/ael/ael-test/ael-vtest25/extensions.ael [new file with mode: 0644]
pbx/ael/ael-test/ref.ael-test6
pbx/ael/ael-test/ref.ael-vtest25 [new file with mode: 0644]
res/ael/ael.flex
res/ael/ael_lex.c

diff --git a/pbx/ael/ael-test/ael-vtest25/extensions.ael b/pbx/ael/ael-test/ael-vtest25/extensions.ael
new file mode 100644 (file)
index 0000000..f6d19d7
--- /dev/null
@@ -0,0 +1,8 @@
+context test11 {
+        841 => {
+                &test234("testing", ${CUT(EXTEN,,3)});
+                jump ${DB(uri/${uri_string})};
+                Set(line=${DB(uri/${uri_string})});
+                jump ${line};
+        }
+}
index 968c7c7..4b46c08 100644 (file)
@@ -2,23 +2,22 @@
 (If you find progress and other non-error messages irritating, you can use -q to suppress them)
 
 (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump)
-LOG: lev:2 file:pbx_ael.c  line:113 func: pbx_load_module  Starting AEL load process.
-LOG: lev:4 file:ael.flex  line:288 func: ael_yylex  File=./extensions.ael, line=165, column=49: Mismatched '}' in expression!
-LOG: lev:4 file:ael.y  line:772 func: ael_yyerror  ==== File: ./extensions.ael, Line 165, Cols: 51-51: Error: syntax error, unexpected '=', expecting ')'
-LOG: lev:4 file:ael.flex  line:288 func: ael_yylex  File=./extensions.ael, line=174, column=49: Mismatched '}' in expression!
-LOG: lev:4 file:ael.y  line:772 func: ael_yyerror  ==== File: ./extensions.ael, Line 174, Cols: 51-51: Error: syntax error, unexpected '=', expecting ')'
-LOG: lev:4 file:ael.flex  line:288 func: ael_yylex  File=./extensions.ael, line=222, column=41: Mismatched '}' in expression!
-LOG: lev:4 file:ael.y  line:772 func: ael_yyerror  ==== File: ./extensions.ael, Line 222, Cols: 43-43: Error: syntax error, unexpected '=', expecting ')'
-LOG: lev:4 file:ael.y  line:772 func: ael_yyerror  ==== File: ./extensions.ael, Line 291, Cols: 21-28: Error: syntax error, unexpected word, expecting '(' or ';' or '=' or ':'
-LOG: lev:4 file:ael.y  line:772 func: ael_yyerror  ==== File: ./extensions.ael, Line 291, Cols: 32-32: Error: syntax error, unexpected '|', expecting '(' or ';' or '=' or ':'
-LOG: lev:2 file:pbx_ael.c  line:126 func: pbx_load_module  AEL load process: parsed config file name './extensions.ael'.
-LOG: lev:3 file:pval.c  line:671 func: check_macro_returns  Warning: file ./extensions.ael, line 116-125: The macro dialout does not end with a return; I will insert one.
-LOG: lev:3 file:pval.c  line:671 func: check_macro_returns  Warning: file ./extensions.ael, line 129-182: The macro stdexten does not end with a return; I will insert one.
-LOG: lev:3 file:pval.c  line:671 func: check_macro_returns  Warning: file ./extensions.ael, line 184-191: The macro uvm does not end with a return; I will insert one.
-LOG: lev:3 file:pval.c  line:671 func: check_macro_returns  Warning: file ./extensions.ael, line 193-200: The macro bvm does not end with a return; I will insert one.
-LOG: lev:3 file:pval.c  line:671 func: check_macro_returns  Warning: file ./extensions.ael, line 202-207: The macro checkdnd does not end with a return; I will insert one.
-LOG: lev:3 file:pval.c  line:671 func: check_macro_returns  Warning: file ./extensions.ael, line 209-216: The macro checkcf does not end with a return; I will insert one.
-LOG: lev:3 file:pval.c  line:671 func: check_macro_returns  Warning: file ./extensions.ael, line 218-230: The macro checkcfb does not end with a return; I will insert one.
-LOG: lev:3 file:pval.c  line:671 func: check_macro_returns  Warning: file ./extensions.ael, line 688-694: The macro check-psd-exists does not end with a return; I will insert one.
-LOG: lev:4 file:pbx_ael.c  line:139 func: pbx_load_module  Sorry, but 5 syntax errors and 0 semantic errors were detected. It doesn't make sense to compile.
-LOG: lev:4 file:ael2_parse  line:531 func: main  0 contexts, 0 extensions, 0 priorities
+LOG: lev:2 file:pbx_ael.c  line:115 func: pbx_load_module  Starting AEL load process.
+LOG: lev:4 file:ael.flex  line:437 func: ael_yylex  File=./extensions.ael, line=165, column=49: Mismatched '}' in expression!
+LOG: lev:4 file:ael.y  line:777 func: ael_yyerror  ==== File: ./extensions.ael, Line 165, Cols: 52-52: Error: syntax error, unexpected '=', expecting ')'
+LOG: lev:4 file:ael.flex  line:437 func: ael_yylex  File=./extensions.ael, line=174, column=49: Mismatched '}' in expression!
+LOG: lev:4 file:ael.y  line:777 func: ael_yyerror  ==== File: ./extensions.ael, Line 174, Cols: 52-52: Error: syntax error, unexpected '=', expecting ')'
+LOG: lev:4 file:ael.flex  line:437 func: ael_yylex  File=./extensions.ael, line=222, column=41: Mismatched '}' in expression!
+LOG: lev:4 file:ael.y  line:777 func: ael_yyerror  ==== File: ./extensions.ael, Line 222, Cols: 44-44: Error: syntax error, unexpected '=', expecting ')'
+LOG: lev:4 file:ael.y  line:777 func: ael_yyerror  ==== File: ./extensions.ael, Line 291, Cols: 22-33: Error: syntax error, unexpected word, expecting '(' or ';' or '=' or ':'
+LOG: lev:2 file:pbx_ael.c  line:128 func: pbx_load_module  AEL load process: parsed config file name './extensions.ael'.
+LOG: lev:3 file:pval.c  line:672 func: check_macro_returns  Warning: file ./extensions.ael, line 116-125: The macro dialout does not end with a return; I will insert one.
+LOG: lev:3 file:pval.c  line:672 func: check_macro_returns  Warning: file ./extensions.ael, line 129-182: The macro stdexten does not end with a return; I will insert one.
+LOG: lev:3 file:pval.c  line:672 func: check_macro_returns  Warning: file ./extensions.ael, line 184-191: The macro uvm does not end with a return; I will insert one.
+LOG: lev:3 file:pval.c  line:672 func: check_macro_returns  Warning: file ./extensions.ael, line 193-200: The macro bvm does not end with a return; I will insert one.
+LOG: lev:3 file:pval.c  line:672 func: check_macro_returns  Warning: file ./extensions.ael, line 202-207: The macro checkdnd does not end with a return; I will insert one.
+LOG: lev:3 file:pval.c  line:672 func: check_macro_returns  Warning: file ./extensions.ael, line 209-216: The macro checkcf does not end with a return; I will insert one.
+LOG: lev:3 file:pval.c  line:672 func: check_macro_returns  Warning: file ./extensions.ael, line 218-230: The macro checkcfb does not end with a return; I will insert one.
+LOG: lev:3 file:pval.c  line:672 func: check_macro_returns  Warning: file ./extensions.ael, line 688-694: The macro check-psd-exists does not end with a return; I will insert one.
+LOG: lev:4 file:pbx_ael.c  line:144 func: pbx_load_module  Sorry, but 4 syntax errors and 0 semantic errors were detected. It doesn't make sense to compile.
+LOG: lev:4 file:ael2_parse  line:520 func: main  0 contexts, 0 extensions, 0 priorities
diff --git a/pbx/ael/ael-test/ref.ael-vtest25 b/pbx/ael/ael-test/ref.ael-vtest25
new file mode 100644 (file)
index 0000000..c1be413
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+[test11]
+exten => 841,1,Gosub(test234,s,1("testing", ${CUT(EXTEN,,3)}))
+exten => 841,2,Goto(${DB(uri/${uri_string})},1)
+exten => 841,3,Set(line=${DB(uri/${uri_string})})
+exten => 841,4,Goto(${line},1)
index 58d71e4..64c96a6 100644 (file)
@@ -26,7 +26,7 @@
  *
  * %x describes the contexts we have: paren, semic and argg, plus INITIAL
  */
-%x paren semic argg  comment
+%x paren semic argg  comment curlystate wordstate brackstate
 
 /* prefix used for various globally-visible functions and variables.
  * This renames also yywrap, but since we do not use it, we just
@@ -85,10 +85,28 @@ static char pbcstack[400];  /* XXX missing size checks */
 static int pbcpos = 0;
 static void pbcpush(char x);
 static int pbcpop(char x);
-
 static int parencount = 0;
 
 /*
+ * A similar stack to keep track of matching brackets ( [ { } ] ) in word tokens surrounded by ${ ... }
+ */
+static char pbcstack2[400];    /* XXX missing size checks */
+static int pbcpos2 = 0;
+static void pbcpush2(char x);
+static int pbcpop2(char x);
+static int parencount2 = 0;
+
+/*
+ * A similar stack to keep track of matching brackets ( [ { } ] ) in word tokens surrounded by $[ ... ]
+ */
+static char pbcstack3[400];    /* XXX missing size checks */
+static int pbcpos3 = 0;
+static void pbcpush3(char x);
+static int pbcpop3(char x);
+static int parencount3 = 0;
+
+
+/*
  * current line, column and filename, updated as we read the input.
  */
 static int my_lineno = 1;      /* current line in the source */
@@ -177,6 +195,7 @@ static void pbcwhere(const char *text, int *line, int *col )
 #endif
 %}
 
+KEYWORD     (context|abstract|extend|macro|globals|local|ignorepat|switch|if|ifTime|random|regexten|hint|else|goto|jump|return|break|continue|for|while|case|default|pattern|catch|switches|eswitches|includes)
 
 NOPARENS       ([^()\[\]\{\}]|\\[()\[\]\{\}])*
 
@@ -235,20 +254,144 @@ includes { STORE_POS; return KW_INCLUDES;}
 <comment>[^*\n]*\n     { ++my_lineno; my_col=1;}
 <comment>"*"+[^*/\n]*  { my_col += yyleng; }
 <comment>"*"+[^*/\n]*\n        { ++my_lineno; my_col=1;}
-<comment>"*/"          { my_col += 2; BEGIN(INITIAL); }
+<comment>"*/"          { my_col += 2; BEGIN(INITIAL); } /* the nice thing about comments is that you know exactly what ends them */
 
 \n             { my_lineno++; my_col = 1; }
 [ ]+           { my_col += yyleng; }
 [\t]+          { my_col += (yyleng*8)-(my_col%8); }
 
-([-a-zA-Z0-9'"_/.\<\>\*\\\+!$#\[\]]|{HIBIT})([-a-zA-Z0-9'"_/.!\*\\\+\<\>\{\}$#\[\]]|{HIBIT})*  {
+({KEYWORD}?[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]]|{HIBIT}|(\\.)|(\$\{)|(\$\[)) { 
+      /* boy did I open a can of worms when I changed the lexical token "word". 
+                all the above keywords can be used as a beginning to a "word".-
+                before, a "word" would match a longer sequence than the above   
+            keywords, and all would be well. But now "word" is a single char           
+            and feeds into a statemachine sort of sequence from there on. So...
+                I added the {KEYWORD}? to the beginning of the word match sequence */
+
+               if (!strcmp(yytext,"${")) {
+                       parencount2 = 0;
+                       pbcpos2 = 0;
+                       pbcpush2('{');  /* push '{' so the last pcbpop (parencount2 = -1) will succeed */
+                       BEGIN(curlystate);
+                       yymore();
+               } else if (!strcmp(yytext,"$[")) {
+                       parencount3 = 0;
+                       pbcpos3 = 0;
+                       pbcpush3('[');  /* push '[' so the last pcbpop (parencount3 = -1) will succeed */
+                       BEGIN(brackstate);
+                       yymore();
+               } else {
+                   BEGIN(wordstate);
+                       yymore();
+               }
+       }
+
+<wordstate>[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]] { yymore(); /* Keep going */ }
+<wordstate>{HIBIT} { yymore(); /* Keep going */ }
+<wordstate>(\\.)  { yymore(); /* Keep Going */ }
+<wordstate>(\$\{)  { /* the beginning of a ${} construct. prepare and pop into curlystate */
+               parencount2 = 0;
+               pbcpos2 = 0;
+               pbcpush2('{');  /* push '{' so the last pcbpop (parencount2 = -1) will succeed */
+               BEGIN(curlystate);
+               yymore();
+       }
+<wordstate>(\$\[)  { /* the beginning of a $[] construct. prepare and pop into brackstate */
+               parencount3 = 0;
+               pbcpos3 = 0;
+               pbcpush3('[');  /* push '[' so the last pcbpop (parencount3 = -1) will succeed */
+               BEGIN(brackstate);
+               yymore();
+       }
+<wordstate>([^a-zA-Z0-9\x80-\xff\x2d'"_/.\<\>\*\+!$#\[\]]) {
+               /* a non-word constituent char, like a space, tab, curly, paren, etc */
+               char c = yytext[yyleng-1];
                STORE_POS;
                yylval->str = strdup(yytext);
-               prev_word = yylval->str;
+               yylval->str[yyleng-1] = 0;
+               unput(c);  /* put this ending char back in the stream */
+               BEGIN(0);
                return word;
        }
 
 
+<curlystate>{NOPARENS}\}       {
+               if ( pbcpop2('}') ) {   /* error */
+                       STORE_LOC;
+                       ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);
+                       BEGIN(0);
+                       yylval->str = strdup(yytext);
+                       return word;
+               }
+               parencount2--;
+               if ( parencount2 >= 0) {
+                       yymore();
+               } else {
+                       BEGIN(wordstate); /* Finished with the current ${} construct. Return to word gathering state */
+                       yymore();
+               }
+       }
+
+<curlystate>{NOPARENS}[\(\[\{] { 
+               char c = yytext[yyleng-1];
+               if (c == '{')
+                       parencount2++;
+               pbcpush2(c);
+               yymore();
+       }
+
+<curlystate>{NOPARENS}[\]\)]   { 
+               char c = yytext[yyleng-1];
+               if ( pbcpop2(c))  { /* error */
+                       STORE_LOC;
+                       ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",
+                               my_file, my_lineno, my_col, c);
+                       BEGIN(0);
+                       yylval->str = strdup(yytext);
+                       return word;
+               }
+               yymore();
+       }
+
+
+<brackstate>{NOPARENS}\]       {
+               if ( pbcpop3(']') ) {   /* error */
+                       STORE_LOC;
+                       ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);
+                       BEGIN(0);
+                       yylval->str = strdup(yytext);
+                       return word;
+               }
+               parencount3--;
+               if ( parencount3 >= 0) {
+                       yymore();
+               } else {
+                       BEGIN(wordstate); /* Finished with the current ${} construct. Return to word gathering state */
+                       yymore();
+               }
+       }
+
+<brackstate>{NOPARENS}[\(\[\{] { 
+               char c = yytext[yyleng-1];
+               if (c == '[')
+                       parencount3++;
+               pbcpush3(c);
+               yymore();
+       }
+
+<brackstate>{NOPARENS}[\}\)]   { 
+               char c = yytext[yyleng-1];
+               if ( pbcpop3(c))  { /* error */
+                       STORE_LOC;
+                       ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",
+                               my_file, my_lineno, my_col, c);
+                       BEGIN(0);
+                       yylval->str = strdup(yytext);
+                       return word;
+               }
+               yymore();
+       }
+
 
        /*
         * context used for arguments of if_head, random_head, switch_head,
@@ -500,6 +643,38 @@ static int pbcpop(char x)
        return 1; /* error */
 }
 
+static void pbcpush2(char x)
+{
+       pbcstack2[pbcpos2++] = x;
+}
+
+static int pbcpop2(char x)
+{
+       if (   ( x == ')' && pbcstack2[pbcpos2-1] == '(' )
+               || ( x == ']' && pbcstack2[pbcpos2-1] == '[' )
+               || ( x == '}' && pbcstack2[pbcpos2-1] == '{' )) {
+               pbcpos2--;
+               return 0;
+       }
+       return 1; /* error */
+}
+
+static void pbcpush3(char x)
+{
+       pbcstack3[pbcpos3++] = x;
+}
+
+static int pbcpop3(char x)
+{
+       if (   ( x == ')' && pbcstack3[pbcpos3-1] == '(' )
+               || ( x == ']' && pbcstack3[pbcpos3-1] == '[' )
+               || ( x == '}' && pbcstack3[pbcpos3-1] == '{' )) {
+               pbcpos3--;
+               return 0;
+       }
+       return 1; /* error */
+}
+
 static int c_prevword(void)
 {
        char *c = prev_word;
index 37e9a90..2a14400 100644 (file)
@@ -32,7 +32,7 @@
 
 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
-#if !defined __STDC_VERSION__ || __STDC_VERSION__ >= 199901L
+#if __STDC_VERSION__ >= 199901L
 
 /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
  * if you want the limit (max/min) macros for int types. 
@@ -357,8 +357,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
        *yy_cp = '\0'; \
        yyg->yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 63
-#define YY_END_OF_BUFFER 64
+#define YY_NUM_RULES 75
+#define YY_END_OF_BUFFER 76
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -366,35 +366,39 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[244] =
+static yyconst flex_int16_t yy_accept[285] =
     {   0,
         0,    0,    0,    0,    0,    0,    0,    0,   43,   43,
-       64,   63,   50,   48,   49,   51,   51,    9,    3,    4,
-        7,   51,    8,    5,    6,   12,   51,   51,   51,   51,
+        0,    0,    0,    0,    0,    0,   76,   75,   50,   48,
+       49,   51,   51,   51,    9,    3,    4,    7,   51,    8,
+        5,    6,   12,   75,   51,   51,   51,   51,   51,   51,
        51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,    1,   10,    2,   63,   53,   52,   63,   54,
-       63,   59,   60,   61,   63,   63,   55,   56,   57,   63,
-       58,   43,   44,   45,   50,   49,   51,   51,   42,   13,
-       11,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   22,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,    0,   53,   52,    0,   54,   53,
-
-       52,   54,    0,   59,   60,   61,    0,   59,   60,   61,
-        0,   55,   56,   57,    0,   58,   55,   56,   57,   58,
-       43,   44,   45,   46,   45,   47,   51,   13,   13,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   33,   51,
-       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51,   35,   51,   51,
-       51,   27,   51,   51,   51,   28,   26,   51,   51,   51,
-       29,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-       51,   31,   38,   51,   51,   51,   51,   51,   51,   51,
-       51,   51,   19,   17,   51,   51,   51,   51,   51,   34,
-
-       51,   51,   51,   51,   51,   51,   16,   51,   23,   51,
-       51,   51,   24,   51,   30,   21,   51,   51,   14,   51,
-       36,   51,   18,   51,   51,   37,   51,   51,   51,   15,
-       32,   51,   51,   41,   25,   39,    0,   40,   20,    0,
-        0,   62,    0
+        1,   10,    2,   75,   65,   64,   75,   66,   75,   71,
+       72,   73,   75,   75,   67,   68,   69,   75,   70,   43,
+       44,   45,   75,   59,   60,   75,   58,   57,   52,   52,
+       57,   53,   75,   62,   63,   75,   61,   50,   49,    0,
+       51,   42,   13,   11,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,   22,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   65,   64,
+        0,   66,   65,   64,   66,    0,   71,   72,   73,    0,
+       71,   72,   73,    0,   67,   68,   69,    0,   70,   67,
+       68,   69,   70,   43,   44,   45,   46,   45,   47,    0,
+       59,   60,    0,   58,   59,   60,   58,   56,   55,   54,
+        0,   62,   63,    0,   61,   62,   63,   61,    0,   13,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   33,
+        0,    0,    0,   51,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   35,    0,
+
+        0,    0,   27,    0,    0,    0,   28,   26,    0,    0,
+        0,   29,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   31,   38,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   19,   17,    0,    0,    0,    0,    0,
+       34,    0,    0,    0,    0,    0,    0,   16,    0,   23,
+        0,    0,    0,   24,    0,   30,   21,    0,    0,   14,
+        0,   36,    0,   18,    0,    0,   37,    0,   51,    0,
+       15,   32,    0,    0,   41,   25,   39,    0,   40,   20,
+        0,    0,   74,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -402,340 +406,360 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    4,    5,    6,    7,    5,    1,    8,    5,    9,
-       10,   11,    5,   12,    5,    5,   13,    5,    5,    5,
-        5,    5,    5,    5,    5,    5,    5,   14,   15,    5,
-       16,   17,    1,   18,    5,    5,    5,    5,    5,    5,
+        1,    4,    5,    6,    7,    8,    1,    9,    5,   10,
+       11,   12,    5,   13,    5,    5,   14,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,   15,   16,    5,
+       17,   18,    1,   19,    5,    5,    5,    5,    5,    5,
         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
-        5,    5,    5,   19,    5,    5,    5,    5,    5,    5,
-       20,   21,   22,    1,    5,    1,   23,   24,   25,   26,
-
-       27,   28,   29,   30,   31,   32,   33,   34,   35,   36,
-       37,   38,    5,   39,   40,   41,   42,    5,   43,   44,
-        5,    5,   45,   46,   47,    1,    1,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48
+        5,    5,    5,   20,    5,    5,    5,    5,    5,    5,
+       21,   22,   23,    1,    5,    1,   24,   25,   26,   27,
+
+       28,   29,   30,   31,   32,   33,   34,   35,   36,   37,
+       38,   39,    5,   40,   41,   42,   43,    5,   44,   45,
+        5,    5,   46,   47,   48,    1,    1,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49
     } ;
 
-static yyconst flex_int32_t yy_meta[49] =
+static yyconst flex_int32_t yy_meta[50] =
     {   0,
-        1,    1,    2,    1,    3,    4,    3,    1,    1,    1,
-        5,    1,    3,    1,    1,    1,    3,    1,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        1,    1,    2,    1,    3,    4,    3,    3,    1,    1,
+        1,    5,    1,    3,    1,    1,    1,    3,    1,    3,
+        3,    1,    3,    3,    3,    3,    3,    3,    3,    3,
         3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    1,    3,    3
+        3,    3,    3,    3,    3,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int16_t yy_base[257] =
+static yyconst flex_int16_t yy_base[304] =
     {   0,
-        0,    0,   40,   43,   82,  121,  160,  199,   48,   55,
-      320,  986,  317,  986,  314,    0,  286,  986,  986,  986,
-      986,   43,  986,  986,  299,  986,  291,  275,   32,  286,
-       33,  275,   34,  280,   46,  268,  272,  285,  284,   49,
-      263,  275,  986,  986,  986,   74,  986,  986,   90,  986,
-      238,  986,  986,  986,  277,  316,  986,  986,  986,  355,
-      986,  301,  986,   67,  301,  298,    0,  265,    0,  402,
-      986,  260,  269,   65,  259,  266,  253,  248,  249,  250,
-      251,  243,  246,  262,  244,  254,  243,  252,  251,  234,
-      238,   52,  242,  241,  104,  986,  986,  138,  986,  143,
-
-      177,  182,  440,  986,  986,  986,  479,  518,  557,  596,
-      635,  986,  986,  986,  674,  986,  713,  752,  791,  830,
-      268,  986,  104,  986,  105,  986,  245,    0,  877,  228,
-      245,  240,  241,  224,  241,  236,  231,  234,    0,  233,
-      219,  214,  223,  215,  217,  212,  226,  206,  202,  216,
-      214,  198,  198,  204,  203,  197,  202,    0,  204,  101,
-      191,    0,  191,  195,  207,    0,    0,  193,  187,  183,
-        0,  189,  181,  190,  179,  171,  175,  188,  185,  168,
-      183,    0,    0,  157,  164,  162,  170,  168,  159,  162,
-      157,  153,    0,    0,  139,  142,  135,  138,  137,    0,
-
-      136,  136,  116,  114,  114,  124,    0,  110,    0,  108,
-      118,  108,    0,  113,    0,  112,  111,   93,    0,  106,
-        0,   96,    0,   86,   61,    0,   62,   49,  118,    0,
-        0,   46,   38,    0,    0,    0,  169,    0,    0,    0,
-       51,  986,  986,  923,  928,  933,  938,  941,  946,  951,
-      956,  961,  965,  970,  975,  980
+        0,    0,   40,   43,   82,  121,  160,  199,   55,   56,
+       60,   74,  247,  296,   90,  104,  432, 1023,  429, 1023,
+      426, 1023,  397,   31, 1023, 1023, 1023, 1023,   43, 1023,
+     1023,  410, 1023,    0,  401,  382,   36,  389,   34,  378,
+       38,  380,   80,  368,  372,  385,  381,   66,  357,  369,
+     1023, 1023, 1023,  138, 1023, 1023,  143, 1023,  336, 1023,
+     1023, 1023,  375,  414, 1023, 1023, 1023,  453, 1023,  396,
+     1023,  104,  177, 1023, 1023,  182, 1023, 1023, 1023,   78,
+        0, 1023,  231, 1023, 1023,  262, 1023,  393,  390,  356,
+     1023, 1023,    0, 1023,  348,  360,   92,  350,  354,  337,
+
+      333,  333,  333,  334,  329,  333,  344,  326,  335,  320,
+      327,  322,  299,  303,   93,  302,  301,  280, 1023, 1023,
+      314, 1023,  328,  344,  358,  492, 1023, 1023, 1023,  531,
+      570,  609,  648,  687, 1023, 1023, 1023,  726, 1023,  765,
+      804,  843,  882,  329, 1023,  143, 1023,  144, 1023,  392,
+     1023, 1023,  397, 1023,  431,  436,  470, 1023, 1023, 1023,
+      475, 1023, 1023,  484, 1023,  514,  523,  553,  305,    0,
+      288,  305,  299,  297,  280,  297,  292,  287,  289,    0,
+      291,  276,  250,  257,  250,  252,  247,  258,  241,  238,
+      251,  248,  232,  232,  236,  235,  228,  233,    0,  234,
+
+      113,  218,    0,  217,  209,  220,    0,    0,  207,  200,
+      196,    0,  203,  199,  208,  197,  189,  193,  206,  203,
+      186,  203,    0,    0,  181,  187,  184,  192,  190,  181,
+      187,  186,  186,    0,    0,  171,  171,  160,  164,  166,
+        0,  169,  169,  152,  147,  143,  149,    0,  138,    0,
+      139,  149,  138,    0,  140,    0,  135,  134,  109,    0,
+      112,    0,  111,    0,  105,   80,    0,   82,   61,   76,
+        0,    0,   46,   30,    0,    0,    0,  170,    0,    0,
+        0,   50, 1023, 1023,  930,  935,  940,  945,  950,  955,
+      960,  965,  970,  975,  980,  985,  989,  994,  999, 1004,
+
+     1009, 1012, 1017
     } ;
 
-static yyconst flex_int16_t yy_def[257] =
+static yyconst flex_int16_t yy_def[304] =
     {   0,
-      243,    1,  244,  244,  245,  245,  246,  246,  247,  247,
-      243,  243,  243,  243,  243,  248,  248,  243,  243,  243,
-      243,  248,  243,  243,  243,  243,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  243,  243,  243,  249,  243,  243,  249,  243,
-      250,  243,  243,  243,  250,  251,  243,  243,  243,  251,
-      243,  252,  243,  253,  243,  243,  248,  248,  248,  254,
-      243,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  249,  243,  243,  249,  243,  249,
-
-      249,  249,  250,  243,  243,  243,  250,  250,  250,  250,
-      251,  243,  243,  243,  251,  243,  251,  251,  251,  251,
-      252,  243,  253,  243,  253,  243,  248,  255,  254,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  248,  248,  248,  248,
-      248,  248,  248,  248,  248,  248,  243,  248,  248,  256,
-      256,  243,    0,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243
+      284,    1,  285,  285,  286,  286,  287,  287,  288,  288,
+      289,  289,  290,  290,  291,  291,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  292,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  293,  284,  284,  293,  284,  294,  284,
+      284,  284,  294,  295,  284,  284,  284,  295,  284,  296,
+      284,  297,  298,  284,  284,  298,  284,  284,  284,  284,
+      299,  284,  300,  284,  284,  300,  284,  284,  284,  284,
+      284,  284,  301,  284,  284,  284,  284,  284,  284,  284,
+
+      284,  284,  284,  284,  284,  284,  302,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  293,  284,  284,
+      293,  284,  293,  293,  293,  294,  284,  284,  284,  294,
+      294,  294,  294,  295,  284,  284,  284,  295,  284,  295,
+      295,  295,  295,  296,  284,  297,  284,  297,  284,  298,
+      284,  284,  298,  284,  298,  298,  298,  284,  284,  284,
+      300,  284,  284,  300,  284,  300,  300,  300,  284,  301,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  302,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  302,  284,
+
+      284,  284,  302,  284,  284,  284,  302,  302,  284,  284,
+      284,  302,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  302,  302,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  302,  302,  284,  284,  284,  284,  284,
+      302,  284,  284,  284,  284,  284,  284,  302,  284,  302,
+      284,  284,  284,  302,  284,  302,  302,  284,  284,  302,
+      284,  302,  284,  302,  284,  284,  302,  284,  284,  284,
+      302,  302,  284,  284,  302,  302,  302,  284,  302,  302,
+      303,  303,  284,    0,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+
+      284,  284,  284
     } ;
 
-static yyconst flex_int16_t yy_nxt[1035] =
+static yyconst flex_int16_t yy_nxt[1073] =
     {   0,
-       12,   13,   14,   15,   16,   16,   17,   18,   19,   20,
-       16,   21,   22,   23,   24,   25,   16,   26,   16,   16,
-       16,   16,   27,   28,   29,   30,   31,   32,   33,   34,
-       35,   36,   16,   37,   38,   16,   16,   39,   40,   41,
-       16,   16,   42,   16,   43,   44,   45,   16,   47,   48,
-       63,   47,   48,   69,   74,   70,  242,   63,   64,   47,
-       49,   50,   47,   49,   50,   64,   77,   81,   75,  124,
-       82,   91,   78,   84,   85,   92,   79,  125,  239,  126,
-      151,   86,   96,   97,   47,  238,   50,   47,  236,   50,
-       52,   53,  152,   96,   98,   99,   54,  235,  100,  101,
-
-      234,   52,   55,   53,  132,  133,  124,  124,  233,  100,
-       98,  102,   96,   97,  243,  125,  243,  243,   96,  237,
-       99,  237,  232,   96,   98,   99,   52,  184,   53,   52,
-       53,  185,  231,  230,  100,   54,  102,  229,  228,  227,
-       52,   55,   53,  226,  225,  224,  100,  101,   96,  223,
-       99,   96,   97,  222,  221,  220,  219,  100,   98,  102,
-      218,  217,   96,   98,   99,   52,  216,   53,   57,   58,
-      237,   59,  237,  215,  240,  214,  213,  212,  211,   57,
-       60,   61,  100,  210,  102,   96,   97,   96,  209,   99,
-       96,   97,  208,  207,  206,  205,   96,   98,   99,  204,
-
-      203,   96,   98,   99,   57,  202,   61,   57,   58,  201,
-       59,  200,  199,  198,  197,  196,  195,  194,   57,   60,
-       61,   96,  193,   99,  192,  191,   96,  190,   99,  189,
-      188,  187,  186,  183,  182,  181,  180,  179,  178,  177,
-      176,  175,  174,   57,  173,   61,  104,  105,  172,  171,
-      170,  169,  106,  168,  167,  166,  165,  104,  107,  105,
-      164,  163,  162,  161,  160,  159,  158,  157,  156,  155,
-      122,  154,  153,  150,  149,  148,  147,  146,  145,  144,
-      143,  142,  104,  141,  105,  108,  109,  140,  139,  138,
-      137,  110,  136,  135,  134,  131,  108,  107,  109,  130,
-
-      127,   66,   65,  122,   94,   93,   90,   89,   88,   87,
-       83,   80,   76,   73,   72,   71,   68,   66,   65,  243,
-      243,  108,  243,  109,  112,  113,  243,  114,  243,  243,
-      243,  243,  243,  243,  243,  112,  115,  116,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      112,  243,  116,  117,  118,  243,  119,  243,  243,  243,
-      243,  243,  243,  243,  117,  115,  120,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  117,
-
-      243,  120,  128,  128,  243,  128,  243,  243,  243,  128,
-      128,  128,  243,  128,  243,  128,  128,  128,  243,  128,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  128,  104,  105,
-      243,  243,  243,  243,  106,  243,  243,  243,  243,  104,
-      107,  105,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  104,  243,  105,  108,  109,  243,
-      243,  243,  243,  110,  243,  243,  243,  243,  108,  107,
-
-      109,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  108,  243,  109,  104,  105,  243,  243,
-      243,  243,  106,  243,  243,  243,  243,  104,  107,  105,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  104,  243,  105,  104,  105,  243,  243,  243,
-      243,  106,  243,  243,  243,  243,  104,  107,  105,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-
-      243,  104,  243,  105,  104,  105,  243,  243,  243,  243,
-      106,  243,  243,  243,  243,  104,  107,  105,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      104,  243,  105,  112,  113,  243,  114,  243,  243,  243,
-      243,  243,  243,  243,  112,  115,  116,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  112,
-      243,  116,  117,  118,  243,  119,  243,  243,  243,  243,
-      243,  243,  243,  117,  115,  120,  243,  243,  243,  243,
-
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  117,  243,
-      120,  112,  113,  243,  114,  243,  243,  243,  243,  243,
-      243,  243,  112,  115,  116,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  112,  243,  116,
-      112,  113,  243,  114,  243,  243,  243,  243,  243,  243,
-      243,  112,  115,  116,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  112,  243,  116,  112,
-
-      113,  243,  114,  243,  243,  243,  243,  243,  243,  243,
-      112,  115,  116,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  112,  243,  116,  112,  113,
-      243,  114,  243,  243,  243,  243,  243,  243,  243,  112,
-      115,  116,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  112,  243,  116,  128,  128,  243,
-      128,  243,  243,  243,  128,  128,  128,  243,  128,  243,
-      128,  128,  128,  243,  128,  243,  243,  243,  243,  243,
-
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  128,   46,   46,   46,   46,   46,   51,   51,
-       51,   51,   51,   56,   56,   56,   56,   56,   62,   62,
-       62,   62,   62,   67,   67,   67,   95,   95,   95,   95,
-       95,  103,  103,  103,  103,  103,  111,  111,  111,  111,
-      111,  121,  121,  121,  121,  123,  123,  123,  123,  123,
-      129,  243,  129,  129,  129,  128,  243,  128,  128,  128,
-      241,  241,  241,  243,  241,   11,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243
+       18,   19,   20,   21,   22,   22,   23,   24,   25,   26,
+       27,   22,   28,   29,   30,   31,   32,   22,   33,   22,
+       22,   34,   22,   35,   36,   37,   38,   39,   40,   41,
+       42,   43,   44,   22,   45,   46,   22,   22,   47,   48,
+       49,   22,   22,   50,   22,   51,   52,   53,   22,   55,
+       56,   91,   55,   56,   92,  283,   93,   71,   71,   97,
+       55,   57,   58,   55,   57,   58,   72,   72,  100,   74,
+       75,  280,  104,   98,  101,  105,   91,  278,  102,  278,
+       74,   76,   75,   74,   75,   55,  279,   58,   55,  114,
+       58,   60,   61,  115,   74,   76,   75,   62,  158,   84,
+
+       85,  277,   60,   63,   61,   74,  147,   77,  107,  108,
+       84,   86,   87,   84,   85,  148,  109,  149,  276,   74,
+      275,   77,  192,  159,   84,   86,   87,   60,  274,   61,
+       60,   61,  173,  174,  193,   84,   62,   85,  273,  272,
+      225,   60,   63,   61,  226,  147,  147,  119,  120,   84,
+      271,   85,  123,  124,  284,  148,  284,  284,  119,  121,
+      122,  270,  269,  123,  121,  125,   60,  268,   61,   65,
+       66,  278,   67,  278,  267,  281,  266,  265,  264,  263,
+       65,   68,   69,  119,  262,  122,  151,  152,  123,  261,
+      125,  155,  156,  260,  259,  258,  257,  151,  153,  152,
+
+      256,  255,  155,  153,  156,   65,  254,   69,   65,   66,
+      253,   67,  252,  251,  250,  249,  248,  247,  246,   65,
+       68,   69,  151,  245,  154,  244,  243,  155,  242,  157,
+      241,  240,  239,  238,  237,  236,  235,  234,  233,  232,
+      162,  163,  231,  230,   65,  229,   69,   78,   78,   78,
+       78,  162,  164,  165,   80,   78,   78,   78,  228,   78,
+      227,   78,   78,   78,  224,   78,  223,  222,   81,  221,
+      220,  166,  167,  219,  218,  217,  162,  216,  163,  215,
+      214,  213,  166,  164,  168,  212,  211,  210,  209,  119,
+      120,  208,   78,   78,   78,   82,   78,   78,   78,   78,
+
+      119,  121,  122,   80,   78,   78,   78,  166,   78,  167,
+       78,   78,   78,  207,   78,  206,  205,   81,  204,  203,
+      202,  201,  200,  123,  124,  119,  199,  122,  198,  197,
+      196,  145,  195,  194,  123,  121,  125,  119,  120,  191,
+      190,   78,   78,   78,   82,  127,  128,  189,  119,  121,
+      122,  129,  188,  119,  120,  187,  127,  130,  128,  123,
+      186,  125,  185,  184,  119,  121,  122,  119,  120,  183,
+      182,  181,  180,  119,  179,  122,  178,  177,  119,  121,
+      122,  127,  176,  128,  131,  132,  175,  172,  171,  119,
+      133,  122,  169,   89,   88,  131,  130,  132,  145,  117,
+
+      116,  151,  152,  119,  113,  122,  155,  156,  112,  111,
+      110,  106,  151,  153,  152,  103,   99,  155,  153,  156,
+      131,   96,  132,  135,  136,   95,  137,   94,   90,   89,
+       88,  284,  284,  284,  135,  138,  139,  151,  284,  154,
+      151,  152,  155,  284,  157,  151,  152,  284,  284,  284,
+      284,  151,  153,  152,  284,  284,  151,  153,  152,  135,
+      284,  139,  140,  141,  284,  142,  284,  284,  284,  284,
+      284,  284,  284,  140,  138,  143,  151,  284,  154,  151,
+      152,  151,  284,  154,  162,  163,  284,  284,  284,  284,
+      151,  153,  152,  166,  167,  162,  164,  165,  140,  284,
+
+      143,  127,  128,  284,  166,  164,  168,  129,  284,  284,
+      284,  284,  127,  130,  128,  151,  284,  154,  284,  284,
+      162,  284,  163,  162,  163,  284,  284,  284,  284,  166,
+      284,  167,  162,  163,  162,  164,  165,  127,  284,  128,
+      131,  132,  284,  162,  164,  165,  133,  284,  284,  284,
+      284,  131,  130,  132,  284,  284,  284,  284,  284,  162,
+      284,  163,  162,  163,  284,  284,  284,  284,  162,  284,
+      163,  284,  284,  162,  164,  165,  131,  284,  132,  127,
+      128,  284,  284,  284,  284,  129,  284,  284,  284,  284,
+      127,  130,  128,  284,  284,  284,  284,  284,  162,  284,
+
+      163,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  127,  284,  128,  127,  128,
+      284,  284,  284,  284,  129,  284,  284,  284,  284,  127,
+      130,  128,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  127,  284,  128,  127,  128,  284,
+      284,  284,  284,  129,  284,  284,  284,  284,  127,  130,
+      128,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  127,  284,  128,  135,  136,  284,  137,
+
+      284,  284,  284,  284,  284,  284,  284,  135,  138,  139,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  135,  284,  139,  140,  141,  284,  142,  284,
+      284,  284,  284,  284,  284,  284,  140,  138,  143,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  140,  284,  143,  135,  136,  284,  137,  284,  284,
+      284,  284,  284,  284,  284,  135,  138,  139,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      135,  284,  139,  135,  136,  284,  137,  284,  284,  284,
+      284,  284,  284,  284,  135,  138,  139,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  135,
+      284,  139,  135,  136,  284,  137,  284,  284,  284,  284,
+      284,  284,  284,  135,  138,  139,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  135,  284,
+      139,  135,  136,  284,  137,  284,  284,  284,  284,  284,
+
+      284,  284,  135,  138,  139,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  135,  284,  139,
+       54,   54,   54,   54,   54,   59,   59,   59,   59,   59,
+       64,   64,   64,   64,   64,   70,   70,   70,   70,   70,
+       73,   73,   73,   73,   73,   79,   79,   79,   79,   79,
+       83,   83,   83,   83,   83,   91,  284,   91,   91,   91,
+      118,  118,  118,  118,  118,  126,  126,  126,  126,  126,
+      134,  134,  134,  134,  134,  144,  144,  144,  144,  146,
+      146,  146,  146,  146,  150,  150,  150,  150,  150,  160,
+
+      284,  160,  160,  160,  161,  161,  161,  161,  161,  170,
+      284,  170,  170,  170,   91,   91,   91,  282,  282,  282,
+      284,  282,   17,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284
     } ;
 
-static yyconst flex_int16_t yy_chk[1035] =
+static yyconst flex_int16_t yy_chk[1073] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    3,    3,
-        9,    4,    4,   22,   29,   22,  241,   10,    9,    3,
-        3,    3,    4,    4,    4,   10,   31,   33,   29,   64,
-       33,   40,   31,   35,   35,   40,   31,   64,  233,   64,
-       92,   35,   46,   46,    3,  232,    3,    4,  228,    4,
-        5,    5,   92,   46,   46,   46,    5,  227,   49,   49,
-
-      225,    5,    5,    5,   74,   74,  123,  125,  224,   49,
-       49,   49,   95,   95,  123,  125,  123,  125,   46,  229,
-       46,  229,  222,   95,   95,   95,    5,  160,    5,    6,
-        6,  160,  220,  218,   49,    6,   49,  217,  216,  214,
-        6,    6,    6,  212,  211,  210,   98,   98,   95,  208,
-       95,  100,  100,  206,  205,  204,  203,   98,   98,   98,
-      202,  201,  100,  100,  100,    6,  199,    6,    7,    7,
-      237,    7,  237,  198,  237,  197,  196,  195,  192,    7,
-        7,    7,   98,  191,   98,  101,  101,  100,  190,  100,
-      102,  102,  189,  188,  187,  186,  101,  101,  101,  185,
-
-      184,  102,  102,  102,    7,  181,    7,    8,    8,  180,
-        8,  179,  178,  177,  176,  175,  174,  173,    8,    8,
-        8,  101,  172,  101,  170,  169,  102,  168,  102,  165,
-      164,  163,  161,  159,  157,  156,  155,  154,  153,  152,
-      151,  150,  149,    8,  148,    8,   51,   51,  147,  146,
-      145,  144,   51,  143,  142,  141,  140,   51,   51,   51,
-      138,  137,  136,  135,  134,  133,  132,  131,  130,  127,
-      121,   94,   93,   91,   90,   89,   88,   87,   86,   85,
-       84,   83,   51,   82,   51,   55,   55,   81,   80,   79,
-       78,   55,   77,   76,   75,   73,   55,   55,   55,   72,
-
-       68,   66,   65,   62,   42,   41,   39,   38,   37,   36,
-       34,   32,   30,   28,   27,   25,   17,   15,   13,   11,
-        0,   55,    0,   55,   56,   56,    0,   56,    0,    0,
-        0,    0,    0,    0,    0,   56,   56,   56,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       56,    0,   56,   60,   60,    0,   60,    0,    0,    0,
-        0,    0,    0,    0,   60,   60,   60,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,   60,
-
-        0,   60,   70,   70,    0,   70,    0,    0,    0,   70,
-       70,   70,    0,   70,    0,   70,   70,   70,    0,   70,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
+        3,   24,    4,    4,   29,  282,   29,    9,   10,   37,
+        3,    3,    3,    4,    4,    4,    9,   10,   39,   11,
+       11,  274,   41,   37,   39,   41,   24,  270,   39,  270,
+       11,   11,   11,   12,   12,    3,  273,    3,    4,   48,
+        4,    5,    5,   48,   12,   12,   12,    5,   80,   15,
+
+       15,  269,    5,    5,    5,   11,   72,   11,   43,   43,
+       15,   15,   15,   16,   16,   72,   43,   72,  268,   12,
+      266,   12,  115,   80,   16,   16,   16,    5,  265,    5,
+        6,    6,   97,   97,  115,   15,    6,   15,  263,  261,
+      201,    6,    6,    6,  201,  146,  148,   54,   54,   16,
+      259,   16,   57,   57,  146,  148,  146,  148,   54,   54,
+       54,  258,  257,   57,   57,   57,    6,  255,    6,    7,
+        7,  278,    7,  278,  253,  278,  252,  251,  249,  247,
+        7,    7,    7,   54,  246,   54,   73,   73,   57,  245,
+       57,   76,   76,  244,  243,  242,  240,   73,   73,   73,
+
+      239,  238,   76,   76,   76,    7,  237,    7,    8,    8,
+      236,    8,  233,  232,  231,  230,  229,  228,  227,    8,
+        8,    8,   73,  226,   73,  225,  222,   76,  221,   76,
+      220,  219,  218,  217,  216,  215,  214,  213,  211,  210,
+       83,   83,  209,  206,    8,  205,    8,   13,   13,   13,
+       13,   83,   83,   83,   13,   13,   13,   13,  204,   13,
+      202,   13,   13,   13,  200,   13,  198,  197,   13,  196,
+      195,   86,   86,  194,  193,  192,   83,  191,   83,  190,
+      189,  188,   86,   86,   86,  187,  186,  185,  184,  118,
+      118,  183,   13,   13,   13,   13,   14,   14,   14,   14,
+
+      118,  118,  118,   14,   14,   14,   14,   86,   14,   86,
+       14,   14,   14,  182,   14,  181,  179,   14,  178,  177,
+      176,  175,  174,  121,  121,  118,  173,  118,  172,  171,
+      169,  144,  117,  116,  121,  121,  121,  123,  123,  114,
+      113,   14,   14,   14,   14,   59,   59,  112,  123,  123,
+      123,   59,  111,  124,  124,  110,   59,   59,   59,  121,
+      109,  121,  108,  107,  124,  124,  124,  125,  125,  106,
+      105,  104,  103,  123,  102,  123,  101,  100,  125,  125,
+      125,   59,   99,   59,   63,   63,   98,   96,   95,  124,
+       63,  124,   90,   89,   88,   63,   63,   63,   70,   50,
+
+       49,  150,  150,  125,   47,  125,  153,  153,   46,   45,
+       44,   42,  150,  150,  150,   40,   38,  153,  153,  153,
+       63,   36,   63,   64,   64,   35,   64,   32,   23,   21,
+       19,   17,    0,    0,   64,   64,   64,  150,    0,  150,
+      155,  155,  153,    0,  153,  156,  156,    0,    0,    0,
+        0,  155,  155,  155,    0,    0,  156,  156,  156,   64,
+        0,   64,   68,   68,    0,   68,    0,    0,    0,    0,
+        0,    0,    0,   68,   68,   68,  155,    0,  155,  157,
+      157,  156,    0,  156,  161,  161,    0,    0,    0,    0,
+      157,  157,  157,  164,  164,  161,  161,  161,   68,    0,
+
+       68,  126,  126,    0,  164,  164,  164,  126,    0,    0,
+        0,    0,  126,  126,  126,  157,    0,  157,    0,    0,
+      161,    0,  161,  166,  166,    0,    0,    0,    0,  164,
+        0,  164,  167,  167,  166,  166,  166,  126,    0,  126,
+      130,  130,    0,  167,  167,  167,  130,    0,    0,    0,
+        0,  130,  130,  130,    0,    0,    0,    0,    0,  166,
+        0,  166,  168,  168,    0,    0,    0,    0,  167,    0,
+      167,    0,    0,  168,  168,  168,  130,    0,  130,  131,
+      131,    0,    0,    0,    0,  131,    0,    0,    0,    0,
+      131,  131,  131,    0,    0,    0,    0,    0,  168,    0,
+
+      168,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  131,    0,  131,  132,  132,
+        0,    0,    0,    0,  132,    0,    0,    0,    0,  132,
+      132,  132,    0,    0,    0,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  132,    0,  132,  133,  133,    0,
+        0,    0,    0,  133,    0,    0,    0,    0,  133,  133,
+      133,    0,    0,    0,    0,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,   70,  103,  103,
-        0,    0,    0,    0,  103,    0,    0,    0,    0,  103,
-      103,  103,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,  103,    0,  103,  107,  107,    0,
-        0,    0,    0,  107,    0,    0,    0,    0,  107,  107,
+        0,    0,    0,  133,    0,  133,  134,  134,    0,  134,
 
-      107,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,  134,  134,  134,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,  107,    0,  107,  108,  108,    0,    0,
-        0,    0,  108,    0,    0,    0,    0,  108,  108,  108,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,  134,    0,  134,  138,  138,    0,  138,    0,
+        0,    0,    0,    0,    0,    0,  138,  138,  138,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,  108,    0,  108,  109,  109,    0,    0,    0,
-        0,  109,    0,    0,    0,    0,  109,  109,  109,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  138,    0,  138,  140,  140,    0,  140,    0,    0,
+        0,    0,    0,    0,    0,  140,  140,  140,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
 
-        0,  109,    0,  109,  110,  110,    0,    0,    0,    0,
-      110,    0,    0,    0,    0,  110,  110,  110,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      140,    0,  140,  141,  141,    0,  141,    0,    0,    0,
+        0,    0,    0,    0,  141,  141,  141,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-      110,    0,  110,  111,  111,    0,  111,    0,    0,    0,
-        0,    0,    0,    0,  111,  111,  111,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  141,
+        0,  141,  142,  142,    0,  142,    0,    0,    0,    0,
+        0,    0,    0,  142,  142,  142,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,  111,
-        0,  111,  115,  115,    0,  115,    0,    0,    0,    0,
-        0,    0,    0,  115,  115,  115,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  142,    0,
+      142,  143,  143,    0,  143,    0,    0,    0,    0,    0,
 
+        0,    0,  143,  143,  143,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,  115,    0,
-      115,  117,  117,    0,  117,    0,    0,    0,    0,    0,
-        0,    0,  117,  117,  117,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,  117,    0,  117,
-      118,  118,    0,  118,    0,    0,    0,    0,    0,    0,
-        0,  118,  118,  118,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,  118,    0,  118,  119,
-
-      119,    0,  119,    0,    0,    0,    0,    0,    0,    0,
-      119,  119,  119,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,  119,    0,  119,  120,  120,
-        0,  120,    0,    0,    0,    0,    0,    0,    0,  120,
-      120,  120,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,  120,    0,  120,  129,  129,    0,
-      129,    0,    0,    0,  129,  129,  129,    0,  129,    0,
-      129,  129,  129,    0,  129,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,  129,  244,  244,  244,  244,  244,  245,  245,
-      245,  245,  245,  246,  246,  246,  246,  246,  247,  247,
-      247,  247,  247,  248,  248,  248,  249,  249,  249,  249,
-      249,  250,  250,  250,  250,  250,  251,  251,  251,  251,
-      251,  252,  252,  252,  252,  253,  253,  253,  253,  253,
-      254,    0,  254,  254,  254,  255,    0,  255,  255,  255,
-      256,  256,  256,    0,  256,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243,  243,  243,  243,  243,  243,  243,
-      243,  243,  243,  243
+        0,    0,    0,    0,    0,    0,    0,  143,    0,  143,
+      285,  285,  285,  285,  285,  286,  286,  286,  286,  286,
+      287,  287,  287,  287,  287,  288,  288,  288,  288,  288,
+      289,  289,  289,  289,  289,  290,  290,  290,  290,  290,
+      291,  291,  291,  291,  291,  292,    0,  292,  292,  292,
+      293,  293,  293,  293,  293,  294,  294,  294,  294,  294,
+      295,  295,  295,  295,  295,  296,  296,  296,  296,  297,
+      297,  297,  297,  297,  298,  298,  298,  298,  298,  299,
+
+        0,  299,  299,  299,  300,  300,  300,  300,  300,  301,
+        0,  301,  301,  301,  302,  302,  302,  303,  303,  303,
+        0,  303,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -818,10 +842,28 @@ static char pbcstack[400];        /* XXX missing size checks */
 static int pbcpos = 0;
 static void pbcpush(char x);
 static int pbcpop(char x);
-
 static int parencount = 0;
 
 /*
+ * A similar stack to keep track of matching brackets ( [ { } ] ) in word tokens surrounded by ${ ... }
+ */
+static char pbcstack2[400];    /* XXX missing size checks */
+static int pbcpos2 = 0;
+static void pbcpush2(char x);
+static int pbcpop2(char x);
+static int parencount2 = 0;
+
+/*
+ * A similar stack to keep track of matching brackets ( [ { } ] ) in word tokens surrounded by $[ ... ]
+ */
+static char pbcstack3[400];    /* XXX missing size checks */
+static int pbcpos3 = 0;
+static void pbcpush3(char x);
+static int pbcpop3(char x);
+static int parencount3 = 0;
+
+
+/*
  * current line, column and filename, updated as we read the input.
  */
 static int my_lineno = 1;      /* current line in the source */
@@ -908,13 +950,16 @@ static void pbcwhere(const char *text, int *line, int *col )
 #define        STORE_POS
 #define        STORE_LOC
 #endif
-#line 911 "ael_lex.c"
+#line 953 "ael_lex.c"
 
 #define INITIAL 0
 #define paren 1
 #define semic 2
 #define argg 3
 #define comment 4
+#define curlystate 5
+#define wordstate 6
+#define brackstate 7
 
 #ifndef YY_NO_UNISTD_H
 /* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -1147,10 +1192,10 @@ YY_DECL
        register int yy_act;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-#line 189 "ael.flex"
+#line 208 "ael.flex"
 
 
-#line 1153 "ael_lex.c"
+#line 1198 "ael_lex.c"
 
     yylval = yylval_param;
 
@@ -1213,13 +1258,13 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 244 )
+                               if ( yy_current_state >= 285 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
                        ++yy_cp;
                        }
-               while ( yy_current_state != 243 );
+               while ( yy_current_state != 284 );
                yy_cp = yyg->yy_last_accepting_cpos;
                yy_current_state = yyg->yy_last_accepting_state;
 
@@ -1241,267 +1286,438 @@ do_action:    /* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 191 "ael.flex"
+#line 210 "ael.flex"
 { STORE_POS; return LC;}
        YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 192 "ael.flex"
+#line 211 "ael.flex"
 { STORE_POS; return RC;}
        YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 193 "ael.flex"
+#line 212 "ael.flex"
 { STORE_POS; return LP;}
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 194 "ael.flex"
+#line 213 "ael.flex"
 { STORE_POS; return RP;}
        YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 195 "ael.flex"
+#line 214 "ael.flex"
 { STORE_POS; return SEMI;}
        YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 196 "ael.flex"
+#line 215 "ael.flex"
 { STORE_POS; return EQ;}
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 197 "ael.flex"
+#line 216 "ael.flex"
 { STORE_POS; return COMMA;}
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 198 "ael.flex"
+#line 217 "ael.flex"
 { STORE_POS; return COLON;}
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 199 "ael.flex"
+#line 218 "ael.flex"
 { STORE_POS; return AMPER;}
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 200 "ael.flex"
+#line 219 "ael.flex"
 { STORE_POS; return BAR;}
        YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 201 "ael.flex"
+#line 220 "ael.flex"
 { STORE_POS; return EXTENMARK;}
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 202 "ael.flex"
+#line 221 "ael.flex"
 { STORE_POS; return AT;}
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 203 "ael.flex"
+#line 222 "ael.flex"
 {/*comment*/}
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 204 "ael.flex"
+#line 223 "ael.flex"
 { STORE_POS; return KW_CONTEXT;}
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 205 "ael.flex"
+#line 224 "ael.flex"
 { STORE_POS; return KW_ABSTRACT;}
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 206 "ael.flex"
+#line 225 "ael.flex"
 { STORE_POS; return KW_EXTEND;}
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 207 "ael.flex"
+#line 226 "ael.flex"
 { STORE_POS; return KW_MACRO;};
        YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 208 "ael.flex"
+#line 227 "ael.flex"
 { STORE_POS; return KW_GLOBALS;}
        YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 209 "ael.flex"
+#line 228 "ael.flex"
 { STORE_POS; return KW_LOCAL;}
        YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 210 "ael.flex"
+#line 229 "ael.flex"
 { STORE_POS; return KW_IGNOREPAT;}
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 211 "ael.flex"
+#line 230 "ael.flex"
 { STORE_POS; return KW_SWITCH;}
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 212 "ael.flex"
+#line 231 "ael.flex"
 { STORE_POS; return KW_IF;}
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 213 "ael.flex"
+#line 232 "ael.flex"
 { STORE_POS; return KW_IFTIME;}
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 214 "ael.flex"
+#line 233 "ael.flex"
 { STORE_POS; return KW_RANDOM;}
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 215 "ael.flex"
+#line 234 "ael.flex"
 { STORE_POS; return KW_REGEXTEN;}
        YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 216 "ael.flex"
+#line 235 "ael.flex"
 { STORE_POS; return KW_HINT;}
        YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 217 "ael.flex"
+#line 236 "ael.flex"
 { STORE_POS; return KW_ELSE;}
        YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 218 "ael.flex"
+#line 237 "ael.flex"
 { STORE_POS; return KW_GOTO;}
        YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 219 "ael.flex"
+#line 238 "ael.flex"
 { STORE_POS; return KW_JUMP;}
        YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 220 "ael.flex"
+#line 239 "ael.flex"
 { STORE_POS; return KW_RETURN;}
        YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 221 "ael.flex"
+#line 240 "ael.flex"
 { STORE_POS; return KW_BREAK;}
        YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 222 "ael.flex"
+#line 241 "ael.flex"
 { STORE_POS; return KW_CONTINUE;}
        YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 223 "ael.flex"
+#line 242 "ael.flex"
 { STORE_POS; return KW_FOR;}
        YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 224 "ael.flex"
+#line 243 "ael.flex"
 { STORE_POS; return KW_WHILE;}
        YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 225 "ael.flex"
+#line 244 "ael.flex"
 { STORE_POS; return KW_CASE;}
        YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 226 "ael.flex"
+#line 245 "ael.flex"
 { STORE_POS; return KW_DEFAULT;}
        YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 227 "ael.flex"
+#line 246 "ael.flex"
 { STORE_POS; return KW_PATTERN;}
        YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 228 "ael.flex"
+#line 247 "ael.flex"
 { STORE_POS; return KW_CATCH;}
        YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 229 "ael.flex"
+#line 248 "ael.flex"
 { STORE_POS; return KW_SWITCHES;}
        YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 230 "ael.flex"
+#line 249 "ael.flex"
 { STORE_POS; return KW_ESWITCHES;}
        YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 231 "ael.flex"
+#line 250 "ael.flex"
 { STORE_POS; return KW_INCLUDES;}
        YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 232 "ael.flex"
+#line 251 "ael.flex"
 { BEGIN(comment); my_col += 2; }
        YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 234 "ael.flex"
+#line 253 "ael.flex"
 { my_col += yyleng; }
        YY_BREAK
 case 44:
 /* rule 44 can match eol */
 YY_RULE_SETUP
-#line 235 "ael.flex"
+#line 254 "ael.flex"
 { ++my_lineno; my_col=1;}
        YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 236 "ael.flex"
+#line 255 "ael.flex"
 { my_col += yyleng; }
        YY_BREAK
 case 46:
 /* rule 46 can match eol */
 YY_RULE_SETUP
-#line 237 "ael.flex"
+#line 256 "ael.flex"
 { ++my_lineno; my_col=1;}
        YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 238 "ael.flex"
-{ my_col += 2; BEGIN(INITIAL); }
+#line 257 "ael.flex"
+{ my_col += 2; BEGIN(INITIAL); } /* the nice thing about comments is that you know exactly what ends them */
        YY_BREAK
 case 48:
 /* rule 48 can match eol */
 YY_RULE_SETUP
-#line 240 "ael.flex"
+#line 259 "ael.flex"
 { my_lineno++; my_col = 1; }
        YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 241 "ael.flex"
+#line 260 "ael.flex"
 { my_col += yyleng; }
        YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 242 "ael.flex"
+#line 261 "ael.flex"
 { my_col += (yyleng*8)-(my_col%8); }
        YY_BREAK
 case 51:
 YY_RULE_SETUP
-#line 244 "ael.flex"
+#line 263 "ael.flex"
+{ 
+      /* boy did I open a can of worms when I changed the lexical token "word". 
+                all the above keywords can be used as a beginning to a "word".-
+                before, a "word" would match a longer sequence than the above   
+            keywords, and all would be well. But now "word" is a single char           
+            and feeds into a statemachine sort of sequence from there on. So...
+                I added the {KEYWORD}? to the beginning of the word match sequence */
+
+               if (!strcmp(yytext,"${")) {
+                       parencount2 = 0;
+                       pbcpos2 = 0;
+                       pbcpush2('{');  /* push '{' so the last pcbpop (parencount2 = -1) will succeed */
+                       BEGIN(curlystate);
+                       yymore();
+               } else if (!strcmp(yytext,"$[")) {
+                       parencount3 = 0;
+                       pbcpos3 = 0;
+                       pbcpush3('[');  /* push '[' so the last pcbpop (parencount3 = -1) will succeed */
+                       BEGIN(brackstate);
+                       yymore();
+               } else {
+                   BEGIN(wordstate);
+                       yymore();
+               }
+       }
+       YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 289 "ael.flex"
+{ yymore(); /* Keep going */ }
+       YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 290 "ael.flex"
+{ yymore(); /* Keep going */ }
+       YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 291 "ael.flex"
+{ yymore(); /* Keep Going */ }
+       YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 292 "ael.flex"
+{ /* the beginning of a ${} construct. prepare and pop into curlystate */
+               parencount2 = 0;
+               pbcpos2 = 0;
+               pbcpush2('{');  /* push '{' so the last pcbpop (parencount2 = -1) will succeed */
+               BEGIN(curlystate);
+               yymore();
+       }
+       YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 299 "ael.flex"
+{ /* the beginning of a $[] construct. prepare and pop into brackstate */
+               parencount3 = 0;
+               pbcpos3 = 0;
+               pbcpush3('[');  /* push '[' so the last pcbpop (parencount3 = -1) will succeed */
+               BEGIN(brackstate);
+               yymore();
+       }
+       YY_BREAK
+case 57:
+/* rule 57 can match eol */
+YY_RULE_SETUP
+#line 306 "ael.flex"
 {
+               /* a non-word constituent char, like a space, tab, curly, paren, etc */
+               char c = yytext[yyleng-1];
                STORE_POS;
                yylval->str = strdup(yytext);
-               prev_word = yylval->str;
+               yylval->str[yyleng-1] = 0;
+               unput(c);  /* put this ending char back in the stream */
+               BEGIN(0);
                return word;
        }
        YY_BREAK
+case 58:
+/* rule 58 can match eol */
+YY_RULE_SETUP
+#line 318 "ael.flex"
+{
+               if ( pbcpop2('}') ) {   /* error */
+                       STORE_LOC;
+                       ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);
+                       BEGIN(0);
+                       yylval->str = strdup(yytext);
+                       return word;
+               }
+               parencount2--;
+               if ( parencount2 >= 0) {
+                       yymore();
+               } else {
+                       BEGIN(wordstate); /* Finished with the current ${} construct. Return to word gathering state */
+                       yymore();
+               }
+       }
+       YY_BREAK
+case 59:
+/* rule 59 can match eol */
+YY_RULE_SETUP
+#line 335 "ael.flex"
+{ 
+               char c = yytext[yyleng-1];
+               if (c == '{')
+                       parencount2++;
+               pbcpush2(c);
+               yymore();
+       }
+       YY_BREAK
+case 60:
+/* rule 60 can match eol */
+YY_RULE_SETUP
+#line 343 "ael.flex"
+{ 
+               char c = yytext[yyleng-1];
+               if ( pbcpop2(c))  { /* error */
+                       STORE_LOC;
+                       ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",
+                               my_file, my_lineno, my_col, c);
+                       BEGIN(0);
+                       yylval->str = strdup(yytext);
+                       return word;
+               }
+               yymore();
+       }
+       YY_BREAK
+case 61:
+/* rule 61 can match eol */
+YY_RULE_SETUP
+#line 357 "ael.flex"
+{
+               if ( pbcpop3(']') ) {   /* error */
+                       STORE_LOC;
+                       ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);
+                       BEGIN(0);
+                       yylval->str = strdup(yytext);
+                       return word;
+               }
+               parencount3--;
+               if ( parencount3 >= 0) {
+                       yymore();
+               } else {
+                       BEGIN(wordstate); /* Finished with the current ${} construct. Return to word gathering state */
+                       yymore();
+               }
+       }
+       YY_BREAK
+case 62:
+/* rule 62 can match eol */
+YY_RULE_SETUP
+#line 374 "ael.flex"
+{ 
+               char c = yytext[yyleng-1];
+               if (c == '[')
+                       parencount3++;
+               pbcpush3(c);
+               yymore();
+       }
+       YY_BREAK
+case 63:
+/* rule 63 can match eol */
+YY_RULE_SETUP
+#line 382 "ael.flex"
+{ 
+               char c = yytext[yyleng-1];
+               if ( pbcpop3(c))  { /* error */
+                       STORE_LOC;
+                       ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",
+                               my_file, my_lineno, my_col, c);
+                       BEGIN(0);
+                       yylval->str = strdup(yytext);
+                       return word;
+               }
+               yymore();
+       }
+       YY_BREAK
 /*
         * context used for arguments of if_head, random_head, switch_head,
         * for (last statement), while (XXX why not iftime_head ?).
@@ -1509,10 +1725,10 @@ YY_RULE_SETUP
         * A comma at the top level is valid here, unlike in argg where it
         * is an argument separator so it must be returned as a token.
         */
-case 52:
-/* rule 52 can match eol */
+case 64:
+/* rule 64 can match eol */
 YY_RULE_SETUP
-#line 260 "ael.flex"
+#line 403 "ael.flex"
 {
                if ( pbcpop(')') ) {    /* error */
                        STORE_LOC;
@@ -1535,10 +1751,10 @@ YY_RULE_SETUP
                }
        }
        YY_BREAK
-case 53:
-/* rule 53 can match eol */
+case 65:
+/* rule 65 can match eol */
 YY_RULE_SETUP
-#line 282 "ael.flex"
+#line 425 "ael.flex"
 {
                char c = yytext[yyleng-1];
                if (c == '(')
@@ -1547,10 +1763,10 @@ YY_RULE_SETUP
                yymore();
        }
        YY_BREAK
-case 54:
-/* rule 54 can match eol */
+case 66:
+/* rule 66 can match eol */
 YY_RULE_SETUP
-#line 290 "ael.flex"
+#line 433 "ael.flex"
 {
                char c = yytext[yyleng-1];
                if ( pbcpop(c))  { /* error */
@@ -1572,10 +1788,10 @@ YY_RULE_SETUP
         * of the (external) call, which happens when parencount == 0
         * before the decrement.
         */
-case 55:
-/* rule 55 can match eol */
+case 67:
+/* rule 67 can match eol */
 YY_RULE_SETUP
-#line 312 "ael.flex"
+#line 455 "ael.flex"
 {
                char c = yytext[yyleng-1];
                if (c == '(')
@@ -1584,10 +1800,10 @@ YY_RULE_SETUP
                yymore();
        }
        YY_BREAK
-case 56:
-/* rule 56 can match eol */
+case 68:
+/* rule 68 can match eol */
 YY_RULE_SETUP
-#line 320 "ael.flex"
+#line 463 "ael.flex"
 {
                if ( pbcpop(')') ) { /* error */
                        STORE_LOC;
@@ -1612,10 +1828,10 @@ YY_RULE_SETUP
                }
        }
        YY_BREAK
-case 57:
-/* rule 57 can match eol */
+case 69:
+/* rule 69 can match eol */
 YY_RULE_SETUP
-#line 344 "ael.flex"
+#line 487 "ael.flex"
 {
                if( parencount != 0) { /* printf("Folding in a comma!\n"); */
                        yymore();
@@ -1630,10 +1846,10 @@ YY_RULE_SETUP
                }
        }
        YY_BREAK
-case 58:
-/* rule 58 can match eol */
+case 70:
+/* rule 70 can match eol */
 YY_RULE_SETUP
-#line 358 "ael.flex"
+#line 501 "ael.flex"
 {
                char c = yytext[yyleng-1];
                if ( pbcpop(c) ) { /* error */
@@ -1651,20 +1867,20 @@ YY_RULE_SETUP
         * or in the first and second operand of a 'for'. As above, match
         * commas and use ';' as a separator (hence return it as a separate token).
         */
-case 59:
-/* rule 59 can match eol */
+case 71:
+/* rule 71 can match eol */
 YY_RULE_SETUP
-#line 375 "ael.flex"
+#line 518 "ael.flex"
 {
                char c = yytext[yyleng-1];
                yymore();
                pbcpush(c);
        }
        YY_BREAK
-case 60:
-/* rule 60 can match eol */
+case 72:
+/* rule 72 can match eol */
 YY_RULE_SETUP
-#line 381 "ael.flex"
+#line 524 "ael.flex"
 {
                char c = yytext[yyleng-1];
                if ( pbcpop(c) ) { /* error */
@@ -1677,10 +1893,10 @@ YY_RULE_SETUP
                yymore();
        }
        YY_BREAK
-case 61:
-/* rule 61 can match eol */
+case 73:
+/* rule 73 can match eol */
 YY_RULE_SETUP
-#line 393 "ael.flex"
+#line 536 "ael.flex"
 {
                STORE_LOC;
                yylval->str = strdup(yytext);
@@ -1690,10 +1906,10 @@ YY_RULE_SETUP
                return word;
        }
        YY_BREAK
-case 62:
-/* rule 62 can match eol */
+case 74:
+/* rule 74 can match eol */
 YY_RULE_SETUP
-#line 402 "ael.flex"
+#line 545 "ael.flex"
 {
                char fnamebuf[1024],*p1,*p2;
                int glob_ret;
@@ -1743,7 +1959,10 @@ case YY_STATE_EOF(paren):
 case YY_STATE_EOF(semic):
 case YY_STATE_EOF(argg):
 case YY_STATE_EOF(comment):
-#line 447 "ael.flex"
+case YY_STATE_EOF(curlystate):
+case YY_STATE_EOF(wordstate):
+case YY_STATE_EOF(brackstate):
+#line 590 "ael.flex"
 {
                char fnamebuf[2048];
                if (include_stack_index > 0 && include_stack[include_stack_index-1].globbuf_pos < include_stack[include_stack_index-1].globbuf.gl_pathc-1) {
@@ -1776,12 +1995,12 @@ case YY_STATE_EOF(comment):
                }
        }
        YY_BREAK
-case 63:
+case 75:
 YY_RULE_SETUP
-#line 479 "ael.flex"
+#line 622 "ael.flex"
 ECHO;
        YY_BREAK
-#line 1784 "ael_lex.c"
+#line 2003 "ael_lex.c"
 
        case YY_END_OF_BUFFER:
                {
@@ -2066,7 +2285,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 244 )
+                       if ( yy_current_state >= 285 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -2095,11 +2314,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 244 )
+               if ( yy_current_state >= 285 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 243);
+       yy_is_jam = (yy_current_state == 284);
 
        return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2906,7 +3125,7 @@ void *ael_yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
 
 #define YYTABLES_NAME "yytables"
 
-#line 479 "ael.flex"
+#line 622 "ael.flex"
 
 
 
@@ -2932,6 +3151,38 @@ static int pbcpop(char x)
        return 1; /* error */
 }
 
+static void pbcpush2(char x)
+{
+       pbcstack2[pbcpos2++] = x;
+}
+
+static int pbcpop2(char x)
+{
+       if (   ( x == ')' && pbcstack2[pbcpos2-1] == '(' )
+               || ( x == ']' && pbcstack2[pbcpos2-1] == '[' )
+               || ( x == '}' && pbcstack2[pbcpos2-1] == '{' )) {
+               pbcpos2--;
+               return 0;
+       }
+       return 1; /* error */
+}
+
+static void pbcpush3(char x)
+{
+       pbcstack3[pbcpos3++] = x;
+}
+
+static int pbcpop3(char x)
+{
+       if (   ( x == ')' && pbcstack3[pbcpos3-1] == '(' )
+               || ( x == ']' && pbcstack3[pbcpos3-1] == '[' )
+               || ( x == '}' && pbcstack3[pbcpos3-1] == '{' )) {
+               pbcpos3--;
+               return 0;
+       }
+       return 1; /* error */
+}
+
 static int c_prevword(void)
 {
        char *c = prev_word;