Subversion Repositories Kolibri OS

Rev

Rev 7693 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 7693 Rev 7696
1
(*
1
(*
2
    BSD 2-Clause License
2
    BSD 2-Clause License
3
 
3
 
4
    Copyright (c) 2018, 2019, Anton Krotov
4
    Copyright (c) 2018-2019, Anton Krotov
5
    All rights reserved.
5
    All rights reserved.
6
*)
6
*)
7
 
7
 
8
MODULE PARS;
8
MODULE PARS;
9
 
9
 
10
IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, IL, CONSOLE, PATHS, UTILS, C := COLLECTIONS, mConst := CONSTANTS;
10
IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, IL, CONSOLE, PATHS, UTILS, C := COLLECTIONS, mConst := CONSTANTS;
11
 
11
 
12
 
12
 
13
CONST
13
CONST
14
 
14
 
15
    eCONST*   =  1;  eTYPE*   =  2;  eVAR*     =  3;  eEXPR*    =  4;
15
    eCONST*   =  1;  eTYPE*   =  2;  eVAR*     =  3;  eEXPR*    =  4;
16
    eVREC*    =  5;  ePROC*   =  6;  eVPAR*    =  7;  ePARAM*   =  8;
16
    eVREC*    =  5;  ePROC*   =  6;  eVPAR*    =  7;  ePARAM*   =  8;
17
    eSTPROC*  =  9;  eSTFUNC* = 10;  eSYSFUNC* = 11;  eSYSPROC* = 12;
17
    eSTPROC*  =  9;  eSTFUNC* = 10;  eSYSFUNC* = 11;  eSYSPROC* = 12;
18
    eIMP*     = 13;
18
    eIMP*     = 13;
19
 
19
 
20
 
20
 
21
TYPE
21
TYPE
22
 
22
 
23
    PATH* = PATHS.PATH;
23
    PATH* = PATHS.PATH;
24
 
24
 
25
    PARSER* = POINTER TO rPARSER;
25
    PARSER* = POINTER TO rPARSER;
26
 
26
 
27
    POSITION* = RECORD (SCAN.POSITION)
27
    POSITION* = RECORD (SCAN.POSITION)
28
 
28
 
29
        parser*: PARSER
29
        parser*: PARSER
30
 
30
 
31
    END;
31
    END;
32
 
32
 
33
    EXPR* = RECORD
33
    EXPR* = RECORD
34
 
34
 
35
        obj*:         INTEGER;
35
        obj*:         INTEGER;
36
        type*:        PROG.TYPE_;
36
        type*:        PROG.TYPE_;
37
        value*:       ARITH.VALUE;
37
        value*:       ARITH.VALUE;
38
        stproc*:      INTEGER;
38
        stproc*:      INTEGER;
39
        readOnly*:    BOOLEAN;
39
        readOnly*:    BOOLEAN;
40
        ident*:       PROG.IDENT
40
        ident*:       PROG.IDENT
41
 
41
 
42
    END;
42
    END;
43
 
43
 
44
    STATPROC  = PROCEDURE (parser: PARSER);
44
    STATPROC  = PROCEDURE (parser: PARSER);
45
    EXPRPROC  = PROCEDURE (parser: PARSER; VAR e: EXPR);
45
    EXPRPROC  = PROCEDURE (parser: PARSER; VAR e: EXPR);
46
    RETPROC   = PROCEDURE (parser: PARSER; e: EXPR; t: PROG.TYPE_; pos: POSITION): BOOLEAN;
46
    RETPROC   = PROCEDURE (parser: PARSER; e: EXPR; t: PROG.TYPE_; pos: POSITION): BOOLEAN;
47
 
47
 
48
    rPARSER = RECORD (C.ITEM)
48
    rPARSER = RECORD (C.ITEM)
49
 
49
 
50
        fname*:      PATH;
50
        fname*:      PATH;
51
        path:        PATH;
51
        path:        PATH;
52
        lib_path:    PATH;
52
        lib_path:    PATH;
53
        ext:         PATH;
53
        ext:         PATH;
54
        modname:     PATH;
54
        modname:     PATH;
55
        scanner:     SCAN.SCANNER;
55
        scanner:     SCAN.SCANNER;
56
        lex*:        SCAN.LEX;
56
        lex*:        SCAN.LEX;
57
        sym*:        INTEGER;
57
        sym*:        INTEGER;
58
        unit*:       PROG.UNIT;
58
        unit*:       PROG.UNIT;
59
        constexp*:   BOOLEAN;
59
        constexp*:   BOOLEAN;
60
        main*:       BOOLEAN;
60
        main*:       BOOLEAN;
61
 
61
 
62
        open*:       PROCEDURE (parser: PARSER; modname: ARRAY OF CHAR): BOOLEAN;
62
        open*:       PROCEDURE (parser: PARSER; modname: ARRAY OF CHAR): BOOLEAN;
63
        parse*:      PROCEDURE (parser: PARSER);
63
        parse*:      PROCEDURE (parser: PARSER);
64
        StatSeq*:    STATPROC;
64
        StatSeq*:    STATPROC;
65
        expression*: EXPRPROC;
65
        expression*: EXPRPROC;
66
        designator*: EXPRPROC;
66
        designator*: EXPRPROC;
67
        chkreturn:   RETPROC;
67
        chkreturn:   RETPROC;
68
 
68
 
69
        create*:     PROCEDURE (path, lib_path: PATH; StatSeq: STATPROC; expression, designator: EXPRPROC; chkreturn: RETPROC): PARSER
69
        create*:     PROCEDURE (path, lib_path: PATH; StatSeq: STATPROC; expression, designator: EXPRPROC; chkreturn: RETPROC): PARSER
70
 
70
 
71
    END;
71
    END;
72
 
72
 
73
 
73
 
74
VAR
74
VAR
75
 
75
 
76
    program*: PROG.PROGRAM;
76
    program*: PROG.PROGRAM;
77
 
77
 
78
    parsers: C.COLLECTION;
78
    parsers: C.COLLECTION;
-
 
79
 
-
 
80
    lines*: INTEGER;
79
 
81
 
80
 
82
 
81
PROCEDURE destroy* (VAR parser: PARSER);
83
PROCEDURE destroy* (VAR parser: PARSER);
82
BEGIN
84
BEGIN
83
    IF parser.scanner # NIL THEN
85
    IF parser.scanner # NIL THEN
84
        SCAN.close(parser.scanner)
86
        SCAN.close(parser.scanner)
85
    END;
87
    END;
86
 
88
 
87
    C.push(parsers, parser);
89
    C.push(parsers, parser);
88
    parser := NIL
90
    parser := NIL
89
END destroy;
91
END destroy;
90
 
92
 
91
 
93
 
92
PROCEDURE getpos (parser: PARSER; VAR pos: POSITION);
94
PROCEDURE getpos (parser: PARSER; VAR pos: POSITION);
93
BEGIN
95
BEGIN
94
    pos.line   := parser.lex.pos.line;
96
    pos.line   := parser.lex.pos.line;
95
    pos.col    := parser.lex.pos.col;
97
    pos.col    := parser.lex.pos.col;
96
    pos.parser := parser
98
    pos.parser := parser
97
END getpos;
99
END getpos;
98
 
100
 
99
 
101
 
100
PROCEDURE error* (pos: POSITION; errno: INTEGER);
102
PROCEDURE error* (pos: POSITION; errno: INTEGER);
101
BEGIN
103
BEGIN
102
    ERRORS.ErrorMsg(pos.parser.fname, pos.line, pos.col, errno)
104
    ERRORS.ErrorMsg(pos.parser.fname, pos.line, pos.col, errno)
103
END error;
105
END error;
104
 
106
 
105
 
107
 
106
PROCEDURE check* (condition: BOOLEAN; pos: POSITION; errno: INTEGER);
108
PROCEDURE check* (condition: BOOLEAN; pos: POSITION; errno: INTEGER);
107
BEGIN
109
BEGIN
108
    IF ~condition THEN
110
    IF ~condition THEN
109
        error(pos, errno)
111
        error(pos, errno)
110
    END
112
    END
111
END check;
113
END check;
112
 
114
 
113
 
115
 
114
PROCEDURE check1* (condition: BOOLEAN; parser: PARSER; errno: INTEGER);
116
PROCEDURE check1* (condition: BOOLEAN; parser: PARSER; errno: INTEGER);
115
VAR
117
VAR
116
    pos: POSITION;
118
    pos: POSITION;
117
 
119
 
118
BEGIN
120
BEGIN
119
    IF ~condition THEN
121
    IF ~condition THEN
120
        getpos(parser, pos);
122
        getpos(parser, pos);
121
        error(pos, errno)
123
        error(pos, errno)
122
    END
124
    END
123
END check1;
125
END check1;
124
 
126
 
125
 
127
 
126
PROCEDURE Next* (parser: PARSER);
128
PROCEDURE Next* (parser: PARSER);
127
VAR
129
VAR
128
    errno: INTEGER;
130
    errno: INTEGER;
129
 
131
 
130
BEGIN
132
BEGIN
131
    SCAN.Next(parser.scanner, parser.lex);
133
    SCAN.Next(parser.scanner, parser.lex);
132
    errno := parser.lex.error;
134
    errno := parser.lex.error;
133
    IF (errno = 0) & (program.target.sys = mConst.Target_iMSP430) THEN
135
    IF (errno = 0) & (program.target.sys = mConst.Target_iMSP430) THEN
134
        IF parser.lex.sym = SCAN.lxFLOAT THEN
136
        IF parser.lex.sym = SCAN.lxFLOAT THEN
135
            errno := -SCAN.lxERROR13
137
            errno := -SCAN.lxERROR13
136
        ELSIF (parser.lex.sym = SCAN.lxCHAR) & (parser.lex.value.typ = ARITH.tWCHAR) THEN
138
        ELSIF (parser.lex.sym = SCAN.lxCHAR) & (parser.lex.value.typ = ARITH.tWCHAR) THEN
137
            errno := -SCAN.lxERROR10
139
            errno := -SCAN.lxERROR10
138
        END
140
        END
139
    END;
141
    END;
140
 
142
 
141
    IF errno # 0 THEN
143
    IF errno # 0 THEN
142
        check1(FALSE, parser, errno)
144
        check1(FALSE, parser, errno)
143
    END;
145
    END;
144
    parser.sym := parser.lex.sym
146
    parser.sym := parser.lex.sym
145
END Next;
147
END Next;
146
 
148
 
147
 
149
 
148
PROCEDURE NextPos (parser: PARSER; VAR pos: POSITION);
150
PROCEDURE NextPos (parser: PARSER; VAR pos: POSITION);
149
BEGIN
151
BEGIN
150
    Next(parser);
152
    Next(parser);
151
    getpos(parser, pos)
153
    getpos(parser, pos)
152
END NextPos;
154
END NextPos;
153
 
155
 
154
 
156
 
155
PROCEDURE checklex* (parser: PARSER; sym: INTEGER);
157
PROCEDURE checklex* (parser: PARSER; sym: INTEGER);
156
VAR
158
VAR
157
    err: INTEGER;
159
    err: INTEGER;
158
 
160
 
159
BEGIN
161
BEGIN
160
 
162
 
161
    IF parser.sym # sym THEN
163
    IF parser.sym # sym THEN
162
 
164
 
163
        CASE sym OF
165
        CASE sym OF
164
        |SCAN.lxCOMMA:   err := 65
166
        |SCAN.lxCOMMA:   err := 65
165
        |SCAN.lxRROUND:  err := 33
167
        |SCAN.lxRROUND:  err := 33
166
        |SCAN.lxPOINT:   err := 26
168
        |SCAN.lxPOINT:   err := 26
167
        |SCAN.lxIDENT:   err := 22
169
        |SCAN.lxIDENT:   err := 22
168
        |SCAN.lxRSQUARE: err := 71
170
        |SCAN.lxRSQUARE: err := 71
169
        |SCAN.lxRCURLY:  err := 35
171
        |SCAN.lxRCURLY:  err := 35
170
        |SCAN.lxUNDEF:   err := 34
172
        |SCAN.lxUNDEF:   err := 34
171
        |SCAN.lxTHEN:    err := 88
173
        |SCAN.lxTHEN:    err := 88
172
        |SCAN.lxEND:     err := 27
174
        |SCAN.lxEND:     err := 27
173
        |SCAN.lxDO:      err := 89
175
        |SCAN.lxDO:      err := 89
174
        |SCAN.lxUNTIL:   err := 90
176
        |SCAN.lxUNTIL:   err := 90
175
        |SCAN.lxCOLON:   err := 53
177
        |SCAN.lxCOLON:   err := 53
176
        |SCAN.lxOF:      err := 67
178
        |SCAN.lxOF:      err := 67
177
        |SCAN.lxASSIGN:  err := 96
179
        |SCAN.lxASSIGN:  err := 96
178
        |SCAN.lxTO:      err := 57
180
        |SCAN.lxTO:      err := 57
179
        |SCAN.lxLROUND:  err := 64
181
        |SCAN.lxLROUND:  err := 64
180
        |SCAN.lxEQ:      err := 32
182
        |SCAN.lxEQ:      err := 32
181
        |SCAN.lxSEMI:    err := 24
183
        |SCAN.lxSEMI:    err := 24
182
        |SCAN.lxRETURN:  err := 38
184
        |SCAN.lxRETURN:  err := 38
183
        |SCAN.lxMODULE:  err := 21
185
        |SCAN.lxMODULE:  err := 21
184
        |SCAN.lxSTRING:  err := 66
186
        |SCAN.lxSTRING:  err := 66
185
        END;
187
        END;
186
 
188
 
187
        check1(FALSE, parser, err)
189
        check1(FALSE, parser, err)
188
    END
190
    END
189
END checklex;
191
END checklex;
190
 
192
 
191
 
193
 
192
PROCEDURE ExpectSym* (parser: PARSER; sym: INTEGER);
194
PROCEDURE ExpectSym* (parser: PARSER; sym: INTEGER);
193
BEGIN
195
BEGIN
194
    Next(parser);
196
    Next(parser);
195
    checklex(parser, sym)
197
    checklex(parser, sym)
196
END ExpectSym;
198
END ExpectSym;
197
 
199
 
198
 
200
 
199
PROCEDURE ImportList (parser: PARSER);
201
PROCEDURE ImportList (parser: PARSER);
200
VAR
202
VAR
201
    name:    SCAN.IDENT;
203
    name:    SCAN.IDENT;
202
    parser2: PARSER;
204
    parser2: PARSER;
203
    pos:     POSITION;
205
    pos:     POSITION;
204
    alias:   BOOLEAN;
206
    alias:   BOOLEAN;
205
    unit:    PROG.UNIT;
207
    unit:    PROG.UNIT;
206
    ident:   PROG.IDENT;
208
    ident:   PROG.IDENT;
207
 
209
 
208
BEGIN
210
BEGIN
209
    alias := FALSE;
211
    alias := FALSE;
210
 
212
 
211
    REPEAT
213
    REPEAT
212
 
214
 
213
        ExpectSym(parser, SCAN.lxIDENT);
215
        ExpectSym(parser, SCAN.lxIDENT);
214
        name := parser.lex.ident;
216
        name := parser.lex.ident;
215
 
217
 
216
        getpos(parser, pos);
218
        getpos(parser, pos);
217
 
219
 
218
        IF ~alias THEN
220
        IF ~alias THEN
219
            ident := PROG.addIdent(parser.unit, name, PROG.idMODULE);
221
            ident := PROG.addIdent(parser.unit, name, PROG.idMODULE);
220
            check(ident # NIL, pos, 30)
222
            check(ident # NIL, pos, 30)
221
        END;
223
        END;
222
 
224
 
223
        Next(parser);
225
        Next(parser);
224
 
226
 
225
        IF (parser.sym = SCAN.lxCOMMA) OR (parser.sym = SCAN.lxSEMI) THEN
227
        IF (parser.sym = SCAN.lxCOMMA) OR (parser.sym = SCAN.lxSEMI) THEN
226
            alias := FALSE;
228
            alias := FALSE;
227
            unit := PROG.getUnit(program, name);
229
            unit := PROG.getUnit(program, name);
228
 
230
 
229
            IF unit # NIL THEN
231
            IF unit # NIL THEN
230
                check(unit.closed, pos, 31)
232
                check(unit.closed, pos, 31)
231
            ELSE
233
            ELSE
232
                parser2 := parser.create(parser.path, parser.lib_path,
234
                parser2 := parser.create(parser.path, parser.lib_path,
233
                    parser.StatSeq, parser.expression, parser.designator, parser.chkreturn);
235
                    parser.StatSeq, parser.expression, parser.designator, parser.chkreturn);
234
 
236
 
235
                IF ~parser2.open(parser2, name.s) THEN
237
                IF ~parser2.open(parser2, name.s) THEN
236
                    IF parser.path # parser.lib_path THEN
238
                    IF parser.path # parser.lib_path THEN
237
                        destroy(parser2);
239
                        destroy(parser2);
238
                        parser2 := parser.create(parser.lib_path, parser.lib_path,
240
                        parser2 := parser.create(parser.lib_path, parser.lib_path,
239
                            parser.StatSeq, parser.expression, parser.designator, parser.chkreturn);
241
                            parser.StatSeq, parser.expression, parser.designator, parser.chkreturn);
240
                        check(parser2.open(parser2, name.s), pos, 29)
242
                        check(parser2.open(parser2, name.s), pos, 29)
241
                    ELSE
243
                    ELSE
242
                        error(pos, 29)
244
                        error(pos, 29)
243
                    END
245
                    END
244
                END;
246
                END;
245
 
247
 
246
                parser2.parse(parser2);
248
                parser2.parse(parser2);
247
                unit := parser2.unit;
249
                unit := parser2.unit;
248
                destroy(parser2)
250
                destroy(parser2)
249
            END;
251
            END;
250
            IF unit = program.sysunit THEN
252
            IF unit = program.sysunit THEN
251
                parser.unit.sysimport := TRUE
253
                parser.unit.sysimport := TRUE
252
            END;
254
            END;
253
            ident.unit := unit
255
            ident.unit := unit
254
 
256
 
255
        ELSIF parser.sym = SCAN.lxASSIGN THEN
257
        ELSIF parser.sym = SCAN.lxASSIGN THEN
256
            alias := TRUE
258
            alias := TRUE
257
 
259
 
258
        ELSE
260
        ELSE
259
            check1(FALSE, parser, 28)
261
            check1(FALSE, parser, 28)
260
        END
262
        END
261
 
263
 
262
    UNTIL parser.sym = SCAN.lxSEMI;
264
    UNTIL parser.sym = SCAN.lxSEMI;
263
 
265
 
264
    Next(parser)
266
    Next(parser)
265
 
267
 
266
END ImportList;
268
END ImportList;
267
 
269
 
268
 
270
 
269
PROCEDURE QIdent (parser: PARSER; forward: BOOLEAN): PROG.IDENT;
271
PROCEDURE QIdent (parser: PARSER; forward: BOOLEAN): PROG.IDENT;
270
VAR
272
VAR
271
    ident: PROG.IDENT;
273
    ident: PROG.IDENT;
272
    unit:  PROG.UNIT;
274
    unit:  PROG.UNIT;
273
 
275
 
274
BEGIN
276
BEGIN
275
    ASSERT(parser.sym = SCAN.lxIDENT);
277
    ASSERT(parser.sym = SCAN.lxIDENT);
276
 
278
 
277
    ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE);
279
    ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE);
278
 
280
 
279
    IF ~forward THEN
281
    IF ~forward THEN
280
        check1(ident # NIL, parser, 48)
282
        check1(ident # NIL, parser, 48)
281
    END;
283
    END;
282
 
284
 
283
    IF (ident # NIL) & (ident.typ = PROG.idMODULE) THEN
285
    IF (ident # NIL) & (ident.typ = PROG.idMODULE) THEN
284
        unit := ident.unit;
286
        unit := ident.unit;
285
        ExpectSym(parser, SCAN.lxPOINT);
287
        ExpectSym(parser, SCAN.lxPOINT);
286
        ExpectSym(parser, SCAN.lxIDENT);
288
        ExpectSym(parser, SCAN.lxIDENT);
287
        ident := PROG.getIdent(unit, parser.lex.ident, FALSE);
289
        ident := PROG.getIdent(unit, parser.lex.ident, FALSE);
288
        check1((ident # NIL) & ident.export, parser, 48)
290
        check1((ident # NIL) & ident.export, parser, 48)
289
    END
291
    END
290
 
292
 
291
    RETURN ident
293
    RETURN ident
292
END QIdent;
294
END QIdent;
293
 
295
 
294
 
296
 
295
PROCEDURE strcmp* (VAR v: ARITH.VALUE; v2: ARITH.VALUE; operator: INTEGER);
297
PROCEDURE strcmp* (VAR v: ARITH.VALUE; v2: ARITH.VALUE; operator: INTEGER);
296
VAR
298
VAR
297
    str: SCAN.LEXSTR;
299
    str: SCAN.LEXSTR;
298
    string1, string2: SCAN.IDENT;
300
    string1, string2: SCAN.IDENT;
299
    bool: BOOLEAN;
301
    bool: BOOLEAN;
300
 
302
 
301
BEGIN
303
BEGIN
302
 
304
 
303
    IF v.typ = ARITH.tCHAR THEN
305
    IF v.typ = ARITH.tCHAR THEN
304
        ASSERT(v2.typ = ARITH.tSTRING);
306
        ASSERT(v2.typ = ARITH.tSTRING);
305
        ARITH.charToStr(v, str);
307
        ARITH.charToStr(v, str);
306
        string1 := SCAN.enterid(str);
308
        string1 := SCAN.enterid(str);
307
        string2 := v2.string(SCAN.IDENT)
309
        string2 := v2.string(SCAN.IDENT)
308
    END;
310
    END;
309
 
311
 
310
    IF v2.typ = ARITH.tCHAR THEN
312
    IF v2.typ = ARITH.tCHAR THEN
311
        ASSERT(v.typ = ARITH.tSTRING);
313
        ASSERT(v.typ = ARITH.tSTRING);
312
        ARITH.charToStr(v2, str);
314
        ARITH.charToStr(v2, str);
313
        string2 := SCAN.enterid(str);
315
        string2 := SCAN.enterid(str);
314
        string1 := v.string(SCAN.IDENT)
316
        string1 := v.string(SCAN.IDENT)
315
    END;
317
    END;
316
 
318
 
317
    IF v.typ = v2.typ THEN
319
    IF v.typ = v2.typ THEN
318
        string1 := v.string(SCAN.IDENT);
320
        string1 := v.string(SCAN.IDENT);
319
        string2 := v2.string(SCAN.IDENT)
321
        string2 := v2.string(SCAN.IDENT)
320
    END;
322
    END;
321
 
323
 
322
    CASE operator OF
324
    CASE operator OF
323
    |SCAN.lxEQ: bool := string1.s =  string2.s
325
    |SCAN.lxEQ: bool := string1.s =  string2.s
324
    |SCAN.lxNE: bool := string1.s #  string2.s
326
    |SCAN.lxNE: bool := string1.s #  string2.s
325
    |SCAN.lxLT: bool := string1.s <  string2.s
327
    |SCAN.lxLT: bool := string1.s <  string2.s
326
    |SCAN.lxGT: bool := string1.s >  string2.s
328
    |SCAN.lxGT: bool := string1.s >  string2.s
327
    |SCAN.lxLE: bool := string1.s <= string2.s
329
    |SCAN.lxLE: bool := string1.s <= string2.s
328
    |SCAN.lxGE: bool := string1.s >= string2.s
330
    |SCAN.lxGE: bool := string1.s >= string2.s
329
    END;
331
    END;
330
 
332
 
331
    ARITH.setbool(v, bool)
333
    ARITH.setbool(v, bool)
332
END strcmp;
334
END strcmp;
333
 
335
 
334
 
336
 
335
PROCEDURE ConstExpression* (parser: PARSER; VAR v: ARITH.VALUE);
337
PROCEDURE ConstExpression* (parser: PARSER; VAR v: ARITH.VALUE);
336
VAR
338
VAR
337
    e: EXPR;
339
    e: EXPR;
338
    pos: POSITION;
340
    pos: POSITION;
339
 
341
 
340
BEGIN
342
BEGIN
341
    getpos(parser, pos);
343
    getpos(parser, pos);
342
    parser.constexp := TRUE;
344
    parser.constexp := TRUE;
343
    parser.expression(parser, e);
345
    parser.expression(parser, e);
344
    parser.constexp := FALSE;
346
    parser.constexp := FALSE;
345
    check(e.obj = eCONST, pos, 62);
347
    check(e.obj = eCONST, pos, 62);
346
    v := e.value
348
    v := e.value
347
END ConstExpression;
349
END ConstExpression;
348
 
350
 
349
 
351
 
350
PROCEDURE FieldList (parser: PARSER; rec: PROG.TYPE_);
352
PROCEDURE FieldList (parser: PARSER; rec: PROG.TYPE_);
351
VAR
353
VAR
352
    name:   SCAN.IDENT;
354
    name:   SCAN.IDENT;
353
    export: BOOLEAN;
355
    export: BOOLEAN;
354
    pos:    POSITION;
356
    pos:    POSITION;
355
 
357
 
356
BEGIN
358
BEGIN
357
    ASSERT(parser.sym = SCAN.lxIDENT);
359
    ASSERT(parser.sym = SCAN.lxIDENT);
358
 
360
 
359
    WHILE parser.sym = SCAN.lxIDENT DO
361
    WHILE parser.sym = SCAN.lxIDENT DO
360
 
362
 
361
        getpos(parser, pos);
363
        getpos(parser, pos);
362
 
364
 
363
        name := parser.lex.ident;
365
        name := parser.lex.ident;
364
 
366
 
365
        Next(parser);
367
        Next(parser);
366
 
368
 
367
        export := parser.sym = SCAN.lxMUL;
369
        export := parser.sym = SCAN.lxMUL;
368
 
370
 
369
        IF export THEN
371
        IF export THEN
370
            check1(parser.unit.scopeLvl = 0, parser, 61);
372
            check1(parser.unit.scopeLvl = 0, parser, 61);
371
            Next(parser)
373
            Next(parser)
372
        END;
374
        END;
373
 
375
 
374
        check(PROG.addField(rec, name, export), pos, 30);
376
        check(PROG.addField(rec, name, export), pos, 30);
375
 
377
 
376
        IF parser.sym = SCAN.lxCOMMA THEN
378
        IF parser.sym = SCAN.lxCOMMA THEN
377
            ExpectSym(parser, SCAN.lxIDENT)
379
            ExpectSym(parser, SCAN.lxIDENT)
378
        ELSE
380
        ELSE
379
            checklex(parser, SCAN.lxCOLON)
381
            checklex(parser, SCAN.lxCOLON)
380
        END
382
        END
381
 
383
 
382
    END
384
    END
383
 
385
 
384
END FieldList;
386
END FieldList;
385
 
387
 
386
 
388
 
387
PROCEDURE FormalParameters (parser: PARSER; type: PROG.TYPE_);
389
PROCEDURE FormalParameters (parser: PARSER; type: PROG.TYPE_);
388
VAR
390
VAR
389
    ident: PROG.IDENT;
391
    ident: PROG.IDENT;
390
 
392
 
391
 
393
 
392
    PROCEDURE FPSection (parser: PARSER; type: PROG.TYPE_);
394
    PROCEDURE FPSection (parser: PARSER; type: PROG.TYPE_);
393
    VAR
395
    VAR
394
        ident:   PROG.IDENT;
396
        ident:   PROG.IDENT;
395
        exit:    BOOLEAN;
397
        exit:    BOOLEAN;
396
        vPar:    BOOLEAN;
398
        vPar:    BOOLEAN;
397
        dim:     INTEGER;
399
        dim:     INTEGER;
398
        t0, t1:  PROG.TYPE_;
400
        t0, t1:  PROG.TYPE_;
399
 
401
 
400
    BEGIN
402
    BEGIN
401
        vPar := parser.sym = SCAN.lxVAR;
403
        vPar := parser.sym = SCAN.lxVAR;
402
        IF vPar THEN
404
        IF vPar THEN
403
            Next(parser)
405
            Next(parser)
404
        END;
406
        END;
405
 
407
 
406
        checklex(parser, SCAN.lxIDENT);
408
        checklex(parser, SCAN.lxIDENT);
407
        exit := FALSE;
409
        exit := FALSE;
408
 
410
 
409
        WHILE (parser.sym = SCAN.lxIDENT) & ~exit DO
411
        WHILE (parser.sym = SCAN.lxIDENT) & ~exit DO
410
            check1(PROG.addParam(type, parser.lex.ident, vPar), parser, 30);
412
            check1(PROG.addParam(type, parser.lex.ident, vPar), parser, 30);
411
            Next(parser);
413
            Next(parser);
412
            IF parser.sym = SCAN.lxCOMMA THEN
414
            IF parser.sym = SCAN.lxCOMMA THEN
413
                ExpectSym(parser, SCAN.lxIDENT)
415
                ExpectSym(parser, SCAN.lxIDENT)
414
            ELSIF parser.sym = SCAN.lxCOLON THEN
416
            ELSIF parser.sym = SCAN.lxCOLON THEN
415
                Next(parser);
417
                Next(parser);
416
                dim := 0;
418
                dim := 0;
417
                WHILE parser.sym = SCAN.lxARRAY DO
419
                WHILE parser.sym = SCAN.lxARRAY DO
418
                    INC(dim);
420
                    INC(dim);
419
                    check1(dim <= PROG.MAXARRDIM, parser, 84);
421
                    check1(dim <= PROG.MAXARRDIM, parser, 84);
420
                    ExpectSym(parser, SCAN.lxOF);
422
                    ExpectSym(parser, SCAN.lxOF);
421
                    Next(parser)
423
                    Next(parser)
422
                END;
424
                END;
423
                checklex(parser, SCAN.lxIDENT);
425
                checklex(parser, SCAN.lxIDENT);
424
                ident := QIdent(parser, FALSE);
426
                ident := QIdent(parser, FALSE);
425
                check1(ident.typ = PROG.idTYPE, parser, 68);
427
                check1(ident.typ = PROG.idTYPE, parser, 68);
426
 
428
 
427
                t0 := ident.type;
429
                t0 := ident.type;
428
                t1 := t0;
430
                t1 := t0;
429
 
431
 
430
                WHILE dim > 0 DO
432
                WHILE dim > 0 DO
431
                    t1 := PROG.enterType(program, PROG.tARRAY, -1, 0, parser.unit);
433
                    t1 := PROG.enterType(program, PROG.tARRAY, -1, 0, parser.unit);
432
                    t1.base := t0;
434
                    t1.base := t0;
433
                    t0 := t1;
435
                    t0 := t1;
434
                    DEC(dim)
436
                    DEC(dim)
435
                END;
437
                END;
436
 
438
 
437
                PROG.setParams(type, t1);
439
                PROG.setParams(type, t1);
438
                Next(parser);
440
                Next(parser);
439
                exit := TRUE
441
                exit := TRUE
440
            ELSE
442
            ELSE
441
                checklex(parser, SCAN.lxCOLON)
443
                checklex(parser, SCAN.lxCOLON)
442
            END
444
            END
443
        END
445
        END
444
 
446
 
445
    END FPSection;
447
    END FPSection;
446
 
448
 
447
 
449
 
448
BEGIN
450
BEGIN
449
    IF parser.sym = SCAN.lxLROUND THEN
451
    IF parser.sym = SCAN.lxLROUND THEN
450
 
452
 
451
        Next(parser);
453
        Next(parser);
452
 
454
 
453
        IF (parser.sym = SCAN.lxVAR) OR (parser.sym = SCAN.lxIDENT) THEN
455
        IF (parser.sym = SCAN.lxVAR) OR (parser.sym = SCAN.lxIDENT) THEN
454
            FPSection(parser, type);
456
            FPSection(parser, type);
455
            WHILE parser.sym = SCAN.lxSEMI DO
457
            WHILE parser.sym = SCAN.lxSEMI DO
456
                Next(parser);
458
                Next(parser);
457
                FPSection(parser, type)
459
                FPSection(parser, type)
458
            END
460
            END
459
        END;
461
        END;
460
 
462
 
461
        checklex(parser, SCAN.lxRROUND);
463
        checklex(parser, SCAN.lxRROUND);
462
        Next(parser);
464
        Next(parser);
463
 
465
 
464
        IF parser.sym = SCAN.lxCOLON THEN
466
        IF parser.sym = SCAN.lxCOLON THEN
465
            ExpectSym(parser, SCAN.lxIDENT);
467
            ExpectSym(parser, SCAN.lxIDENT);
466
            ident := QIdent(parser, FALSE);
468
            ident := QIdent(parser, FALSE);
467
            check1(ident.typ = PROG.idTYPE, parser, 68);
469
            check1(ident.typ = PROG.idTYPE, parser, 68);
468
            check1(~(ident.type.typ IN {PROG.tRECORD, PROG.tARRAY}), parser, 69);
470
            check1(~(ident.type.typ IN {PROG.tRECORD, PROG.tARRAY}), parser, 69);
469
            check1( ~(ODD(type.call) & (ident.type.typ = PROG.tREAL)), parser, 113);
471
            check1( ~(ODD(type.call) & (ident.type.typ = PROG.tREAL)), parser, 113);
470
            type.base := ident.type;
472
            type.base := ident.type;
471
            Next(parser)
473
            Next(parser)
472
        ELSE
474
        ELSE
473
            type.base := NIL
475
            type.base := NIL
474
        END
476
        END
475
 
477
 
476
    END
478
    END
477
END FormalParameters;
479
END FormalParameters;
478
 
480
 
479
 
481
 
480
PROCEDURE sysflag (parser: PARSER; proc: BOOLEAN): INTEGER;
482
PROCEDURE sysflag (parser: PARSER; proc: BOOLEAN): INTEGER;
481
VAR
483
VAR
482
    res, sf: INTEGER;
484
    res, sf: INTEGER;
483
 
485
 
484
BEGIN
486
BEGIN
485
    IF parser.lex.s = "stdcall" THEN
487
    IF parser.lex.s = "stdcall" THEN
486
        sf := PROG.sf_stdcall
488
        sf := PROG.sf_stdcall
487
    ELSIF parser.lex.s = "stdcall64" THEN
489
    ELSIF parser.lex.s = "stdcall64" THEN
488
        sf := PROG.sf_stdcall64
490
        sf := PROG.sf_stdcall64
489
    ELSIF parser.lex.s = "ccall" THEN
491
    ELSIF parser.lex.s = "ccall" THEN
490
        sf := PROG.sf_ccall
492
        sf := PROG.sf_ccall
491
    ELSIF parser.lex.s = "ccall16" THEN
493
    ELSIF parser.lex.s = "ccall16" THEN
492
        sf := PROG.sf_ccall16
494
        sf := PROG.sf_ccall16
493
    ELSIF parser.lex.s = "win64" THEN
495
    ELSIF parser.lex.s = "win64" THEN
494
        sf := PROG.sf_win64
496
        sf := PROG.sf_win64
495
    ELSIF parser.lex.s = "systemv" THEN
497
    ELSIF parser.lex.s = "systemv" THEN
496
        sf := PROG.sf_systemv
498
        sf := PROG.sf_systemv
497
    ELSIF parser.lex.s = "windows" THEN
499
    ELSIF parser.lex.s = "windows" THEN
498
        sf := PROG.sf_windows
500
        sf := PROG.sf_windows
499
    ELSIF parser.lex.s = "linux" THEN
501
    ELSIF parser.lex.s = "linux" THEN
500
        sf := PROG.sf_linux
502
        sf := PROG.sf_linux
501
    ELSIF parser.lex.s = "code" THEN
503
    ELSIF parser.lex.s = "code" THEN
502
        sf := PROG.sf_code
504
        sf := PROG.sf_code
503
    ELSIF parser.lex.s = "noalign" THEN
505
    ELSIF parser.lex.s = "noalign" THEN
504
        sf := PROG.sf_noalign
506
        sf := PROG.sf_noalign
505
    ELSE
507
    ELSE
506
        check1(FALSE, parser, 124)
508
        check1(FALSE, parser, 124)
507
    END;
509
    END;
508
 
510
 
509
    check1(sf IN program.target.sysflags, parser, 125);
511
    check1(sf IN program.target.sysflags, parser, 125);
510
 
512
 
511
    IF proc THEN
513
    IF proc THEN
512
        check1(sf IN PROG.proc_flags, parser, 123)
514
        check1(sf IN PROG.proc_flags, parser, 123)
513
    ELSE
515
    ELSE
514
        check1(sf IN PROG.rec_flags, parser, 123)
516
        check1(sf IN PROG.rec_flags, parser, 123)
515
    END;
517
    END;
516
 
518
 
517
    CASE sf OF
519
    CASE sf OF
518
    |PROG.sf_stdcall:
520
    |PROG.sf_stdcall:
519
        res := PROG.stdcall
521
        res := PROG.stdcall
520
    |PROG.sf_stdcall64:
522
    |PROG.sf_stdcall64:
521
        res := PROG.stdcall64
523
        res := PROG.stdcall64
522
    |PROG.sf_ccall:
524
    |PROG.sf_ccall:
523
        res := PROG.ccall
525
        res := PROG.ccall
524
    |PROG.sf_ccall16:
526
    |PROG.sf_ccall16:
525
        res := PROG.ccall16
527
        res := PROG.ccall16
526
    |PROG.sf_win64:
528
    |PROG.sf_win64:
527
        res := PROG.win64
529
        res := PROG.win64
528
    |PROG.sf_systemv:
530
    |PROG.sf_systemv:
529
        res := PROG.systemv
531
        res := PROG.systemv
530
    |PROG.sf_code:
532
    |PROG.sf_code:
531
        res := PROG.code
533
        res := PROG.code
532
    |PROG.sf_windows:
534
    |PROG.sf_windows:
533
        IF program.target.sys IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN
535
        IF program.target.sys IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN
534
            res := PROG.stdcall
536
            res := PROG.stdcall
535
        ELSIF program.target.sys IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64} THEN
537
        ELSIF program.target.sys IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64} THEN
536
            res := PROG.win64
538
            res := PROG.win64
537
        END
539
        END
538
    |PROG.sf_linux:
540
    |PROG.sf_linux:
539
        IF program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN
541
        IF program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN
540
            res := PROG.ccall16
542
            res := PROG.ccall16
541
        ELSIF program.target.sys IN {mConst.Target_iELF64, mConst.Target_iELFSO64} THEN
543
        ELSIF program.target.sys IN {mConst.Target_iELF64, mConst.Target_iELFSO64} THEN
542
            res := PROG.systemv
544
            res := PROG.systemv
543
        END
545
        END
544
    |PROG.sf_noalign:
546
    |PROG.sf_noalign:
545
        res := PROG.noalign
547
        res := PROG.noalign
546
    END
548
    END
547
 
549
 
548
    RETURN res
550
    RETURN res
549
END sysflag;
551
END sysflag;
550
 
552
 
551
 
553
 
552
PROCEDURE procflag (parser: PARSER; VAR import: IL.IMPORT_PROC; isProc: BOOLEAN): INTEGER;
554
PROCEDURE procflag (parser: PARSER; VAR import: IL.IMPORT_PROC; isProc: BOOLEAN): INTEGER;
553
VAR
555
VAR
554
    call: INTEGER;
556
    call: INTEGER;
555
    dll, proc: SCAN.LEXSTR;
557
    dll, proc: SCAN.LEXSTR;
556
    pos: POSITION;
558
    pos: POSITION;
557
 
559
 
558
BEGIN
560
BEGIN
559
 
561
 
560
    import := NIL;
562
    import := NIL;
561
 
563
 
562
    IF parser.sym = SCAN.lxLSQUARE THEN
564
    IF parser.sym = SCAN.lxLSQUARE THEN
563
        getpos(parser, pos);
565
        getpos(parser, pos);
564
        check1(parser.unit.sysimport, parser, 54);
566
        check1(parser.unit.sysimport, parser, 54);
565
        Next(parser);
567
        Next(parser);
566
        call := sysflag(parser, TRUE);
568
        call := sysflag(parser, TRUE);
567
        Next(parser);
569
        Next(parser);
568
        IF parser.sym = SCAN.lxMINUS THEN
570
        IF parser.sym = SCAN.lxMINUS THEN
569
            Next(parser);
571
            Next(parser);
570
            INC(call)
572
            INC(call)
571
        END;
573
        END;
572
        IF ~isProc THEN
574
        IF ~isProc THEN
573
            checklex(parser, SCAN.lxRSQUARE)
575
            checklex(parser, SCAN.lxRSQUARE)
574
        END;
576
        END;
575
        IF parser.sym = SCAN.lxCOMMA THEN
577
        IF parser.sym = SCAN.lxCOMMA THEN
576
            ExpectSym(parser, SCAN.lxSTRING);
578
            ExpectSym(parser, SCAN.lxSTRING);
577
            dll := parser.lex.s;
579
            dll := parser.lex.s;
578
            ExpectSym(parser, SCAN.lxCOMMA);
580
            ExpectSym(parser, SCAN.lxCOMMA);
579
            ExpectSym(parser, SCAN.lxSTRING);
581
            ExpectSym(parser, SCAN.lxSTRING);
580
            proc := parser.lex.s;
582
            proc := parser.lex.s;
581
            Next(parser);
583
            Next(parser);
582
            import := IL.AddImp(dll, proc)
584
            import := IL.AddImp(dll, proc)
583
        END;
585
        END;
584
        checklex(parser, SCAN.lxRSQUARE);
586
        checklex(parser, SCAN.lxRSQUARE);
585
        Next(parser)
587
        Next(parser)
586
    ELSE
588
    ELSE
587
        CASE program.target.bit_depth OF
589
        CASE program.target.bit_depth OF
588
        |16: call := PROG.default16
590
        |16: call := PROG.default16
589
        |32: call := PROG.default32
591
        |32: call := PROG.default32
590
        |64: call := PROG.default64
592
        |64: call := PROG.default64
591
        END
593
        END
592
    END;
594
    END;
593
 
595
 
594
    IF import # NIL THEN
596
    IF import # NIL THEN
595
        check(~(program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELF64, mConst.Target_iELFSO32,
597
        check(~(program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELF64, mConst.Target_iELFSO32,
596
            mConst.Target_iELFSO64, mConst.Target_iMSP430}), pos, 70)
598
            mConst.Target_iELFSO64, mConst.Target_iMSP430}), pos, 70)
597
    END
599
    END
598
 
600
 
599
    RETURN call
601
    RETURN call
600
END procflag;
602
END procflag;
601
 
603
 
602
 
604
 
603
PROCEDURE type (parser: PARSER; VAR t: PROG.TYPE_; flags: SET);
605
PROCEDURE type (parser: PARSER; VAR t: PROG.TYPE_; flags: SET);
604
CONST
606
CONST
605
    comma   = 0;
607
    comma   = 0;
606
    closed  = 1;
608
    closed  = 1;
607
    forward = 2;
609
    forward = 2;
608
 
610
 
609
VAR
611
VAR
610
    arrLen:     ARITH.VALUE;
612
    arrLen:     ARITH.VALUE;
611
    typeSize:   ARITH.VALUE;
613
    typeSize:   ARITH.VALUE;
612
    ident:      PROG.IDENT;
614
    ident:      PROG.IDENT;
613
    unit:       PROG.UNIT;
615
    unit:       PROG.UNIT;
614
    pos, pos2:  POSITION;
616
    pos, pos2:  POSITION;
615
    fieldType:  PROG.TYPE_;
617
    fieldType:  PROG.TYPE_;
616
    baseIdent:  SCAN.IDENT;
618
    baseIdent:  SCAN.IDENT;
617
    a, b:       INTEGER;
619
    a, b:       INTEGER;
618
    RecFlag:    INTEGER;
620
    RecFlag:    INTEGER;
619
    import:     IL.IMPORT_PROC;
621
    import:     IL.IMPORT_PROC;
620
 
622
 
621
BEGIN
623
BEGIN
622
    unit := parser.unit;
624
    unit := parser.unit;
623
    t := NIL;
625
    t := NIL;
624
 
626
 
625
    IF parser.sym = SCAN.lxIDENT THEN
627
    IF parser.sym = SCAN.lxIDENT THEN
626
        ident := QIdent(parser, forward IN flags);
628
        ident := QIdent(parser, forward IN flags);
627
 
629
 
628
        IF ident # NIL THEN
630
        IF ident # NIL THEN
629
            check1(ident.typ = PROG.idTYPE, parser, 49);
631
            check1(ident.typ = PROG.idTYPE, parser, 49);
630
            t := ident.type;
632
            t := ident.type;
631
            check1(t # NIL, parser, 50);
633
            check1(t # NIL, parser, 50);
632
            IF closed IN flags THEN
634
            IF closed IN flags THEN
633
                check1(t.closed, parser, 50)
635
                check1(t.closed, parser, 50)
634
            END
636
            END
635
        END;
637
        END;
636
 
638
 
637
        Next(parser)
639
        Next(parser)
638
 
640
 
639
    ELSIF (parser.sym = SCAN.lxARRAY) OR ((parser.sym = SCAN.lxCOMMA) & (comma IN flags)) THEN
641
    ELSIF (parser.sym = SCAN.lxARRAY) OR ((parser.sym = SCAN.lxCOMMA) & (comma IN flags)) THEN
640
 
642
 
641
        IF parser.sym = SCAN.lxARRAY THEN
643
        IF parser.sym = SCAN.lxARRAY THEN
642
            getpos(parser, pos2)
644
            getpos(parser, pos2)
643
        END;
645
        END;
644
        NextPos(parser, pos);
646
        NextPos(parser, pos);
645
 
647
 
646
        ConstExpression(parser, arrLen);
648
        ConstExpression(parser, arrLen);
647
 
649
 
648
        check(arrLen.typ = ARITH.tINTEGER, pos, 43);
650
        check(arrLen.typ = ARITH.tINTEGER, pos, 43);
649
        check(ARITH.check(arrLen),         pos, 39);
651
        check(ARITH.check(arrLen),         pos, 39);
650
        check(ARITH.getInt(arrLen) > 0,    pos, 51);
652
        check(ARITH.getInt(arrLen) > 0,    pos, 51);
651
 
653
 
652
        t := PROG.enterType(program, PROG.tARRAY, -1, ARITH.getInt(arrLen), unit);
654
        t := PROG.enterType(program, PROG.tARRAY, -1, ARITH.getInt(arrLen), unit);
653
 
655
 
654
        IF parser.sym = SCAN.lxCOMMA THEN
656
        IF parser.sym = SCAN.lxCOMMA THEN
655
            type(parser, t.base, {comma, closed})
657
            type(parser, t.base, {comma, closed})
656
        ELSIF parser.sym = SCAN.lxOF THEN
658
        ELSIF parser.sym = SCAN.lxOF THEN
657
            Next(parser);
659
            Next(parser);
658
            type(parser, t.base, {closed})
660
            type(parser, t.base, {closed})
659
        ELSE
661
        ELSE
660
            check1(FALSE, parser, 47)
662
            check1(FALSE, parser, 47)
661
        END;
663
        END;
662
 
664
 
663
        t.align := t.base.align;
665
        t.align := t.base.align;
664
 
666
 
665
        a := t.length;
667
        a := t.length;
666
        b := t.base.size;
668
        b := t.base.size;
667
        check(ARITH.mulInt(a, b), pos2, 104);
669
        check(ARITH.mulInt(a, b), pos2, 104);
668
        check(ARITH.setInt(typeSize, a), pos2, 104);
670
        check(ARITH.setInt(typeSize, a), pos2, 104);
669
        t.size := a;
671
        t.size := a;
670
 
672
 
671
        t.closed := TRUE
673
        t.closed := TRUE
672
 
674
 
673
    ELSIF parser.sym = SCAN.lxRECORD THEN
675
    ELSIF parser.sym = SCAN.lxRECORD THEN
674
        getpos(parser, pos2);
676
        getpos(parser, pos2);
675
        Next(parser);
677
        Next(parser);
676
 
678
 
677
        t := PROG.enterType(program, PROG.tRECORD, 0, 0, unit);
679
        t := PROG.enterType(program, PROG.tRECORD, 0, 0, unit);
678
        t.align := 1;
680
        t.align := 1;
679
 
681
 
680
        IF parser.sym = SCAN.lxLSQUARE THEN
682
        IF parser.sym = SCAN.lxLSQUARE THEN
681
            check1(parser.unit.sysimport, parser, 54);
683
            check1(parser.unit.sysimport, parser, 54);
682
            Next(parser);
684
            Next(parser);
683
            RecFlag := sysflag(parser, FALSE);
685
            RecFlag := sysflag(parser, FALSE);
684
            t.noalign := RecFlag = PROG.noalign;
686
            t.noalign := RecFlag = PROG.noalign;
685
            ExpectSym(parser, SCAN.lxRSQUARE);
687
            ExpectSym(parser, SCAN.lxRSQUARE);
686
            Next(parser)
688
            Next(parser)
687
        END;
689
        END;
688
 
690
 
689
        IF parser.sym = SCAN.lxLROUND THEN
691
        IF parser.sym = SCAN.lxLROUND THEN
690
            check1(~t.noalign, parser, 111);
692
            check1(~t.noalign, parser, 111);
691
            ExpectSym(parser, SCAN.lxIDENT);
693
            ExpectSym(parser, SCAN.lxIDENT);
692
            getpos(parser, pos);
694
            getpos(parser, pos);
693
 
695
 
694
            type(parser, t.base, {closed});
696
            type(parser, t.base, {closed});
695
 
697
 
696
            check(t.base.typ IN {PROG.tRECORD, PROG.tPOINTER}, pos, 52);
698
            check(t.base.typ IN {PROG.tRECORD, PROG.tPOINTER}, pos, 52);
697
 
699
 
698
            IF t.base.typ = PROG.tPOINTER THEN
700
            IF t.base.typ = PROG.tPOINTER THEN
699
                t.base := t.base.base;
701
                t.base := t.base.base;
700
                check(t.base # NIL, pos, 55)
702
                check(t.base # NIL, pos, 55)
701
            END;
703
            END;
702
 
704
 
703
            check(~t.base.noalign, pos, 112);
705
            check(~t.base.noalign, pos, 112);
704
 
706
 
705
            checklex(parser, SCAN.lxRROUND);
707
            checklex(parser, SCAN.lxRROUND);
706
            Next(parser);
708
            Next(parser);
707
 
709
 
708
            t.size := t.base.size;
710
            t.size := t.base.size;
709
            IF t.base.align > t.align THEN
711
            IF t.base.align > t.align THEN
710
                t.align := t.base.align
712
                t.align := t.base.align
711
            END
713
            END
712
        ELSE
714
        ELSE
713
            t.base := program.stTypes.tANYREC
715
            t.base := program.stTypes.tANYREC
714
        END;
716
        END;
715
 
717
 
716
        WHILE parser.sym = SCAN.lxIDENT DO
718
        WHILE parser.sym = SCAN.lxIDENT DO
717
            FieldList(parser, t);
719
            FieldList(parser, t);
718
 
720
 
719
            ASSERT(parser.sym = SCAN.lxCOLON);
721
            ASSERT(parser.sym = SCAN.lxCOLON);
720
            Next(parser);
722
            Next(parser);
721
 
723
 
722
            type(parser, fieldType, {closed});
724
            type(parser, fieldType, {closed});
723
            check(PROG.setFields(t, fieldType), pos2, 104);
725
            check(PROG.setFields(t, fieldType), pos2, 104);
724
 
726
 
725
            IF (fieldType.align > t.align) & ~t.noalign THEN
727
            IF (fieldType.align > t.align) & ~t.noalign THEN
726
                t.align := fieldType.align
728
                t.align := fieldType.align
727
            END;
729
            END;
728
 
730
 
729
            IF parser.sym = SCAN.lxSEMI THEN
731
            IF parser.sym = SCAN.lxSEMI THEN
730
                ExpectSym(parser, SCAN.lxIDENT)
732
                ExpectSym(parser, SCAN.lxIDENT)
731
            ELSE
733
            ELSE
732
                checklex(parser, SCAN.lxEND)
734
                checklex(parser, SCAN.lxEND)
733
            END
735
            END
734
        END;
736
        END;
735
 
737
 
736
        t.closed := TRUE;
738
        t.closed := TRUE;
737
 
739
 
738
        IL.AddRec(t.base.num);
740
        IL.AddRec(t.base.num);
739
 
741
 
740
        IF ~t.noalign THEN
742
        IF ~t.noalign THEN
741
            check(UTILS.Align(t.size, t.align), pos2, 104);
743
            check(UTILS.Align(t.size, t.align), pos2, 104);
742
            check(ARITH.setInt(typeSize, t.size), pos2, 104)
744
            check(ARITH.setInt(typeSize, t.size), pos2, 104)
743
        END;
745
        END;
744
 
746
 
745
        checklex(parser, SCAN.lxEND);
747
        checklex(parser, SCAN.lxEND);
746
        Next(parser)
748
        Next(parser)
747
 
749
 
748
    ELSIF parser.sym = SCAN.lxPOINTER THEN
750
    ELSIF parser.sym = SCAN.lxPOINTER THEN
749
        ExpectSym(parser, SCAN.lxTO);
751
        ExpectSym(parser, SCAN.lxTO);
750
        Next(parser);
752
        Next(parser);
751
 
753
 
752
        t := PROG.enterType(program, PROG.tPOINTER, program.target.adr, 0, unit);
754
        t := PROG.enterType(program, PROG.tPOINTER, program.target.adr, 0, unit);
753
        t.align := program.target.adr;
755
        t.align := program.target.adr;
754
 
756
 
755
        getpos(parser, pos);
757
        getpos(parser, pos);
756
 
758
 
757
        IF parser.sym = SCAN.lxIDENT THEN
759
        IF parser.sym = SCAN.lxIDENT THEN
758
            baseIdent := parser.lex.ident
760
            baseIdent := parser.lex.ident
759
        END;
761
        END;
760
 
762
 
761
        type(parser, t.base, {forward});
763
        type(parser, t.base, {forward});
762
 
764
 
763
        IF t.base # NIL THEN
765
        IF t.base # NIL THEN
764
            check(t.base.typ = PROG.tRECORD, pos, 58)
766
            check(t.base.typ = PROG.tRECORD, pos, 58)
765
        ELSE
767
        ELSE
766
            PROG.frwPtr(unit, t, baseIdent, pos)
768
            PROG.frwPtr(unit, t, baseIdent, pos)
767
        END
769
        END
768
 
770
 
769
    ELSIF parser.sym = SCAN.lxPROCEDURE THEN
771
    ELSIF parser.sym = SCAN.lxPROCEDURE THEN
770
        NextPos(parser, pos);
772
        NextPos(parser, pos);
771
        t := PROG.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit);
773
        t := PROG.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit);
772
        t.align := program.target.adr;
774
        t.align := program.target.adr;
773
        t.call := procflag(parser, import, FALSE);
775
        t.call := procflag(parser, import, FALSE);
774
        FormalParameters(parser, t)
776
        FormalParameters(parser, t)
775
    ELSE
777
    ELSE
776
        check1(FALSE, parser, 49)
778
        check1(FALSE, parser, 49)
777
    END
779
    END
778
 
780
 
779
END type;
781
END type;
780
 
782
 
781
 
783
 
782
PROCEDURE IdentDef (parser: PARSER; typ: INTEGER; VAR name: SCAN.IDENT): PROG.IDENT;
784
PROCEDURE IdentDef (parser: PARSER; typ: INTEGER; VAR name: SCAN.IDENT): PROG.IDENT;
783
VAR
785
VAR
784
    ident:  PROG.IDENT;
786
    ident:  PROG.IDENT;
785
    pos:    POSITION;
787
    pos:    POSITION;
786
 
788
 
787
BEGIN
789
BEGIN
788
    ASSERT(parser.sym = SCAN.lxIDENT);
790
    ASSERT(parser.sym = SCAN.lxIDENT);
789
 
791
 
790
    name := parser.lex.ident;
792
    name := parser.lex.ident;
791
    getpos(parser, pos);
793
    getpos(parser, pos);
792
    ident := PROG.addIdent(parser.unit, name, typ);
794
    ident := PROG.addIdent(parser.unit, name, typ);
793
    check(ident # NIL, pos, 30);
795
    check(ident # NIL, pos, 30);
794
    ident.pos := pos;
796
    ident.pos := pos;
795
    Next(parser);
797
    Next(parser);
796
 
798
 
797
    IF parser.sym = SCAN.lxMUL THEN
799
    IF parser.sym = SCAN.lxMUL THEN
798
        check1(ident.global, parser, 61);
800
        check1(ident.global, parser, 61);
799
        ident.export := TRUE;
801
        ident.export := TRUE;
800
        Next(parser)
802
        Next(parser)
801
    END
803
    END
802
 
804
 
803
    RETURN ident
805
    RETURN ident
804
END IdentDef;
806
END IdentDef;
805
 
807
 
806
 
808
 
807
PROCEDURE ConstTypeDeclaration (parser: PARSER; const: BOOLEAN);
809
PROCEDURE ConstTypeDeclaration (parser: PARSER; const: BOOLEAN);
808
VAR
810
VAR
809
    ident: PROG.IDENT;
811
    ident: PROG.IDENT;
810
    name:  SCAN.IDENT;
812
    name:  SCAN.IDENT;
811
    pos:   POSITION;
813
    pos:   POSITION;
812
 
814
 
813
BEGIN
815
BEGIN
814
    IF const THEN
816
    IF const THEN
815
        ident := IdentDef(parser, PROG.idNONE, name)
817
        ident := IdentDef(parser, PROG.idNONE, name)
816
    ELSE
818
    ELSE
817
        ident := IdentDef(parser, PROG.idTYPE, name)
819
        ident := IdentDef(parser, PROG.idTYPE, name)
818
    END;
820
    END;
819
 
821
 
820
    checklex(parser, SCAN.lxEQ);
822
    checklex(parser, SCAN.lxEQ);
821
    NextPos(parser, pos);
823
    NextPos(parser, pos);
822
 
824
 
823
    IF const THEN
825
    IF const THEN
824
        ConstExpression(parser, ident.value);
826
        ConstExpression(parser, ident.value);
825
        IF ident.value.typ = ARITH.tINTEGER THEN
827
        IF ident.value.typ = ARITH.tINTEGER THEN
826
            check(ARITH.check(ident.value), pos, 39)
828
            check(ARITH.check(ident.value), pos, 39)
827
        ELSIF ident.value.typ = ARITH.tREAL THEN
829
        ELSIF ident.value.typ = ARITH.tREAL THEN
828
            check(ARITH.check(ident.value), pos, 40)
830
            check(ARITH.check(ident.value), pos, 40)
829
        END;
831
        END;
830
        ident.typ  := PROG.idCONST;
832
        ident.typ  := PROG.idCONST;
831
        ident.type := PROG.getType(program, ident.value.typ)
833
        ident.type := PROG.getType(program, ident.value.typ)
832
    ELSE
834
    ELSE
833
        type(parser, ident.type, {})
835
        type(parser, ident.type, {})
834
    END;
836
    END;
835
 
837
 
836
    checklex(parser, SCAN.lxSEMI);
838
    checklex(parser, SCAN.lxSEMI);
837
    Next(parser)
839
    Next(parser)
838
 
840
 
839
END ConstTypeDeclaration;
841
END ConstTypeDeclaration;
840
 
842
 
841
 
843
 
842
PROCEDURE VarDeclaration (parser: PARSER);
844
PROCEDURE VarDeclaration (parser: PARSER);
843
VAR
845
VAR
844
    ident: PROG.IDENT;
846
    ident: PROG.IDENT;
845
    name:  SCAN.IDENT;
847
    name:  SCAN.IDENT;
846
    t:     PROG.TYPE_;
848
    t:     PROG.TYPE_;
847
 
849
 
848
BEGIN
850
BEGIN
849
 
851
 
850
    REPEAT
852
    REPEAT
851
        ident := IdentDef(parser, PROG.idVAR, name);
853
        ident := IdentDef(parser, PROG.idVAR, name);
852
 
854
 
853
        IF parser.sym = SCAN.lxCOMMA THEN
855
        IF parser.sym = SCAN.lxCOMMA THEN
854
            ExpectSym(parser, SCAN.lxIDENT)
856
            ExpectSym(parser, SCAN.lxIDENT)
855
        ELSIF parser.sym = SCAN.lxCOLON THEN
857
        ELSIF parser.sym = SCAN.lxCOLON THEN
856
            Next(parser);
858
            Next(parser);
857
            type(parser, t, {});
859
            type(parser, t, {});
858
            PROG.setVarsType(parser.unit, t);
860
            PROG.setVarsType(parser.unit, t);
859
            checklex(parser, SCAN.lxSEMI);
861
            checklex(parser, SCAN.lxSEMI);
860
            Next(parser)
862
            Next(parser)
861
        ELSE
863
        ELSE
862
            checklex(parser, SCAN.lxCOLON)
864
            checklex(parser, SCAN.lxCOLON)
863
        END
865
        END
864
 
866
 
865
    UNTIL parser.sym # SCAN.lxIDENT
867
    UNTIL parser.sym # SCAN.lxIDENT
866
 
868
 
867
END VarDeclaration;
869
END VarDeclaration;
868
 
870
 
869
 
871
 
870
PROCEDURE DeclarationSequence (parser: PARSER): BOOLEAN;
872
PROCEDURE DeclarationSequence (parser: PARSER): BOOLEAN;
871
VAR
873
VAR
872
    ptr: PROG.FRWPTR;
874
    ptr: PROG.FRWPTR;
873
    endmod: BOOLEAN;
875
    endmod: BOOLEAN;
874
    pos: POSITION;
876
    pos: POSITION;
875
 
877
 
876
 
878
 
877
    PROCEDURE ProcDeclaration (parser: PARSER): BOOLEAN;
879
    PROCEDURE ProcDeclaration (parser: PARSER): BOOLEAN;
878
    VAR
880
    VAR
879
        proc:       PROG.IDENT;
881
        proc:       PROG.IDENT;
880
        endname,
882
        endname,
881
        name:       SCAN.IDENT;
883
        name:       SCAN.IDENT;
882
        param:      PROG.PARAM;
884
        param:      PROG.PARAM;
883
        unit:       PROG.UNIT;
885
        unit:       PROG.UNIT;
884
        ident:      PROG.IDENT;
886
        ident:      PROG.IDENT;
885
        e:          EXPR;
887
        e:          EXPR;
886
        pos, pos1,
888
        pos, pos1,
887
        pos2:       POSITION;
889
        pos2:       POSITION;
888
        label:      INTEGER;
890
        label:      INTEGER;
889
        enter:      IL.COMMAND;
891
        enter:      IL.COMMAND;
890
        call:       INTEGER;
892
        call:       INTEGER;
891
        t:          PROG.TYPE_;
893
        t:          PROG.TYPE_;
892
        import:     IL.IMPORT_PROC;
894
        import:     IL.IMPORT_PROC;
893
        endmod, b:  BOOLEAN;
895
        endmod, b:  BOOLEAN;
894
        fparams:    SET;
896
        fparams:    SET;
895
        variables:  LISTS.LIST;
897
        variables:  LISTS.LIST;
896
        int, flt:   INTEGER;
898
        int, flt:   INTEGER;
897
        comma:      BOOLEAN;
899
        comma:      BOOLEAN;
898
        code:       ARITH.VALUE;
900
        code:       ARITH.VALUE;
899
        codeProc:   BOOLEAN;
901
        codeProc:   BOOLEAN;
900
 
902
 
901
    BEGIN
903
    BEGIN
902
        endmod := FALSE;
904
        endmod := FALSE;
903
 
905
 
904
        unit := parser.unit;
906
        unit := parser.unit;
905
 
907
 
906
        call := procflag(parser, import, TRUE);
908
        call := procflag(parser, import, TRUE);
907
 
909
 
908
        getpos(parser, pos);
910
        getpos(parser, pos);
909
        pos1 := pos;
911
        pos1 := pos;
910
        checklex(parser, SCAN.lxIDENT);
912
        checklex(parser, SCAN.lxIDENT);
911
 
913
 
912
        IF import # NIL THEN
914
        IF import # NIL THEN
913
            proc := IdentDef(parser, PROG.idIMP, name);
915
            proc := IdentDef(parser, PROG.idIMP, name);
914
            proc.import := import;
916
            proc.import := import;
915
            program.procs.last(PROG.PROC).import := import
917
            program.procs.last(PROG.PROC).import := import
916
        ELSE
918
        ELSE
917
            proc := IdentDef(parser, PROG.idPROC, name)
919
            proc := IdentDef(parser, PROG.idPROC, name)
918
        END;
920
        END;
919
 
921
 
920
        check(PROG.openScope(unit, proc.proc), pos, 116);
922
        check(PROG.openScope(unit, proc.proc), pos, 116);
921
 
923
 
922
        proc.type := PROG.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit);
924
        proc.type := PROG.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit);
923
        t := proc.type;
925
        t := proc.type;
924
        t.align := program.target.adr;
926
        t.align := program.target.adr;
925
        t.call  := call;
927
        t.call  := call;
926
 
928
 
927
        FormalParameters(parser, t);
929
        FormalParameters(parser, t);
928
 
930
 
929
        codeProc := call IN {PROG.code, PROG._code};
931
        codeProc := call IN {PROG.code, PROG._code};
930
 
932
 
931
        IF call IN {PROG.systemv, PROG._systemv} THEN
933
        IF call IN {PROG.systemv, PROG._systemv} THEN
932
            check(t.parSize <= PROG.MAXSYSVPARAM, pos, 120)
934
            check(t.parSize <= PROG.MAXSYSVPARAM, pos, 120)
933
        END;
935
        END;
934
 
936
 
935
        param := t.params.first(PROG.PARAM);
937
        param := t.params.first(PROG.PARAM);
936
        WHILE param # NIL DO
938
        WHILE param # NIL DO
937
            ident := PROG.addIdent(unit, param.name, PROG.idPARAM);
939
            ident := PROG.addIdent(unit, param.name, PROG.idPARAM);
938
            ASSERT(ident # NIL);
940
            ASSERT(ident # NIL);
939
            ident.type := param.type;
941
            ident.type := param.type;
940
            ident.offset := param.offset;
942
            ident.offset := param.offset;
941
            IF param.vPar THEN
943
            IF param.vPar THEN
942
                ident.typ := PROG.idVPAR
944
                ident.typ := PROG.idVPAR
943
            END;
945
            END;
944
            param := param.next(PROG.PARAM)
946
            param := param.next(PROG.PARAM)
945
        END;
947
        END;
946
 
948
 
947
        IF import = NIL THEN
949
        IF import = NIL THEN
948
            label := IL.NewLabel();
950
            label := IL.NewLabel();
949
            proc.proc.label := label
951
            proc.proc.label := label
950
        END;
952
        END;
951
 
953
 
952
        IF codeProc THEN
954
        IF codeProc THEN
953
            enter := IL.EnterC(label);
955
            enter := IL.EnterC(label);
954
            comma := FALSE;
956
            comma := FALSE;
955
            WHILE (parser.sym # SCAN.lxSEMI) OR comma DO
957
            WHILE (parser.sym # SCAN.lxSEMI) OR comma DO
956
                getpos(parser, pos2);
958
                getpos(parser, pos2);
957
                ConstExpression(parser, code);
959
                ConstExpression(parser, code);
958
                check(code.typ = ARITH.tINTEGER, pos2, 43);
960
                check(code.typ = ARITH.tINTEGER, pos2, 43);
959
                IF program.target.sys # mConst.Target_iMSP430 THEN
961
                IF program.target.sys # mConst.Target_iMSP430 THEN
960
                    check(ARITH.range(code, 0, 255), pos2, 42)
962
                    check(ARITH.range(code, 0, 255), pos2, 42)
961
                END;
963
                END;
962
                IL.AddCmd(IL.opCODE, ARITH.getInt(code));
964
                IL.AddCmd(IL.opCODE, ARITH.getInt(code));
963
                comma := parser.sym = SCAN.lxCOMMA;
965
                comma := parser.sym = SCAN.lxCOMMA;
964
                IF comma THEN
966
                IF comma THEN
965
                    Next(parser)
967
                    Next(parser)
966
                ELSE
968
                ELSE
967
                    checklex(parser, SCAN.lxSEMI)
969
                    checklex(parser, SCAN.lxSEMI)
968
                END
970
                END
969
            END
971
            END
970
        END;
972
        END;
971
 
973
 
972
        checklex(parser, SCAN.lxSEMI);
974
        checklex(parser, SCAN.lxSEMI);
973
        Next(parser);
975
        Next(parser);
974
 
976
 
975
        IF import = NIL THEN
977
        IF import = NIL THEN
976
 
978
 
977
            IF parser.main & proc.export & program.dll THEN
979
            IF parser.main & proc.export & program.dll THEN
978
                IF program.obj THEN
980
                IF program.obj THEN
979
                    check((proc.name.s # "lib_init") & (proc.name.s # "version"), pos, 114)
981
                    check((proc.name.s # "lib_init") & (proc.name.s # "version"), pos, 114)
980
                END;
982
                END;
981
                IL.AddExp(label, proc.name.s);
983
                IL.AddExp(label, proc.name.s);
982
                proc.proc.used := TRUE
984
                proc.proc.used := TRUE
983
            END;
985
            END;
984
 
986
 
985
            IF ~codeProc THEN
987
            IF ~codeProc THEN
986
                b := DeclarationSequence(parser)
988
                b := DeclarationSequence(parser)
987
            END;
989
            END;
988
 
990
 
989
            program.locsize := 0;
991
            program.locsize := 0;
990
            IF call IN {PROG._win64, PROG.win64} THEN
992
            IF call IN {PROG._win64, PROG.win64} THEN
991
                fparams := PROG.getFloatParamsPos(proc.type, 3, int, flt);
993
                fparams := PROG.getFloatParamsPos(proc.type, 3, int, flt);
992
                enter := IL.Enter(label, LSL(ORD(fparams), 5) + MIN(proc.type.parSize, 4))
994
                enter := IL.Enter(label, LSL(ORD(fparams), 5) + MIN(proc.type.parSize, 4))
993
            ELSIF call IN {PROG._systemv, PROG.systemv} THEN
995
            ELSIF call IN {PROG._systemv, PROG.systemv} THEN
994
                fparams := PROG.getFloatParamsPos(proc.type, PROG.MAXSYSVPARAM - 1, int, flt);
996
                fparams := PROG.getFloatParamsPos(proc.type, PROG.MAXSYSVPARAM - 1, int, flt);
995
                enter := IL.Enter(label, -(LSL(ORD(fparams), 5) + proc.type.parSize))
997
                enter := IL.Enter(label, -(LSL(ORD(fparams), 5) + proc.type.parSize))
996
            ELSIF codeProc THEN
998
            ELSIF codeProc THEN
997
 
999
 
998
            ELSE
1000
            ELSE
999
                enter := IL.Enter(label, 0)
1001
                enter := IL.Enter(label, 0)
1000
            END;
1002
            END;
1001
            proc.proc.enter := enter;
1003
            proc.proc.enter := enter;
1002
 
1004
 
1003
            IF ~codeProc & (parser.sym = SCAN.lxBEGIN) THEN
1005
            IF ~codeProc & (parser.sym = SCAN.lxBEGIN) THEN
1004
                Next(parser);
1006
                Next(parser);
1005
                parser.StatSeq(parser)
1007
                parser.StatSeq(parser)
1006
            END;
1008
            END;
1007
 
1009
 
1008
            IF ~codeProc & (t.base # NIL) THEN
1010
            IF ~codeProc & (t.base # NIL) THEN
1009
                checklex(parser, SCAN.lxRETURN);
1011
                checklex(parser, SCAN.lxRETURN);
1010
                NextPos(parser, pos);
1012
                NextPos(parser, pos);
1011
                parser.expression(parser, e);
1013
                parser.expression(parser, e);
1012
                check(parser.chkreturn(parser, e, t.base, pos), pos, 87)
1014
                check(parser.chkreturn(parser, e, t.base, pos), pos, 87)
1013
            END;
1015
            END;
1014
 
1016
 
1015
            IF ~codeProc THEN
1017
            IF ~codeProc THEN
1016
                proc.proc.leave := IL.Leave(t.base # NIL, (t.base # NIL) & (t.base.typ = PROG.tREAL), program.locsize,
1018
                proc.proc.leave := IL.Leave(t.base # NIL, (t.base # NIL) & (t.base.typ = PROG.tREAL), program.locsize,
1017
                    t.parSize * ORD((t.call IN PROG.callee_clean_up) OR (t.call IN {PROG.systemv, PROG._systemv})));
1019
                    t.parSize * ORD((t.call IN PROG.callee_clean_up) OR (t.call IN {PROG.systemv, PROG._systemv})));
1018
                enter.param2 := program.locsize;
1020
                enter.param2 := program.locsize;
1019
                checklex(parser, SCAN.lxEND)
1021
                checklex(parser, SCAN.lxEND)
1020
            ELSE
1022
            ELSE
1021
                proc.proc.leave := IL.LeaveC()
1023
                proc.proc.leave := IL.LeaveC()
1022
            END;
1024
            END;
1023
 
1025
 
1024
            IF program.target.sys = mConst.Target_iMSP430 THEN
1026
            IF program.target.sys = mConst.Target_iMSP430 THEN
1025
                check((enter.param2 * ORD(~codeProc) + proc.type.parSize) * 2 + 16 < program.target.options.ram, pos1, 63)
1027
                check((enter.param2 * ORD(~codeProc) + proc.type.parSize) * 2 + 16 < program.target.options.ram, pos1, 63)
1026
            END
1028
            END
1027
        END;
1029
        END;
1028
 
1030
 
1029
        IF parser.sym = SCAN.lxEND THEN
1031
        IF parser.sym = SCAN.lxEND THEN
1030
            ExpectSym(parser, SCAN.lxIDENT);
1032
            ExpectSym(parser, SCAN.lxIDENT);
1031
            getpos(parser, pos);
1033
            getpos(parser, pos);
1032
            endname := parser.lex.ident;
1034
            endname := parser.lex.ident;
1033
            IF ~codeProc & (import = NIL) THEN
1035
            IF ~codeProc & (import = NIL) THEN
1034
                check(endname = name, pos, 60);
1036
                check(endname = name, pos, 60);
1035
                ExpectSym(parser, SCAN.lxSEMI);
1037
                ExpectSym(parser, SCAN.lxSEMI);
1036
                Next(parser)
1038
                Next(parser)
1037
            ELSE
1039
            ELSE
1038
                IF endname = parser.unit.name THEN
1040
                IF endname = parser.unit.name THEN
1039
                    ExpectSym(parser, SCAN.lxPOINT);
1041
                    ExpectSym(parser, SCAN.lxPOINT);
1040
                    Next(parser);
1042
                    Next(parser);
1041
                    endmod := TRUE
1043
                    endmod := TRUE
1042
                ELSIF endname = name THEN
1044
                ELSIF endname = name THEN
1043
                    ExpectSym(parser, SCAN.lxSEMI);
1045
                    ExpectSym(parser, SCAN.lxSEMI);
1044
                    Next(parser)
1046
                    Next(parser)
1045
                ELSE
1047
                ELSE
1046
                    error(pos, 60)
1048
                    error(pos, 60)
1047
                END
1049
                END
1048
            END
1050
            END
1049
        END;
1051
        END;
1050
 
1052
 
1051
        IF ~codeProc & (import = NIL) THEN
1053
        IF ~codeProc & (import = NIL) THEN
1052
            variables := LISTS.create(NIL);
1054
            variables := LISTS.create(NIL);
1053
        ELSE
1055
        ELSE
1054
            variables := NIL
1056
            variables := NIL
1055
        END;
1057
        END;
1056
 
1058
 
1057
        PROG.closeScope(unit, variables);
1059
        PROG.closeScope(unit, variables);
1058
 
1060
 
1059
        IF ~codeProc & (import = NIL) THEN
1061
        IF ~codeProc & (import = NIL) THEN
1060
            enter.variables := variables
1062
            enter.variables := variables
1061
        END
1063
        END
1062
 
1064
 
1063
        RETURN endmod
1065
        RETURN endmod
1064
    END ProcDeclaration;
1066
    END ProcDeclaration;
1065
 
1067
 
1066
 
1068
 
1067
BEGIN
1069
BEGIN
1068
    IF parser.sym = SCAN.lxCONST THEN
1070
    IF parser.sym = SCAN.lxCONST THEN
1069
        Next(parser);
1071
        Next(parser);
1070
        WHILE parser.sym = SCAN.lxIDENT DO
1072
        WHILE parser.sym = SCAN.lxIDENT DO
1071
            ConstTypeDeclaration(parser, TRUE)
1073
            ConstTypeDeclaration(parser, TRUE)
1072
        END
1074
        END
1073
    END;
1075
    END;
1074
 
1076
 
1075
    IF parser.sym = SCAN.lxTYPE THEN
1077
    IF parser.sym = SCAN.lxTYPE THEN
1076
        Next(parser);
1078
        Next(parser);
1077
        WHILE parser.sym = SCAN.lxIDENT DO
1079
        WHILE parser.sym = SCAN.lxIDENT DO
1078
            ConstTypeDeclaration(parser, FALSE)
1080
            ConstTypeDeclaration(parser, FALSE)
1079
        END
1081
        END
1080
    END;
1082
    END;
1081
 
1083
 
1082
    ptr := PROG.linkPtr(parser.unit);
1084
    ptr := PROG.linkPtr(parser.unit);
1083
    IF ptr # NIL THEN
1085
    IF ptr # NIL THEN
1084
        pos.line := ptr.pos.line;
1086
        pos.line := ptr.pos.line;
1085
        pos.col  := ptr.pos.col;
1087
        pos.col  := ptr.pos.col;
1086
        pos.parser := parser;
1088
        pos.parser := parser;
1087
        IF ptr.notRecord THEN
1089
        IF ptr.notRecord THEN
1088
            error(pos, 58)
1090
            error(pos, 58)
1089
        ELSE
1091
        ELSE
1090
            error(pos, 48)
1092
            error(pos, 48)
1091
        END
1093
        END
1092
    END;
1094
    END;
1093
 
1095
 
1094
    IF parser.sym = SCAN.lxVAR THEN
1096
    IF parser.sym = SCAN.lxVAR THEN
1095
        Next(parser);
1097
        Next(parser);
1096
        IF parser.sym = SCAN.lxIDENT THEN
1098
        IF parser.sym = SCAN.lxIDENT THEN
1097
            VarDeclaration(parser)
1099
            VarDeclaration(parser)
1098
        END
1100
        END
1099
    END;
1101
    END;
1100
 
1102
 
1101
    endmod := FALSE;
1103
    endmod := FALSE;
1102
    WHILE ~endmod & (parser.sym = SCAN.lxPROCEDURE) DO
1104
    WHILE ~endmod & (parser.sym = SCAN.lxPROCEDURE) DO
1103
        Next(parser);
1105
        Next(parser);
1104
        endmod := ProcDeclaration(parser)
1106
        endmod := ProcDeclaration(parser)
1105
    END
1107
    END
1106
 
1108
 
1107
    RETURN endmod
1109
    RETURN endmod
1108
END DeclarationSequence;
1110
END DeclarationSequence;
1109
 
1111
 
1110
 
1112
 
1111
PROCEDURE parse (parser: PARSER);
1113
PROCEDURE parse (parser: PARSER);
1112
VAR
1114
VAR
1113
    unit:     PROG.UNIT;
1115
    unit:     PROG.UNIT;
1114
    label:    INTEGER;
1116
    label:    INTEGER;
1115
    name:     INTEGER;
1117
    name:     INTEGER;
1116
    endmod:   BOOLEAN;
1118
    endmod:   BOOLEAN;
1117
    errlabel: INTEGER;
1119
    errlabel: INTEGER;
1118
    errno:    INTEGER;
1120
    errno:    INTEGER;
1119
 
1121
 
1120
BEGIN
1122
BEGIN
1121
    ASSERT(parser # NIL);
1123
    ASSERT(parser # NIL);
1122
    ASSERT(parser.scanner # NIL);
1124
    ASSERT(parser.scanner # NIL);
1123
 
1125
 
1124
    ExpectSym(parser, SCAN.lxMODULE);
1126
    ExpectSym(parser, SCAN.lxMODULE);
1125
    ExpectSym(parser, SCAN.lxIDENT);
1127
    ExpectSym(parser, SCAN.lxIDENT);
1126
 
1128
 
1127
    IF ~parser.main THEN
1129
    IF ~parser.main THEN
1128
        check1(parser.lex.s = parser.modname, parser, 23)
1130
        check1(parser.lex.s = parser.modname, parser, 23)
1129
    END;
1131
    END;
1130
 
1132
 
1131
    unit := PROG.newUnit(program, parser.lex.ident);
1133
    unit := PROG.newUnit(program, parser.lex.ident);
1132
 
1134
 
1133
    parser.unit := unit;
1135
    parser.unit := unit;
1134
 
1136
 
1135
    ExpectSym(parser, SCAN.lxSEMI);
1137
    ExpectSym(parser, SCAN.lxSEMI);
1136
 
1138
 
1137
    Next(parser);
1139
    Next(parser);
1138
    IF parser.sym = SCAN.lxIMPORT THEN
1140
    IF parser.sym = SCAN.lxIMPORT THEN
1139
        ImportList(parser)
1141
        ImportList(parser)
1140
    END;
1142
    END;
1141
 
1143
 
1142
    CONSOLE.String("compiling "); CONSOLE.String(unit.name.s);
1144
    CONSOLE.String("compiling "); CONSOLE.String(unit.name.s);
1143
    IF parser.unit.sysimport THEN
1145
    IF parser.unit.sysimport THEN
1144
        CONSOLE.String(" (SYSTEM)")
1146
        CONSOLE.String(" (SYSTEM)")
1145
    END;
1147
    END;
1146
    CONSOLE.Ln;
1148
    CONSOLE.Ln;
1147
 
1149
 
1148
    label := IL.NewLabel();
1150
    label := IL.NewLabel();
1149
    IL.AddJmpCmd(IL.opJMP, label);
1151
    IL.AddJmpCmd(IL.opJMP, label);
1150
 
1152
 
1151
    name := IL.putstr(unit.name.s);
1153
    name := IL.putstr(unit.name.s);
1152
 
1154
 
1153
    errlabel := IL.NewLabel();
1155
    errlabel := IL.NewLabel();
1154
    IL.SetLabel(errlabel);
1156
    IL.SetLabel(errlabel);
1155
    IL.StrAdr(name);
1157
    IL.StrAdr(name);
1156
    IL.Param1;
1158
    IL.Param1;
1157
    IL.AddCmd0(IL.opERR);
1159
    IL.AddCmd0(IL.opERR);
1158
 
1160
 
1159
    FOR errno := 1 TO LEN(IL.codes.errlabels) - 1 DO
1161
    FOR errno := 1 TO LEN(IL.codes.errlabels) - 1 DO
1160
        IL.SetErrLabel(errno);
1162
        IL.SetErrLabel(errno);
1161
        IL.AddCmd(IL.opPUSHC, errno);
1163
        IL.AddCmd(IL.opPUSHC, errno);
1162
        IL.AddJmpCmd(IL.opJMP, errlabel)
1164
        IL.AddJmpCmd(IL.opJMP, errlabel)
1163
    END;
1165
    END;
1164
 
1166
 
1165
    endmod := DeclarationSequence(parser);
1167
    endmod := DeclarationSequence(parser);
1166
 
1168
 
1167
    IL.SetLabel(label);
1169
    IL.SetLabel(label);
1168
 
1170
 
1169
    IF ~endmod THEN
1171
    IF ~endmod THEN
1170
 
1172
 
1171
        IF parser.sym = SCAN.lxBEGIN THEN
1173
        IF parser.sym = SCAN.lxBEGIN THEN
1172
            Next(parser);
1174
            Next(parser);
1173
            parser.StatSeq(parser)
1175
            parser.StatSeq(parser)
1174
        END;
1176
        END;
1175
 
1177
 
1176
        checklex(parser, SCAN.lxEND);
1178
        checklex(parser, SCAN.lxEND);
1177
 
1179
 
1178
        ExpectSym(parser, SCAN.lxIDENT);
1180
        ExpectSym(parser, SCAN.lxIDENT);
1179
        check1(parser.lex.s = unit.name.s, parser, 25);
1181
        check1(parser.lex.s = unit.name.s, parser, 25);
1180
        ExpectSym(parser, SCAN.lxPOINT)
1182
        ExpectSym(parser, SCAN.lxPOINT)
1181
 
-
 
1182
    END;
1183
    END;
-
 
1184
 
1183
 
1185
    INC(lines, parser.lex.pos.line);
1184
    PROG.closeUnit(unit)
1186
    PROG.closeUnit(unit)
1185
END parse;
1187
END parse;
1186
 
1188
 
1187
 
1189
 
1188
PROCEDURE open (parser: PARSER; modname: ARRAY OF CHAR): BOOLEAN;
1190
PROCEDURE open (parser: PARSER; modname: ARRAY OF CHAR): BOOLEAN;
1189
BEGIN
1191
BEGIN
1190
    ASSERT(parser # NIL);
1192
    ASSERT(parser # NIL);
1191
 
1193
 
1192
    STRINGS.append(parser.fname, modname);
1194
    STRINGS.append(parser.fname, modname);
1193
    STRINGS.append(parser.fname, parser.ext);
1195
    STRINGS.append(parser.fname, parser.ext);
1194
    STRINGS.append(parser.modname, modname);
1196
    STRINGS.append(parser.modname, modname);
1195
 
1197
 
1196
    parser.scanner := SCAN.open(parser.fname)
1198
    parser.scanner := SCAN.open(parser.fname)
1197
 
1199
 
1198
    RETURN parser.scanner # NIL
1200
    RETURN parser.scanner # NIL
1199
END open;
1201
END open;
1200
 
1202
 
1201
 
1203
 
1202
PROCEDURE NewParser (): PARSER;
1204
PROCEDURE NewParser (): PARSER;
1203
VAR
1205
VAR
1204
    pars:  PARSER;
1206
    pars:  PARSER;
1205
    citem: C.ITEM;
1207
    citem: C.ITEM;
1206
 
1208
 
1207
BEGIN
1209
BEGIN
1208
    citem := C.pop(parsers);
1210
    citem := C.pop(parsers);
1209
    IF citem = NIL THEN
1211
    IF citem = NIL THEN
1210
        NEW(pars)
1212
        NEW(pars)
1211
    ELSE
1213
    ELSE
1212
        pars := citem(PARSER)
1214
        pars := citem(PARSER)
1213
    END
1215
    END
1214
 
1216
 
1215
    RETURN pars
1217
    RETURN pars
1216
END NewParser;
1218
END NewParser;
1217
 
1219
 
1218
 
1220
 
1219
PROCEDURE create* (path, lib_path: PATH; StatSeq: STATPROC; expression, designator: EXPRPROC; chkreturn: RETPROC): PARSER;
1221
PROCEDURE create* (path, lib_path: PATH; StatSeq: STATPROC; expression, designator: EXPRPROC; chkreturn: RETPROC): PARSER;
1220
VAR
1222
VAR
1221
    parser: PARSER;
1223
    parser: PARSER;
1222
 
1224
 
1223
BEGIN
1225
BEGIN
1224
    parser := NewParser();
1226
    parser := NewParser();
1225
 
1227
 
1226
    parser.path     := path;
1228
    parser.path     := path;
1227
    parser.lib_path := lib_path;
1229
    parser.lib_path := lib_path;
1228
    parser.ext      := mConst.FILE_EXT;
1230
    parser.ext      := mConst.FILE_EXT;
1229
    parser.fname    := path;
1231
    parser.fname    := path;
1230
    parser.modname  := "";
1232
    parser.modname  := "";
1231
    parser.scanner  := NIL;
1233
    parser.scanner  := NIL;
1232
    parser.unit     := NIL;
1234
    parser.unit     := NIL;
1233
    parser.constexp := FALSE;
1235
    parser.constexp := FALSE;
1234
    parser.main     := FALSE;
1236
    parser.main     := FALSE;
1235
 
1237
 
1236
    parser.open       := open;
1238
    parser.open       := open;
1237
    parser.parse      := parse;
1239
    parser.parse      := parse;
1238
    parser.StatSeq    := StatSeq;
1240
    parser.StatSeq    := StatSeq;
1239
    parser.expression := expression;
1241
    parser.expression := expression;
1240
    parser.designator := designator;
1242
    parser.designator := designator;
1241
    parser.chkreturn  := chkreturn;
1243
    parser.chkreturn  := chkreturn;
1242
    parser.create     := create
1244
    parser.create     := create
1243
 
1245
 
1244
    RETURN parser
1246
    RETURN parser
1245
END create;
1247
END create;
1246
 
1248
 
1247
 
1249
 
1248
PROCEDURE init* (bit_depth, target: INTEGER; options: PROG.OPTIONS);
1250
PROCEDURE init* (bit_depth, target: INTEGER; options: PROG.OPTIONS);
1249
BEGIN
1251
BEGIN
1250
    program := PROG.create(bit_depth, target, options);
1252
    program := PROG.create(bit_depth, target, options);
1251
    parsers := C.create()
1253
    parsers := C.create();
-
 
1254
    lines   := 0
1252
END init;
1255
END init;
1253
 
1256
 
1254
 
1257
 
1255
END PARS.
1258
END PARS.