final step to context based macro interpreter
[nedit-bw.git] / ParseFields3.diff
blobda2ade800490ee44799b0fcbf2111919127d0504
1 From: Tony Balinski <ajbj@free.fr>
2 Subject: Use the '.' operator as an array accessor
4 Available as a patch:
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.
24 ---
26 source/parse.y | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
27 1 file changed, 98 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 '.' */
42 %union {
43 @@ -85,7 +89,7 @@ static int AllowDefine;
44 int num;
45 AccumulatorData *acc;
47 -%token <sym> STRING SYMBOL
48 +%token <sym> STRING SYMBOL FIELD
49 %token <num> NUMBER
50 %token DELETE ARG_LOOKUP
51 %token IF WHILE ELSE FOR BREAK CONTINUE RETURN
52 @@ -111,6 +115,7 @@ static int AllowDefine;
53 %nonassoc DELETE
54 %nonassoc INCR DECR
55 %right POW
56 +%left '.'
57 %nonassoc '['
58 %nonassoc '('
60 @@ -251,6 +256,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);
66 + }
67 + /* array[index] assignment */
68 | initarraylv '[' arglist ']' '=' expr {
69 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
71 @@ -309,6 +318,65 @@ simpstmt: SYMBOL '=' expr {
72 ADD_OP(OP_DECR);
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);
78 + }
79 + | initarraylv dot field ADDEQ expr {
80 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
81 + ADD_OP(OP_ADD);
82 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
83 + }
84 + | initarraylv dot field SUBEQ expr {
85 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
86 + ADD_OP(OP_SUB);
87 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
88 + }
89 + | initarraylv dot field MULEQ expr {
90 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
91 + ADD_OP(OP_MUL);
92 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
93 + }
94 + | initarraylv dot field DIVEQ expr {
95 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
96 + ADD_OP(OP_DIV);
97 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
98 + }
99 + | initarraylv dot field MODEQ expr {
100 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
101 + ADD_OP(OP_MOD);
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);
111 + ADD_OP(OP_BIT_OR);
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);
116 + ADD_OP(OP_INCR);
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);
121 + ADD_OP(OP_DECR);
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);
126 + ADD_OP(OP_INCR);
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);
131 + ADD_OP(OP_DECR);
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 @@ -376,6 +444,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);
145 arraylv: SYMBOL {
146 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(0);
147 @@ -383,7 +454,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);
156 +field: FIELD {
157 + ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
159 + /* this bit allows things like array.5 for array[5] **
160 + | NUMBER {
161 + ADD_OP(OP_PUSH_IMMED); ADD_IMMED($1);
163 + */
166 arrayexpr: numexpr {
167 $$ = GetPC();
169 @@ -415,6 +500,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 {
177 ADD_OP(OP_ADD);
179 @@ -518,6 +606,10 @@ or: OR {
180 ADD_BR_OFF(0);
183 +dot: '.' %prec '.' {
184 + nextSymIsField = 1;
187 blank: /* nothing */
188 | blank '\n'
190 @@ -635,6 +727,11 @@ static int yylex(void)
191 if (!strcmp(symName, "$args")) return ARG_LOOKUP;
192 if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE;
193 if (!strcmp(symName, "define")) return DEFINE;
194 + if (nextSymIsField) {
195 + nextSymIsField = 0;
196 + yylval.sym = InstallStringConstSymbol(symName);
197 + return FIELD;
199 if ((s=LookupSymbol(symName)) == NULL) {
200 s = InstallSymbol(symName, symName[0]=='$' ?
201 (((symName[1] > '0' && symName[1] <= '9') && symName[2] == 0) ?