break/continue to outer loops, !!booleanize
[nedit-bw.git] / ParseFields3.diff
blobf12c675498a579a8339f85b58cd8cb7412e7d99d
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 | 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 '.' */
42 %union {
43 @@ -88,7 +92,7 @@ static int AllowDefine;
44 Symbol *sym;
45 } define;
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 DEFINE
52 @@ -114,6 +118,7 @@ static int AllowDefine;
53 %nonassoc DELETE
54 %nonassoc INCR DECR
55 %right POW
56 +%left '.'
57 %nonassoc '['
58 %nonassoc '('
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);
66 + }
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 {
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 @@ -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);
145 arraylv: SYMBOL {
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);
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 @@ -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 {
177 ADD_OP(OP_ADD);
179 @@ -525,6 +613,10 @@ or: OR {
180 ADD_BR_OFF(0);
183 +dot: '.' %prec '.' {
184 + nextSymIsField = 1;
187 blank: /* nothing */
188 | blank '\n'
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);
202 InPtr += len;
203 + nextSymIsField = 0;
204 return NUMBER;
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);
214 + return FIELD;
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)
220 yylval.sym = s;
221 return SYMBOL;
223 + nextSymIsField = 0;
225 /* Process quoted strings with embedded escape sequences:
226 For backslashes we recognise hexadecimal values with initial 'x' such