  Use the '.' operator as an array accessor

  Available as a patch:
  http://sourceforge.net/tracker/index.php?func=detail&aid=974211&group_id=11005&atid=311005
	    [ 974211 ] Use the '.' operator as an array accessor
	    ParseFields2.diff 2004-06-21 22:34

  This allows you to view NEdit macro language arrays as records (both are
  aggregates of heterogeneously typed objects). The only constraint is that
  the accessor must appear like a valid symbol name, although internally it
  is handled as a string. Thus the following statements are equivalent:
	    array["member"] = array["field"]
	    array.member = array.field

  This implementation uses a flag, set when a '.' is scanned, to determine
  whether the next identifier is a field - if so, it doesn't make a symbol
  out of the identifier (leading to a variable in the resultant macro), but
  instead returns a field token, which is just a constant string value used
  as an index into the array.

diff -ur nedit_official/source/parse.y nedit_mod/source/parse.y
--- nedit_official/source/parse.y	2003-12-19 18:23:31.000000000 -0500
+++ nedit_mod/source/parse.y	2004-06-21 22:18:47.759166000 -0400
@@ -52,6 +52,10 @@
 extern Inst *LoopStack[]; /* addresses of break, cont stmts */
 extern Inst **LoopStackPtr;  /*  to fill at the end of a loop */
 
+static int nextSymIsField = 0;
+    /* set to 1 when we don't want a full symbol, just a name (string) for a
+       field name following a '.' */
+
 %}
 
 %union {
@@ -59,7 +63,7 @@
     Inst *inst;
     int nArgs;
 }
-%token <sym> NUMBER STRING SYMBOL
+%token <sym> NUMBER STRING SYMBOL FIELD
 %token DELETE ARG_LOOKUP
 %token IF WHILE ELSE FOR BREAK CONTINUE RETURN
 %type <nArgs> arglist
@@ -83,6 +87,7 @@
 %nonassoc DELETE
 %nonassoc INCR DECR
 %right    POW
+%left     '.'
 %nonassoc '['
 %nonassoc '('
 
@@ -180,6 +185,10 @@
             | DELETE arraylv '[' arglist ']' {
                 ADD_OP(OP_ARRAY_DELETE); ADD_IMMED($4);
             }
+            | DELETE arraylv dot field {
+                ADD_OP(OP_ARRAY_DELETE); ADD_IMMED(1);
+            }
+/* array[index] assignment */
             | initarraylv '[' arglist ']' '=' expr {
                 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
             }
@@ -238,6 +247,65 @@
                 ADD_OP(OP_DECR);
                 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
             }
+/* array.field assignment */
+            | initarraylv dot field '=' expr {
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field ADDEQ expr {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
+                ADD_OP(OP_ADD);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field SUBEQ expr {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
+                ADD_OP(OP_SUB);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field MULEQ expr {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
+                ADD_OP(OP_MUL);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field DIVEQ expr {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
+                ADD_OP(OP_DIV);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field MODEQ expr {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
+                ADD_OP(OP_MOD);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field ANDEQ expr {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
+                ADD_OP(OP_BIT_AND);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field OREQ expr {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
+                ADD_OP(OP_BIT_OR);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field INCR {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
+                ADD_OP(OP_INCR);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | initarraylv dot field DECR {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
+                ADD_OP(OP_DECR);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | INCR initarraylv dot field {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
+                ADD_OP(OP_INCR);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
+            | DECR initarraylv dot field {
+                ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
+                ADD_OP(OP_DECR);
+                ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
+            }
             | SYMBOL '(' arglist ')' {
                 ADD_OP(OP_SUBR_CALL);
                 ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
@@ -294,6 +362,9 @@
                 | initarraylv '[' arglist ']' {
                     ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
                 }
+                | initarraylv dot field {
+                    ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
+                }
                 ;
 arraylv:    SYMBOL {
                 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(0);
@@ -301,6 +372,18 @@
             | arraylv '[' arglist ']' {
                 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
             }
+            | arraylv dot field {
+                ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
+            }
+            ;
+field:      FIELD {
+                ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
+            }
+            /* this bit allows things like array.5 for array[5] **
+            | NUMBER {
+                ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
+            }
+            */
             ;
 arrayexpr:  numexpr {
                 $$ = GetPC();
@@ -333,6 +416,9 @@
             | numexpr '[' arglist ']' {
                 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
             }
+            | numexpr dot field {
+                ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
+            }
             | numexpr '+' numexpr {
                 ADD_OP(OP_ADD);
             }
@@ -436,6 +522,10 @@
             ADD_BR_OFF(0);
         }
         ;
+dot:    '.' %prec '.' {
+            nextSymIsField = 1;
+        }
+        ;
 blank:  /* nothing */
         | blank '\n'
         ;
@@ -552,6 +642,11 @@
                 InPtr -= 6;
                 return 0;
             }
+            if (nextSymIsField) {
+                nextSymIsField = 0;
+                yylval.sym = InstallStringConstSymbol(symName);
+                return FIELD;
+            }
             if ((s=LookupSymbol(symName)) == NULL) {
                 s = InstallSymbol(symName, symName[0]=='$' ?
                         (((symName[1] > '0' && symName[1] <= '9') && symName[2] == 0) ?
