1 From: Tony Balinski <ajbj@free.fr>
2 Subject: Use the '.' operator as an array accessor
6 http://sourceforge.net/tracker/index.php?func=detail&aid=974211&group_id=11005&atid=311005
7 [ 974211 ] Use the '.' operator as an array accessor
8 ParseFields2.diff 2004-06-21 22:34
10 This allows you to view NEdit macro language arrays as records (both are
11 aggregates of heterogeneously typed objects). The only constraint is that
12 the accessor must appear like a valid symbol name, although internally it
13 is handled as a string. Thus the following statements are equivalent:
15 array["member"] = array["field"]
16 array.member = array.field
18 This implementation uses a flag, set when a '.' is scanned, to determine
19 whether the next identifier is a field - if so, it doesn't make a symbol
20 out of the identifier (leading to a variable in the resultant macro), but
21 instead returns a field token, which is just a constant string value used
22 as an index into the array.
26 source/parse.y | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
27 1 file changed, 102 insertions(+), 1 deletion(-)
29 diff --quilt old/source/parse.y new/source/parse.y
30 --- old/source/parse.y
31 +++ new/source/parse.y
32 @@ -77,6 +77,10 @@ extern Inst **LoopStackPtr; /* to fill
34 static int AllowDefine;
36 +static int nextSymIsField = 0;
37 + /* set to 1 when we don't want a full symbol, just a name (string) for a
38 + field name following a '.' */
43 @@ -88,7 +92,7 @@ static int AllowDefine;
47 -%token <sym> STRING SYMBOL
48 +%token <sym> STRING SYMBOL FIELD
50 %token DELETE ARG_LOOKUP
51 %token IF WHILE ELSE FOR BREAK CONTINUE RETURN DEFINE
52 @@ -114,6 +118,7 @@ static int AllowDefine;
60 @@ -258,6 +263,10 @@ simpstmt: SYMBOL '=' expr {
61 | DELETE arraylv '[' arglist ']' {
62 ADD_OP(OP_ARRAY_DELETE); ADD_IMMED($4);
64 + | DELETE arraylv dot field {
65 + ADD_OP(OP_ARRAY_DELETE); ADD_IMMED(1);
67 + /* array[index] assignment */
68 | initarraylv '[' arglist ']' '=' expr {
69 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
71 @@ -316,6 +325,65 @@ simpstmt: SYMBOL '=' expr {
73 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
75 + /* array.field assignment */
76 + | initarraylv dot field '=' expr {
77 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
79 + | initarraylv dot field ADDEQ expr {
80 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
82 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
84 + | initarraylv dot field SUBEQ expr {
85 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
87 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
89 + | initarraylv dot field MULEQ expr {
90 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
92 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
94 + | initarraylv dot field DIVEQ expr {
95 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
97 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
99 + | initarraylv dot field MODEQ expr {
100 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
102 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
104 + | initarraylv dot field ANDEQ expr {
105 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
106 + ADD_OP(OP_BIT_AND);
107 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
109 + | initarraylv dot field OREQ expr {
110 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
112 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
114 + | initarraylv dot field INCR {
115 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
117 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
119 + | initarraylv dot field DECR {
120 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
122 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
124 + | INCR initarraylv dot field {
125 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
127 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
129 + | DECR initarraylv dot field {
130 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
132 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
134 | SYMBOL '(' arglist ')' {
135 ADD_OP(OP_SUBR_CALL);
136 ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
137 @@ -383,6 +451,9 @@ initarraylv: SYMBOL {
138 | initarraylv '[' arglist ']' {
139 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
141 + | initarraylv dot field {
142 + ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
146 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(0);
147 @@ -390,7 +461,21 @@ arraylv: SYMBOL {
148 | arraylv '[' arglist ']' {
149 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
151 + | arraylv dot field {
152 + ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
157 + ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
159 + /* this bit allows things like array.5 for array[5] **
161 + ADD_OP(OP_PUSH_IMMED); ADD_IMMED($1);
169 @@ -422,6 +507,9 @@ numexpr: NUMBER {
170 | numexpr '[' arglist ']' {
171 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
173 + | numexpr dot field {
174 + ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
176 | numexpr '+' numexpr {
179 @@ -525,6 +613,10 @@ or: OR {
183 +dot: '.' %prec '.' {
184 + nextSymIsField = 1;
190 @@ -555,6 +647,8 @@ Program *ParseMacro(char *expr, char **m
191 /* whether we allow the "define" keyword */
192 AllowDefine = allowDefine;
194 + nextSymIsField = 0;
196 /* call yyparse to parse the string and check for success. If the parse
197 failed, return the error message and string index (the grammar aborts
198 parsing at the first error) */
199 @@ -629,6 +723,7 @@ static int yylex(void)
200 if (isdigit((unsigned char)*InPtr)) { /* number */
201 sscanf(InPtr, "%d%n", &yylval.num, &len);
203 + nextSymIsField = 0;
207 @@ -657,6 +752,11 @@ static int yylex(void)
208 if (!strcmp(symName, "$args")) return ARG_LOOKUP;
209 if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE;
210 if (!strcmp(symName, "define")) return DEFINE;
211 + if (nextSymIsField) {
212 + nextSymIsField = 0;
213 + yylval.sym = InstallStringConstSymbol(symName);
216 if ((s=LookupSymbol(symName)) == NULL) {
217 s = InstallSymbol(symName, symName[0]=='$' ?
218 (((symName[1] > '0' && symName[1] <= '9') && symName[2] == 0) ?
219 @@ -667,6 +767,7 @@ static int yylex(void)
223 + nextSymIsField = 0;
225 /* Process quoted strings with embedded escape sequences:
226 For backslashes we recognise hexadecimal values with initial 'x' such