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 ParseFields.diff 2004-06-18 09: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 NUMBER STRING SYMBOL +%token NUMBER STRING SYMBOL FIELD %token DELETE ARG_LOOKUP %token IF WHILE ELSE FOR BREAK CONTINUE RETURN %type 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((void *)$4); } + | DELETE arraylv dot field { + ADD_OP(OP_ARRAY_DELETE); ADD_IMMED((void *)1); + } +/* array[index] assignment */ | initarraylv '[' arglist ']' '=' expr { ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)$3); } @@ -238,6 +247,65 @@ ADD_OP(OP_DECR); ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)$4); } +/* array.field assignment */ + | initarraylv dot field '=' expr { + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field ADDEQ expr { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)1); ADD_IMMED((void *)1); + ADD_OP(OP_ADD); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field SUBEQ expr { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)1); ADD_IMMED((void *)1); + ADD_OP(OP_SUB); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field MULEQ expr { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)1); ADD_IMMED((void *)1); + ADD_OP(OP_MUL); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field DIVEQ expr { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)1); ADD_IMMED((void *)1); + ADD_OP(OP_DIV); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field MODEQ expr { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)1); ADD_IMMED((void *)1); + ADD_OP(OP_MOD); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field ANDEQ expr { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)1); ADD_IMMED((void *)1); + ADD_OP(OP_BIT_AND); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field OREQ expr { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)1); ADD_IMMED((void *)1); + ADD_OP(OP_BIT_OR); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field INCR { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)0); ADD_IMMED((void *)1); + ADD_OP(OP_INCR); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | initarraylv dot field DECR { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)0); ADD_IMMED((void *)1); + ADD_OP(OP_DECR); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | INCR initarraylv dot field { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)0); ADD_IMMED((void *)1); + ADD_OP(OP_INCR); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } + | DECR initarraylv dot field { + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED((void *)0); ADD_IMMED((void *)1); + ADD_OP(OP_DECR); + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED((void *)1); + } | SYMBOL '(' arglist ')' { ADD_OP(OP_SUBR_CALL); ADD_SYM(PromoteToGlobal($1)); ADD_IMMED((void *)$3); @@ -294,6 +362,9 @@ | initarraylv '[' arglist ']' { ADD_OP(OP_ARRAY_REF); ADD_IMMED((void *)$3); } + | initarraylv dot field { + ADD_OP(OP_ARRAY_REF); ADD_IMMED((void *)1); + } ; arraylv: SYMBOL { ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED((void *)0); @@ -301,6 +372,18 @@ | arraylv '[' arglist ']' { ADD_OP(OP_ARRAY_REF); ADD_IMMED((void *)$3); } + | arraylv dot field { + ADD_OP(OP_ARRAY_REF); ADD_IMMED((void *)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((void *)$3); } + | numexpr dot field { + ADD_OP(OP_ARRAY_REF); ADD_IMMED((void *)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) ?