/
parse.c
574 lines (489 loc) · 17.2 KB
/
parse.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-2010, Linköpings University,
* Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THIS OSMC PUBLIC
* LICENSE (OSMC-PL). ANY USE, REPRODUCTION OR DISTRIBUTION OF
* THIS PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THE OSMC
* PUBLIC LICENSE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from Linköpings University, either from the above address,
* from the URL: http://www.ida.liu.se/projects/OpenModelica
* and in the OpenModelica distribution.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS
* OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <MetaModelica_Lexer.h>
#include <Modelica_3_Lexer.h>
#include <ModelicaParser.h>
#include "runtime/errorext.h"
const char* modelicafilename; // The filename for the parsed file.
bool modelicafileReadOnly; // True if file is read only.
#include <errno.h>
long unsigned int szMemoryUsed = 0;
long lexerFailed;
void Parser_5finit(void)
{
}
void lexNoRecover(pANTLR3_LEXER lexer)
{
lexer->rec->state->error = ANTLR3_TRUE;
pANTLR3_INT_STREAM istream = lexer->input->istream;
istream->consume(istream);
}
void noRecover(pANTLR3_BASE_RECOGNIZER recognizer)
{
recognizer->state->error = ANTLR3_TRUE;
}
static void* noRecoverFromMismatchedSet(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_BITSET_LIST follow)
{
recognizer->state->error = ANTLR3_TRUE;
return NULL;
}
static void* noRecoverFromMismatchedToken(pANTLR3_BASE_RECOGNIZER recognizer, ANTLR3_UINT32 ttype, pANTLR3_BITSET_LIST follow)
{
pANTLR3_PARSER parser;
pANTLR3_TREE_PARSER tparser;
pANTLR3_INT_STREAM is;
void * matchedSymbol;
// Invoke the debugger event if there is a debugger listening to us
//
if (recognizer->debugger != NULL)
{
recognizer->debugger->recognitionException(recognizer->debugger, recognizer->state->exception);
}
switch (recognizer->type)
{
case ANTLR3_TYPE_PARSER:
parser = (pANTLR3_PARSER) (recognizer->super);
tparser = NULL;
is = parser->tstream->istream;
break;
case ANTLR3_TYPE_TREE_PARSER:
tparser = (pANTLR3_TREE_PARSER) (recognizer->super);
parser = NULL;
is = tparser->ctnstream->tnstream->istream;
break;
default:
ANTLR3_FPRINTF(stderr, "Base recognizer function recoverFromMismatchedToken called by unknown parser type - provide override for this function\n");
return NULL;
break;
}
// Create an exception if we need one
//
if (recognizer->state->exception == NULL)
{
antlr3RecognitionExceptionNew(recognizer);
}
if ( recognizer->mismatchIsUnwantedToken(recognizer, is, ttype) == ANTLR3_TRUE)
{
recognizer->state->exception->type = ANTLR3_UNWANTED_TOKEN_EXCEPTION;
recognizer->state->exception->message = ANTLR3_UNWANTED_TOKEN_EXCEPTION_NAME;
return NULL;
}
if (recognizer->mismatchIsMissingToken(recognizer, is, follow))
{
matchedSymbol = recognizer->getMissingSymbol(recognizer, is, recognizer->state->exception, ttype, follow);
recognizer->state->exception->type = ANTLR3_MISSING_TOKEN_EXCEPTION;
recognizer->state->exception->message = ANTLR3_MISSING_TOKEN_EXCEPTION_NAME;
recognizer->state->exception->token = matchedSymbol;
recognizer->state->exception->expecting = ttype;
return NULL;
}
// Neither deleting nor inserting tokens allows recovery
// must just report the exception.
//
recognizer->state->error = ANTLR3_TRUE;
return NULL;
}
static void handleLexerError(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_UINT8 * tokenNames)
{
pANTLR3_LEXER lexer;
pANTLR3_EXCEPTION ex;
pANTLR3_STRING ftext;
lexer = (pANTLR3_LEXER)(recognizer->super);
ex = lexer->rec->state->exception;
const char* chars = lexer->input->substr(lexer->input, lexer->getCharIndex(lexer), lexer->getCharIndex(lexer)+20)->chars;
int line = lexer->getLine(lexer);
int offset = lexer->getCharPositionInLine(lexer)+1;
c_add_source_message(2, "SYNTAX", "Error", "Lexer failed to recognize: %s", &chars, 1, line, offset, line, offset, false, ModelicaParser_filename_C);
lexerFailed = ANTLR3_TRUE;
}
/* Error handling based on antlr3baserecognizer.c */
void handleParseError(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_UINT8 * tokenNames)
{
pANTLR3_PARSER parser;
pANTLR3_TREE_PARSER tparser;
pANTLR3_INT_STREAM is;
pANTLR3_STRING ttext;
pANTLR3_EXCEPTION ex;
pANTLR3_COMMON_TOKEN theToken;
pANTLR3_BASE_TREE theBaseTree;
pANTLR3_COMMON_TREE theCommonTree;
int type;
const char *error_type = "TRANSLATION";
const char *token_text[2] = {0,0};
int offset, error_id = 0, line;
recognizer->state->error = ANTLR3_TRUE;
if (lexerFailed)
return;
recognizer->state->failed = ANTLR3_TRUE;
// Retrieve some info for easy reading.
ex = recognizer->state->exception;
ttext = NULL;
switch (recognizer->type)
{
case ANTLR3_TYPE_PARSER:
theToken = (pANTLR3_COMMON_TOKEN)(ex->token);
if (theToken != NULL)
ttext = theToken->getText(theToken);
offset = ex->charPositionInLine+1;
if (theToken != NULL && theToken->type == ANTLR3_TOKEN_EOF) {
token_text[0] = "<EOF>";
} else if (ttext != NULL) {
token_text[0] = ttext->chars;
} else {
fprintf(stderr, "has index %d\n", theToken->type);
token_text[0] = (const char*) tokenNames[theToken->index]; // "<no text for the token>";
}
token_text[1] = (const char*) ex->message;
type = ex->type;
break;
default:
ANTLR3_FPRINTF(stderr, "Base recognizer function displayRecognitionError called by unknown parser type - provide override for this function\n");
return;
break;
}
switch (type) {
case ANTLR3_UNWANTED_TOKEN_EXCEPTION:
token_text[0] = ex->expecting == ANTLR3_TOKEN_EOF ? "<EOF>" : (const char*) tokenNames[ex->expecting];
c_add_source_message(2, "SYNTAX", "Error", "Unwanted token '%s'.", token_text, 1, ex->line, offset, ex->line, offset, false, ModelicaParser_filename_C);
break;
case ANTLR3_MISSING_TOKEN_EXCEPTION:
token_text[0] = ex->expecting == ANTLR3_TOKEN_EOF ? "<EOF>" : (const char*) tokenNames[ex->expecting];
c_add_source_message(2, "SYNTAX", "Error", "Missing token '%s'.", token_text, 1, ex->line, offset, ex->line, offset, false, ModelicaParser_filename_C);
break;
case ModelicaParserException:
c_add_source_message(2, "SYNTAX", "Error", "%s.", token_text+1, 1, ex->line, offset, ex->line, offset, false, ModelicaParser_filename_C);
break;
default:
c_add_source_message(2, "SYNTAX", "Error", "Parser error near: '%s'. ", token_text, 1, ex->line, offset, ex->line, offset, false, ModelicaParser_filename_C);
break;
}
}
void* parseFile(void* fileNameRML, int flags)
{
bool debug = check_debug_flag("parsedebug");
bool parsedump = check_debug_flag("parsedump");
bool parseonly = check_debug_flag("parseonly");
void* lxr = 0;
// TODO: Add flags to the actual Parser.parse() call instead of here?
if (accept_meta_modelica_grammar()) flags |= PARSE_META_MODELICA;
if (debug) { fprintf(stderr, "Starting parsing of file: %s\n", ModelicaParser_filename_C); }
pANTLR3_UINT8 fName;
pANTLR3_INPUT_STREAM input;
pANTLR3_LEXER pLexer;
pANTLR3_COMMON_TOKEN_STREAM tstream;
pModelicaParser psr;
ModelicaParser_filename_C = RML_STRINGDATA(fileNameRML);
/* For some reason we get undefined values if we use the old pointer; but only in rare cases */
ModelicaParser_filename_RML = mk_scon((char*)ModelicaParser_filename_C);
ModelicaParser_flags = flags;
fName = (pANTLR3_UINT8)ModelicaParser_filename_C;
input = antlr3AsciiFileStreamNew(fName);
if ( input == NULL ) { fprintf(stderr, "Unable to open file %s\n", ModelicaParser_filename_C); exit(ANTLR3_ERR_NOMEM); }
if (flags & PARSE_META_MODELICA) {
lxr = MetaModelica_LexerNew(input);
if (lxr == NULL ) { fprintf(stderr, "Unable to create the lexer due to malloc() failure1\n"); exit(ANTLR3_ERR_NOMEM); }
pLexer = ((pMetaModelica_Lexer)lxr)->pLexer;
pLexer->rec->displayRecognitionError = handleLexerError;
pLexer->recover = lexNoRecover;
tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(((pMetaModelica_Lexer)lxr)));
} else {
lxr = Modelica_3_LexerNew(input);
if (lxr == NULL ) { fprintf(stderr, "Unable to create the lexer due to malloc() failure1\n"); exit(ANTLR3_ERR_NOMEM); }
pLexer = ((pModelica_3_Lexer)lxr)->pLexer;
pLexer->rec->displayRecognitionError = handleLexerError;
pLexer->recover = lexNoRecover;
tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(((pModelica_3_Lexer)lxr)));
}
lexerFailed = ANTLR3_FALSE;
if (tstream == NULL) { fprintf(stderr, "Out of memory trying to allocate token stream\n"); exit(ANTLR3_ERR_NOMEM); }
tstream->channel = ANTLR3_TOKEN_DEFAULT_CHANNEL;
tstream->discardOffChannel = ANTLR3_TRUE;
tstream->discardOffChannelToks(tstream, ANTLR3_TRUE);
// Finally, now that we have our lexer constructed, create the parser
psr = ModelicaParserNew(tstream); // ModelicaParserNew is generated by ANTLR3
if (tstream == NULL) { fprintf(stderr, "Out of memory trying to allocate parser\n"); exit(ANTLR3_ERR_NOMEM); }
psr->pParser->rec->displayRecognitionError = handleParseError;
psr->pParser->rec->recover = noRecover;
psr->pParser->rec->recoverFromMismatchedToken = noRecoverFromMismatchedToken;
// psr->pParser->rec->recoverFromMismatchedSet = noRecoverFromMismatchedSet;
void* res;
if (flags & PARSE_EXPRESSION)
res = psr->interactive_stmt(psr);
else
res = psr->stored_definition(psr);
if (pLexer->rec->state->failed || psr->pParser->rec->state->failed) // Some parts of the AST are NULL if errors are used...
res = 0;
psr->free(psr);
psr = NULL;
tstream->free(tstream);
tstream = NULL;
if (flags & PARSE_META_MODELICA) {
((pMetaModelica_Lexer)lxr)->free((pMetaModelica_Lexer)lxr);
} else {
((pModelica_3_Lexer)lxr)->free((pModelica_3_Lexer)lxr);
}
lxr = NULL;
input->close(input);
input = NULL;
return res;
}
RML_BEGIN_LABEL(Parser__parse)
{
rmlA0 = parseFile(rmlA0,PARSE_MODELICA);
if (rmlA0)
RML_TAILCALLK(rmlSC);
else
RML_TAILCALLK(rmlFC);
}
RML_END_LABEL
RML_BEGIN_LABEL(Parser__parseexp)
{
rmlA0 = parseFile(rmlA0,PARSE_EXPRESSION);
if (rmlA0)
RML_TAILCALLK(rmlSC);
else
RML_TAILCALLK(rmlFC);
}
RML_END_LABEL
/*
char *get_string(std::ostringstream& s)
{
char *buf=0;
unsigned int size=0;
string str = s.str();
if (str.length() >= size)
{
size = (unsigned int)2*str.length();
if (buf)
delete [] buf;
buf = new char[size];
}
strcpy(buf,str.c_str());
return buf;
}
*/
RML_BEGIN_LABEL(Parser__parsestring)
{
#if 0
std::ostringstream stringStream;
char* str = RML_STRINGDATA(rmlA0);
bool a0set=false;
bool a1set=false;
bool debug = check_debug_flag("parsedump");
std::istringstream stream(str);
modelicafileReadOnly = false;
modelica_lexer lex(stream);
modelica_parser parse(lex);
/* 2004-10-05 adrpo moved this declaration here to
* have the ast initialized before getting
* into the code. This way, if this relation fails at least the
* ast is initialized */
void* ast = mk_nil();
/* adrpo added 2004-10-27
* I use this to delete [] the temp allocation of get_string(...)
*/
char* getStringHolder = NULL;
try
{
ANTLR_USE_NAMESPACE(antlr)ASTFactory my_factory( "MyAST", MyAST::factory );
parse.initializeASTFactory(my_factory);
parse.setASTFactory(&my_factory);
parse.stored_definition();
RefMyAST t = RefMyAST(parse.getAST());
if (t)
{
if (debug)
{
parse_tree_dumper dumper(std::cerr);
//dumper.initializeASTFactory(factory);
//dumper.setASTFactory(&factory);
dumper.dump(t);
}
modelica_tree_parser build;
build.initializeASTFactory(my_factory);
build.setASTFactory(&my_factory);
ast = build.stored_definition(t);
if (debug) { std::cerr << "Build done\n"; }
rmlA0 = ast ? ast : mk_nil(); a0set=true;
rmlA1 = mk_scon("Ok"); a1set=true;
RML_TAILCALLK(rmlSC);
}
else
{
rmlA0 = mk_nil(); a0set=true;
rmlA1 = mk_scon("Internal error: parse tree null"); a1set=true;
RML_TAILCALLK(rmlSC);
}
}
catch (ANTLR_USE_NAMESPACE(antlr)RecognitionException &e)
{
stringStream << "[" <<
e.getLine() << ":" << e.getColumn() << "]: error: "
<< e.getMessage() << std::endl;
// std::cerr << stringStream.str().c_str();
rmlA0 = mk_nil(); a0set=true;
rmlA1 = mk_scon((getStringHolder = get_string(stringStream))); a1set=true;
}
catch (ANTLR_USE_NAMESPACE(antlr)CharStreamException &e)
{
// std::cerr << "Lexical error (CharStreamException). " << std::endl;
rmlA0 = mk_nil(); a0set=true;
rmlA1 = mk_scon("[-,-]: internal error: lexical error"); a1set=true;
}
catch (ANTLR_USE_NAMESPACE(antlr)TokenStreamException &e)
{
stringStream << "[" << lex.getLine() << ":" << lex.getColumn()
<< "]: error: illegal token" << std::endl;
// std::cerr << stringStream.str().c_str();
rmlA0 = mk_nil(); a0set=true;
rmlA1 = mk_scon((getStringHolder = get_string(stringStream))); a1set=true;
}
catch (ANTLR_USE_NAMESPACE(antlr)ANTLRException &e)
{
// std::cerr << "ANTLRException: " << e.getMessage() << std::endl;
stringStream << "[-,-]: internal error: " << e.getMessage() << std::endl;
rmlA0 = mk_nil(); a0set=true;
rmlA1 = mk_scon((getStringHolder = get_string(stringStream))); a1set=true;
}
catch (std::exception &e)
{
// std::cerr << "Error while parsing: " << e.what() << "\n";
stringStream << "[-,-]: internal error: " << e.what() << std::endl;
rmlA0 = mk_nil(); a0set=true;
rmlA1 = mk_scon((getStringHolder = get_string(stringStream))); a1set=true;
}
catch (...)
{
// std::cerr << "Error while parsing\n";
rmlA0 = mk_nil(); a0set=true;
rmlA1 = mk_scon("[-,-]: internal error"); a1set=true;
}
/* adrpo added 2004-10-27
* no need for getStringHolder temp value allocated from get_string
*/
if (getStringHolder) delete [] getStringHolder;
if (! a0set)
{
rmlA0 = mk_nil(); a0set=true;
}
if (! a1set)
{
rmlA1 = mk_scon("internal error"); a1set=true;
}
RML_TAILCALLK(rmlSC);
#endif
RML_TAILCALLK(rmlFC);
}
RML_END_LABEL
RML_BEGIN_LABEL(Parser__parsestringexp)
{
#if 0
char* str = RML_STRINGDATA(rmlA0);
std::ostringstream stringStream;
bool debug = check_debug_flag("parsedump");
/* 2004-10-05 adrpo moved this declaration here to
* have the ast initialized before getting
* into the code. This way, if this relation fails at least the
* ast is initialized */
void* ast = mk_nil();
/* adrpo added 2004-10-27
* I use this to delete [] the temp allocation of get_string(...)
*/
char* getStringHolder = NULL;
try
{
std::istringstream stream(str);
modelicafileReadOnly = false;
modelica_lexer lex(stream);
modelica_expression_parser parse(lex);
ANTLR_USE_NAMESPACE(antlr)ASTFactory factory;
parse.initializeASTFactory(factory);
parse.setASTFactory(&factory);
parse.interactiveStmts();
RefMyAST t = RefMyAST(parse.getAST());
if (t)
{
if (debug)
{
std::cerr << "parsedump not implemented for interactiveStmt yet"<<endl;
//parse_tree_dumper dumper(std::cerr);
//dumper.dump(t);
}
modelica_tree_parser build;
build.initializeASTFactory(factory);
build.setASTFactory(&factory);
ast = build.interactive_stmt(t);
if (debug)
{
std::cerr << "Build done\n";
}
rmlA0 = ast ? ast : mk_nil();
rmlA1 = mk_scon("Ok");
RML_TAILCALLK(rmlSC);
}
else
{
rmlA0 = mk_nil();
rmlA1 = mk_scon("parse tree null");
}
}
catch (ANTLR_USE_NAMESPACE(antlr)ANTLRException &e)
{
//std::cerr << "Error while parsing expression:\n" << e.getMessage() << "\n";
stringStream << "[-,-]: internal error: " << e.getMessage() << std::endl;
rmlA0 = mk_nil();
rmlA1 = mk_scon((getStringHolder = get_string(stringStream)));
}
catch (std::exception &e)
{
//std::cerr << "Error while parsing expression:\n" << e.what() << "\n";
stringStream << "[-,-]: internal error: " << e.what() << std::endl;
rmlA0 = mk_nil();
rmlA1 = mk_scon((getStringHolder = get_string(stringStream)));
}
catch (...)
{
//std::cerr << "Error while parsing expression\n";
stringStream << "Error while parsing expression. Unknown exception in parse.cpp." << std::endl;
rmlA0 = mk_nil();
rmlA1 = mk_scon((getStringHolder = get_string(stringStream)));
}
/* adrpo added 2004-10-27
* no need for getStringHolder temp value allocated from get_string
*/
if (getStringHolder) delete [] getStringHolder;
RML_TAILCALLK(rmlSC);
#endif
RML_TAILCALLK(rmlFC);
}
RML_END_LABEL