Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 1144
Functions: -% 0 / 1 / 1
Branches: 0.0% 0 / 0 / 592

OMCompiler/Compiler/Template/TplParser.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package TplParser
37 "
38 file: TplParser.mo
39 package: TplParser
40 description: Susan Parser
41
42 $Id$
43 "
44
45 import Tpl;
46 import TplAbsyn;
47
48 protected
49 import BaseAvlTree;
50 import Debug;
51 import Flags;
52 import List;
53 import System;
54 //protected import Print;
55
56
57 protected constant Integer TabSpaces = 4;
58
59 package CacheTree "AvlTree for String to Integer. New implementation only used by the backend (until we get a new bootstrapping tarball)"
60 extends BaseAvlTree;
61 redeclare type Key = String;
62 redeclare type Value = list<TplAbsyn.ASTDef>;
63 redeclare function extends keyStr
64 algorithm
65 outString := inKey;
66 end keyStr;
67 redeclare function extends valueStr
68 algorithm
69 outString := "#OPAQUE#";
70 end valueStr;
71 redeclare function extends keyCompare
72 algorithm
73 ✗ outResult := stringCompare(inKey1, inKey2);
74 end keyCompare;
75 annotation(__OpenModelica_Interface="util");
76 end CacheTree;
77
78 public
79 uniontype ParseInfo
80 record PARSE_INFO
81 String fileName;
82 list<String> errors;
83 Boolean wasFatalError;
84 end PARSE_INFO;
85 end ParseInfo;
86
87 public
88 uniontype LineInfo
89 record LINE_INFO
90 ParseInfo parseInfo;
91 Integer lineNumber;
92 Integer lineLength;
93 list<String> startOfLineChars;
94 end LINE_INFO;
95 end LineInfo;
96
97
98 public function getPosition
99 input list<String> inChars;
100 input LineInfo inLineInfo;
101
102 output Integer outLineNumber;
103 output Integer outColumnNumber;
104 algorithm
105 (outLineNumber,outColumnNumber) :=
106 match (inChars, inLineInfo)
107 local
108 list<String> chars;
109 Integer lnum, llen, tillEnd;
110
111 case (chars, LINE_INFO(lineNumber = lnum, lineLength = llen))
112 algorithm
113 ✗ tillEnd := charsTillEndOfLine(chars, 0);
114 ✗ then (lnum, llen - tillEnd);
115 end match;
116 end getPosition;
117
118
119 type LineColumnNumber = tuple<Integer,Integer>;
120 constant SourceInfo dummySourceInfo = TplAbsyn.dummySourceInfo;
121
122 public function captureStartPosition
123 input list<String> inChars;
124 input LineInfo inLineInfo;
125 input Integer inColumnOffset;
126
127 output LineColumnNumber outLineColumnNumber;
128 protected
129 Integer line, col;
130 algorithm
131 ✗ (line, col) := getPosition(inChars, inLineInfo);
132 ✗ col := col - inColumnOffset;
133 ✗ outLineColumnNumber := (line, col);
134 end captureStartPosition;
135
136
137 //TODO: add correct TIME_STAMP
138 public function tplSourceInfo
139 input LineColumnNumber inStartLineColumnNumber;
140 input list<String> inEndChars;
141 input LineInfo inEndLineInfo;
142
143 output SourceInfo outSourceInfo;
144 algorithm
145 outSourceInfo :=
146 match (inStartLineColumnNumber, inEndLineInfo)
147 local
148 Integer startL, startC, endL, endC;
149 LineInfo endlinfo;
150 String fileName;
151
152 case ((startL, startC), endlinfo as LINE_INFO(parseInfo = PARSE_INFO(fileName = fileName)))
153 algorithm
154 ✗ (endL, endC) := getPosition(inEndChars, endlinfo);
155 ✗ outSourceInfo := SOURCEINFO(fileName, false, startL, startC, endL, endC, 0.0);
156 then outSourceInfo;
157 end match;
158 end tplSourceInfo;
159
160
161 public function startPositionFromExp
162 input TplAbsyn.Expression inExpression;
163 output LineColumnNumber outLineColumnNumber;
164 algorithm
165 outLineColumnNumber := match inExpression
166 local
167 Integer startL, startC;
168 case (_, SOURCEINFO(lineNumberStart = startL, columnNumberStart = startC))
169 ✗ then ((startL, startC));
170 end match;
171 end startPositionFromExp;
172
173
174 public function charsTillEndOfLine
175 input list<String> inChars;
176 input output Integer outCharsTillEnd;
177 protected
178 Integer i;
179 algorithm
180 ✗ for c in inChars loop
181 ✗ i := stringCharInt(c);
182 ✗ if (i == 10) or (i == 13) then return; end if;
183 ✗ outCharsTillEnd := outCharsTillEnd + (if i == 9 then TabSpaces else 1); // \t counts as 4 spaces
184 end for;
185 end charsTillEndOfLine;
186
187
188 public function makeStartLineInfo
189 input list<String> inChars;
190 input String inFileName;
191 output LineInfo outLineInfo;
192 protected
193 Integer llen;
194 algorithm
195 ✗ llen := charsTillEndOfLine(inChars, 1);
196 ✗ outLineInfo := LINE_INFO(PARSE_INFO(inFileName,{}, false), 1, llen, inChars);
197 end makeStartLineInfo;
198
199 public function printAndFailIfError
200 input LineInfo inLineInfo;
201 algorithm
202 () := match inLineInfo
203 local
204 list<String> errLst;
205
206 case LINE_INFO(parseInfo = PARSE_INFO(errors = {}))
207 algorithm
208 ✗ print("\nSusan parsing successful.\n");
209 then ();
210
211 case LINE_INFO(parseInfo = PARSE_INFO(errors = errLst as (_::_)))
212 algorithm
213 ✗ print("\nSusan parse error(s):\n");
214 ✗ print(stringDelimitList(listReverse(errLst), "\n"));
215 ✗ print("\n");
216 ✗ then fail();
217
218 end match;
219 end printAndFailIfError;
220
221 public function parseError
222 input list<String> inChars;
223 input LineInfo inLineInfo;
224 input String inErrMessage;
225 input Boolean isFatal;
226
227 output LineInfo outLineInfo;
228 algorithm
229 outLineInfo := matchcontinue (inChars, inLineInfo, inErrMessage, isFatal)
230 local
231 list<String> chars, solchars, errLst;
232 LineInfo linfo;
233 String fname, errMsg, locStr;
234 Integer lnum, llen, colnum;
235 Boolean isfatal;
236
237 case (chars, linfo as LINE_INFO( parseInfo = PARSE_INFO(fileName = fname, errors = errLst, wasFatalError = false),
238 lineNumber = lnum, lineLength = llen, startOfLineChars = solchars
239 ), errMsg, isfatal)
240 algorithm
241 ✗ (_, colnum) := getPosition(chars, linfo);
242 ✗ locStr := intString(lnum) + "." + intString(colnum);
243 ✗ errMsg := fname + ":" + locStr + "-" + locStr + " Error:(parser)" + errMsg + "(col "+intString(colnum)+ ")"; //TplParser.mo:126.38-126.55 Error:
244 ✗ if Flags.isSet(Flags.FAILTRACE) then
245 ✗ Debug.traceln("TplParser.parseError msg: " + errMsg);
246 end if;
247 ✗ then (LINE_INFO(PARSE_INFO(fname, errMsg :: errLst, isfatal), lnum,llen, solchars));
248
249 case (_, linfo as LINE_INFO( parseInfo = PARSE_INFO(wasFatalError = true)), _, _)
250 then (linfo);
251
252 else
253 algorithm
254 ✗ true := Flags.isSet(Flags.FAILTRACE);
255 ✗ Debug.trace("- !!! TplParser.parseError failed.\n");
256 ✗ then fail();
257
258 end matchcontinue;
259 end parseError;
260
261
262 public function parseErrorPrevPosition
263 input list<String> inCharsPrevPos;
264 input LineInfo inLineInfoPrevPos;
265 input LineInfo inLineInfo;
266 input String inErrMessage;
267 input Boolean isFatal;
268
269 output LineInfo outLineInfo;
270 algorithm
271 outLineInfo := matchcontinue (inCharsPrevPos, inLineInfoPrevPos, inLineInfo, inErrMessage, isFatal)
272 local
273 list<String> charspp, solchars, solcharspp;
274 LineInfo linfopp;
275 String errMsg;
276 Integer lnum, llen, lnumpp, llenpp;
277 Boolean isfatal;
278 ParseInfo pinfo;
279
280 case (charspp,
281 LINE_INFO( lineNumber = lnumpp,
282 lineLength = llenpp,
283 startOfLineChars = solcharspp
284 ),
285 LINE_INFO( parseInfo = pinfo,
286 lineNumber = lnum,
287 lineLength = llen,
288 startOfLineChars = solchars
289 ),
290 errMsg, isfatal)
291 algorithm
292 ✗ linfopp := LINE_INFO(pinfo, lnumpp, llenpp, solcharspp);
293 ✗ LINE_INFO(parseInfo = pinfo) := parseError(charspp, linfopp, errMsg, isfatal);
294 ✗ then LINE_INFO(pinfo, lnum, llen,solchars);
295
296 else
297 algorithm
298 ✗ true := Flags.isSet(Flags.FAILTRACE);
299 ✗ Debug.trace("- !!! TplParser.parseErrorPrevPosition failed.\n");
300 ✗ then fail();
301
302 end matchcontinue;
303 end parseErrorPrevPosition;
304
305 public function wasFatalError
306 input LineInfo inLineInfo;
307 output Boolean outWasError;
308 algorithm
309 outWasError := match inLineInfo
310 case LINE_INFO( parseInfo = PARSE_INFO(wasFatalError = true))
311 then true;
312
313 else false;
314 end match;
315 end wasFatalError;
316
317 public function mergeErrors
318 input LineInfo inLineInfo;
319 input LineInfo inLineInfoToAddErrorsFrom;
320 output LineInfo outLineInfo;
321 algorithm
322 outLineInfo := match (inLineInfo, inLineInfoToAddErrorsFrom)
323 local
324 list<String> solchars, errLst, errLstToAdd;
325 String fname;
326 Integer lnum, llen;
327 Boolean wasFatalError;
328
329 case (LINE_INFO( parseInfo = PARSE_INFO(fileName = fname, errors = errLst, wasFatalError = wasFatalError),
330 lineNumber = lnum, lineLength = llen, startOfLineChars = solchars
331 ),
332 LINE_INFO(parseInfo = PARSE_INFO(errors = errLstToAdd ) ))
333 algorithm
334 ✗ errLst := listAppend(errLstToAdd, errLst); //error lists are in reversed order
335 //let the fatal error state from the first, leading file, only add errors from the other file
336 //wasFatalError = wasFatalError or wasFatalErrorToAdd;
337 ✗ then (LINE_INFO(PARSE_INFO(fname, errLst, wasFatalError), lnum, llen, solchars));
338
339 else
340 algorithm
341 ✗ true := Flags.isSet(Flags.FAILTRACE);
342 ✗ Debug.trace("- !!! TplParser.mergeErrors failed.\n");
343 ✗ then fail();
344
345 end match;
346 end mergeErrors;
347
348
349 public function parseErrorPrevPositionOpt
350 input list<String> inCharsPrevPos;
351 input LineInfo inLineInfoPrevPos;
352 input LineInfo inLineInfo;
353 input Option<String> inErrMessage;
354 input Boolean isFatal;
355
356 output LineInfo outLineInfo;
357 algorithm
358 outLineInfo := matchcontinue (inCharsPrevPos, inLineInfoPrevPos, inLineInfo, inErrMessage, isFatal)
359 local
360 list<String> charspp;
361 LineInfo linfo, linfopp;
362 String errMsg;
363 Boolean isfatal;
364
365
366 case (_, _, linfo,NONE(), _)
367 then (linfo);
368
369 case (charspp, linfopp, linfo, SOME(errMsg), isfatal)
370 algorithm
371 ✗ linfo := parseErrorPrevPosition(charspp, linfopp, linfo, errMsg, isfatal);
372 then (linfo);
373
374 else
375 algorithm
376 ✗ true := Flags.isSet(Flags.FAILTRACE);
377 ✗ Debug.trace("- !!! TplParser.parseErrorPrevPositionOpt failed.\n");
378 ✗ then fail();
379
380 end matchcontinue;
381 end parseErrorPrevPositionOpt;
382
383 public function parseErrorPrevPositionOptInfoChars
384 input LineInfo inLineInfoPrevPos;
385 input LineInfo inLineInfo;
386 input Option<String> inErrMessage;
387 input Boolean isFatal;
388 output LineInfo outLineInfo;
389 protected
390 list<String> sol_chars;
391 algorithm
392 ✗ LINE_INFO(startOfLineChars = sol_chars) := inLineInfoPrevPos;
393 ✗ outLineInfo := parseErrorPrevPositionOpt(sol_chars, inLineInfoPrevPos,
394 inLineInfo, inErrMessage, isFatal);
395 end parseErrorPrevPositionOptInfoChars;
396
397 public function expectChar
398 input output list<String> chars;
399 input output LineInfo lineInfo;
400 input String inExpectedChar;
401 algorithm
402 chars := match chars
403 local
404 list<String> rest;
405 String c;
406
407 case c :: rest
408 guard stringEq(c, inExpectedChar)
409 then rest;
410
411 case _
412 algorithm
413 // false = stringEq(c, ec));
414 // or chars = {}
415 ✗ lineInfo := parseError(chars, lineInfo, "Expected character '" + inExpectedChar + "' at the position.", false);
416 //fprint(Flags.FAILTRACE, "???Expected character '" + ec + "'\n");
417 then chars;
418 end match;
419 end expectChar;
420
421 //intended to say error before the last interleave, but need
422 //TODO: remember the last position before interleave in the LINE_INFO
423 public function interleaveExpectChar
424 input list<String> inChars;
425 input LineInfo inLineInfo;
426 input String inExpectedChar;
427
428 output list<String> outChars;
429 output LineInfo outLineInfo;
430 algorithm
431 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo, inExpectedChar)
432 local
433 list<String> chars;
434 LineInfo linfo;
435 String ec, c;
436
437 case (chars, linfo, ec)
438 algorithm
439 ✗ (chars, linfo) := interleave(chars, linfo);
440 ✗ c :: chars := chars;
441 ✗ true := stringEq(c, ec);
442 ✗ then (chars, linfo);
443
444 case (chars, linfo, ec)
445 algorithm
446 // false = stringEq( c, ec );
447 // or chars = {}
448 ✗ linfo := parseError(chars, linfo, "Expected character '" + ec + "' after the position.",false);
449 then (chars, linfo);
450
451 else
452 algorithm
453 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("- !!! TplParser.interleaveExpectChar failed.\n");
454 ✗ then fail();
455
456 end matchcontinue;
457 end interleaveExpectChar;
458
459
460 public function takeKeywordChars
461 input list<String> inChars;
462 input list<String> inKeywordChars;
463
464 output list<String> outChars;
465 algorithm
466 outChars := match (inChars, inKeywordChars)
467 local
468 list<String> chars, kwchars;
469 String c, kwc;
470
471 case (c :: chars, kwc :: kwchars)
472 algorithm
473 ✗ true := stringEq(c, kwc);
474 ✗ then takeKeywordChars(chars, kwchars);
475
476 case (chars, {})
477 then (chars);
478
479 end match;
480 end takeKeywordChars;
481
482 public function isKeyword
483 input list<String> inChars;
484 input list<String> inKeywordChars;
485
486 output list<String> outChars;
487 output Boolean isKeyword;
488 algorithm
489 (outChars, isKeyword) := matchcontinue (inChars, inKeywordChars)
490 local
491 list<String> chars, kwchars;
492
493 case (chars, kwchars)
494 algorithm
495 ✗ chars := takeKeywordChars(chars, kwchars);
496 ✗ afterKeyword(chars);
497 then (chars, true);
498
499 else (inChars, false);
500
501 end matchcontinue;
502 end isKeyword;
503
504
505 public function interleaveExpectKeyWord
506 input list<String> inChars;
507 input LineInfo inLineInfo;
508 input list<String> inKeywordChars;
509 input Boolean isFatal;
510
511 output list<String> outChars;
512 output LineInfo outLineInfo;
513 algorithm
514 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo, inKeywordChars, isFatal)
515 local
516 list<String> chars, kwchars;
517 LineInfo linfo;
518 String kw;
519 Boolean isfatal;
520
521 case (chars, linfo, kwchars, _)
522 algorithm
523 ✗ (chars, linfo) := interleave(chars, linfo);
524 ✗ (chars, true) := isKeyword(chars, kwchars);
525 ✗ then (chars, linfo);
526
527 case (chars, linfo, kwchars, isfatal)
528 algorithm
529 ✗ (chars, linfo) := interleave(chars, linfo);
530 ✗ (_, false) := isKeyword(chars, kwchars);
531 ✗ kw := stringCharListString(kwchars);
532 ✗ linfo := parseError(chars, linfo, "Expected keyword '" + kw + "' at the position.", isfatal);
533 then (chars, linfo);
534
535 else
536 algorithm
537 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("- !!! TplParser.interleaveExpectKeyWord failed.\n");
538 ✗ then fail();
539
540 end matchcontinue;
541 end interleaveExpectKeyWord;
542
543 public function interleaveExpectEndOfFile
544 input list<String> inChars;
545 input LineInfo inLineInfo;
546
547 output list<String> outChars;
548 output LineInfo outLineInfo;
549 algorithm
550 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo)
551 local
552 list<String> chars;
553 LineInfo linfo;
554
555 case (chars, linfo)
556 algorithm
557 ✗ ({}, linfo) := interleave(chars, linfo);
558 then ({}, linfo);
559
560 case (chars, linfo)
561 algorithm
562 ✗ (chars, linfo) := interleave(chars, linfo);
563 ✗ linfo := parseError(chars, linfo, "Expected end of file at the position.", false);
564 then (chars, linfo);
565
566 else
567 algorithm
568 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("- !!! TplParser.interleaveExpectEndOfFile failed.\n");
569 ✗ then fail();
570
571 end matchcontinue;
572 end interleaveExpectEndOfFile;
573
574
575 public function openFile
576 input String inFile;
577
578 output list<String> outChars;
579 output LineInfo outLineInfo;
580 output Option<String> outErrorOpt;
581 algorithm
582 (outChars, outLineInfo, outErrorOpt) := matchcontinue inFile
583 local
584 String file, src, errStr;
585 list<String> chars;
586 LineInfo linfo;
587
588 case file
589 algorithm
590 ✗ true := System.regularFileExists(file);
591 ✗ src := System.readFile(file);
592 ✗ chars := stringListStringChar( src );
593 ✗ linfo := makeStartLineInfo(chars, file);
594 then (chars, linfo,NONE());
595
596 case file
597 algorithm
598 ✗ false := System.regularFileExists(file);
599 chars := {};
600 ✗ linfo := makeStartLineInfo(chars, file);
601 ✗ errStr := "No such file '" + file + "'.";
602 then (chars, linfo, SOME(errStr));
603
604 else
605 algorithm
606 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse error - TplParser.openFile failed for file '" + inFile + "'.\n");
607 ✗ then fail();
608
609 end matchcontinue;
610 end openFile;
611
612
613 public function templPackageFromFile
614 input String inFile;
615 output TplAbsyn.TemplPackage outTemplPackage;
616 algorithm
617 outTemplPackage := matchcontinue inFile
618 local
619 String file;
620 Option<String> errOpt;
621 list<String> chars;
622 LineInfo linfo;
623 TplAbsyn.TemplPackage tplPackage;
624 case file
625 algorithm
626 ✗ (chars, linfo, errOpt) := openFile(file);
627 ✗ linfo := parseErrorPrevPositionOpt(chars, linfo, linfo, errOpt, true);
628 ✗ (chars, linfo, tplPackage) := templPackage(chars, linfo, CacheTree.Tree.EMPTY());
629 ✗ (_, linfo) := interleaveExpectEndOfFile(chars, linfo);
630 ✗ printAndFailIfError(linfo);
631 ✗ then tplPackage;
632
633 else
634 algorithm
635 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse error - TplParser.templPackageFromFile failed for file '" + inFile + "'.\n");
636 ✗ then fail();
637
638 end matchcontinue;
639 end templPackageFromFile;
640
641
642 protected function typeviewDefsFromInterfaceFile
643 input TplAbsyn.PathIdent interfaceName;
644 input output list<TplAbsyn.ASTDef> astDefs;
645 output LineInfo linfo;
646 output Option<String> errOpt;
647 input output CacheTree.Tree cachedDefs;
648 protected
649 String file, dir;
650 list<String> chars;
651 list<TplAbsyn.ASTDef> newAstDefs;
652 algorithm
653 ✗ file := TplAbsyn.pathIdentString(interfaceName) + ".mo";
654 ✗ dir := Flags.getConfigString(Flags.TPL_INTERFACE_DIR);
655 ✗ if dir <> "" and System.regularFileExists(dir + "/" + file) then
656 ✗ file := dir + "/" + file;
657 end if;
658 try
659 ✗ if CacheTree.hasKey(cachedDefs, file) then
660 // Return cached result, because it's very slow if we don't...
661 ✗ astDefs := listAppend(CacheTree.get(cachedDefs, file), astDefs);
662 ✗ linfo := LINE_INFO(PARSE_INFO("cachedResult",{},false),0,0,{});
663 ✗ errOpt := NONE();
664 ✗ return;
665 end if;
666 ✗ (chars, linfo, errOpt) := openFile(file);
667 ✗ (chars, linfo) := interleave(chars, linfo);
668 ✗ (chars, linfo,_, newAstDefs) := interfacePackage(chars, linfo, {});
669 ✗ (_, linfo) := interleaveExpectEndOfFile(chars, linfo);
670 ✗ if Flags.isSet(Flags.FAILTRACE) then
671 ✗ Debug.trace("Loaded interface file: "+file+"\n");
672 end if;
673 ✗ cachedDefs := CacheTree.add(cachedDefs, file, newAstDefs);
674 ✗ astDefs := listAppend(newAstDefs, astDefs);
675 else
676 ✗ if Flags.isSet(Flags.FAILTRACE) then
677 ✗ Debug.trace("Parse error - TplParser.typeviewDefsFromInterfaceFile "+file+" failed.\n");
678 end if;
679 ✗ fail();
680 end try;
681 end typeviewDefsFromInterfaceFile;
682
683
684 protected function typeviewDefsFromTemplateFile
685 input TplAbsyn.PathIdent packageName;
686 input Boolean isUnqualifiedImport;
687 input output list<TplAbsyn.ASTDef> astDefs;
688 output LineInfo linfo;
689 output Option<String> errOpt;
690 input output CacheTree.Tree cachedDefs;
691 protected
692 String file;
693 list<String> chars;
694 TplAbsyn.ASTDef newAstDef;
695 TplAbsyn.TemplPackage tplPackage;
696 list<tuple<TplAbsyn.Ident,TplAbsyn.TemplateDef>> templateDefs;
697 list<tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo>> astTypes;
698 algorithm
699 ✗ file := TplAbsyn.pathIdentString(packageName) + ".tpl";
700 try
701 ✗ if CacheTree.hasKey(cachedDefs, file) then
702 // We cache everything. But we need to pass isUnqualifiedImport=true|false...
703 ✗ {TplAbsyn.AST_DEF(types = astTypes)} := CacheTree.get(cachedDefs, file);
704 ✗ astDefs := TplAbsyn.AST_DEF(packageName, isUnqualifiedImport, false, astTypes)::astDefs;
705 ✗ linfo := LINE_INFO(PARSE_INFO("cachedResult",{},false),0,0,{});
706 ✗ errOpt := NONE();
707 ✗ return;
708 end if;
709 ✗ (chars, linfo, errOpt) := openFile(file);
710 ✗ (chars, linfo, tplPackage, cachedDefs) := templPackage(chars, linfo, cachedDefs);
711 ✗ (_, linfo) := interleaveExpectEndOfFile(chars, linfo);
712 ✗ TplAbsyn.TEMPL_PACKAGE(templateDefs = templateDefs)
713 := TplAbsyn.fullyQualifyTemplatePackage(tplPackage);
714 ✗ astTypes := List.map(templateDefs, templateDefToAstDefType);
715 ✗ newAstDef := TplAbsyn.AST_DEF(packageName, isUnqualifiedImport, false, astTypes);
716 ✗ cachedDefs := CacheTree.add(cachedDefs, file, newAstDef::{});
717 ✗ astDefs := newAstDef :: astDefs;
718 ✗ if Flags.isSet(Flags.FAILTRACE) then
719 ✗ Debug.trace("Loaded typeview from template file: "+file+"\n");
720 end if;
721 else
722 ✗ if Flags.isSet(Flags.FAILTRACE) then
723 ✗ Debug.trace("Parse error - TplParser.typeviewDefsFromInterfaceFile "+file+" failed.\n");
724 end if;
725 ✗ fail();
726 end try;
727 end typeviewDefsFromTemplateFile;
728
729
730 public function templateDefToAstDefType
731 input tuple<TplAbsyn.Ident,TplAbsyn.TemplateDef> inTemplateDef;
732 output tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo> outType;
733 algorithm
734 outType := matchcontinue inTemplateDef
735 local
736 TplAbsyn.Ident id;
737 TplAbsyn.TypeSignature litType;
738 TplAbsyn.TypedIdents iargs, oargs;
739 case (id, TplAbsyn.STR_TOKEN_DEF())
740 ✗ then ( (id, TplAbsyn.TI_CONST_TYPE(TplAbsyn.STRING_TOKEN_TYPE())) );
741
742 case (id, TplAbsyn.LITERAL_DEF(litType = litType))
743 ✗ then ( (id, TplAbsyn.TI_CONST_TYPE(litType)) );
744
745 case (id, TplAbsyn.TEMPLATE_DEF(args = iargs))
746 algorithm
747 iargs := TplAbsyn.imlicitTxtArg :: iargs;
748 ✗ oargs := List.filterOnTrue(iargs, TplAbsyn.isText);
749 ✗ then ( (id, TplAbsyn.TI_FUN_TYPE(iargs,oargs,{})) );
750
751 else
752 algorithm
753 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse error - TplParser.templateDefToAstDefType failed.\n");
754 ✗ then fail();
755
756 end matchcontinue;
757 end templateDefToAstDefType;
758
759 /*
760 newLine:
761 \r \n //CR + LF ... Windows
762 |
763 \n //CR only ... Linux
764 |
765 \r //LF only ... Mac OS up to 9
766 */
767 public function newLine
768 input list<String> inChars;
769 input LineInfo inLineInfo;
770
771 output list<String> outChars;
772 output LineInfo outLineInfo;
773 algorithm
774 (outChars, outLineInfo) := match(inChars, inLineInfo)
775 local
776 list<String> chars;
777 ParseInfo pinfo;
778 String c;
779 Integer lnum, llen, i;
780
781 // CR + LF .. Windows
782 // LF only ... Linux
783 // or CR only - Mac OS up to 9
784 case (c :: chars, LINE_INFO(parseInfo = pinfo, lineNumber = lnum))
785 algorithm
786 ✗ i := stringCharInt(c);
787 ✗ if i == 13
788 then
789 chars := match chars
790 case "\n" :: chars then chars; // \n
791 else chars;
792 end match;
793 end if;
794 ✗ true := (i == 10) or (i == 13); // \n or \r
795 ✗ llen := charsTillEndOfLine(chars, 1); // 1 is colum number of the first character, so count it
796 ✗ lnum := lnum + 1;
797 ✗ then (chars, LINE_INFO(pinfo, lnum, llen, chars));
798
799 end match;
800 end newLine;
801
802 /*
803 // interleave will be applied before every token
804 interleave: //i.e. space / comment
805 [' '\n\r\t] interleave
806 |
807 '//' toEndOfLine interleave
808 |
809 '/''*' comment interleave
810 |
811 _ //just nothing
812 */
813 public function interleave
814 input list<String> inChars;
815 input LineInfo inLineInfo;
816
817 output list<String> outChars;
818 output LineInfo outLineInfo;
819 algorithm
820 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo)
821 local
822 list<String> chars, charsRest;
823 LineInfo linfo;
824 case (" " :: chars, linfo)
825 algorithm
826 ✗ (chars, linfo) := interleave(chars, linfo);
827 then (chars, linfo);
828 case ("\t" :: chars, linfo)
829 algorithm
830 ✗ (chars, linfo) := interleave(chars, linfo);
831 then (chars, linfo);
832 case ("/" :: "/" :: chars, linfo)
833 algorithm
834 ✗ (chars, linfo) := toEndOfLine(chars, linfo);
835 ✗ (chars, linfo) := interleave(chars, linfo);
836 then (chars, linfo);
837 case ("/" :: "*" :: chars, linfo)
838 algorithm
839 ✗ (chars, linfo) := comment(chars, linfo);
840 ✗ (chars, linfo) := interleave(chars, linfo);
841 then (chars, linfo);
842
843 case (chars as ("/" :: "*" :: charsRest), linfo)
844 algorithm
845 ✗ failure(comment(charsRest, linfo));
846 ✗ linfo := parseError(chars, linfo, "Unmatched /* */ comment - reached end of file.", true);
847 ✗ then ({}, linfo);
848
849
850 case (chars, linfo)
851 algorithm
852 ✗ (chars, linfo) := newLine(chars, linfo);
853 ✗ (chars, linfo) := interleave(chars, linfo);
854 then (chars, linfo);
855
856 ✗ else (inChars, inLineInfo);
857
858 end matchcontinue;
859 end interleave;
860
861
862
863 /*
864 toEndOfLine:
865 \n
866 |
867 eof //end of stream ~ {}
868 |
869 any toEndOfLine //any is any character
870 */
871 public function toEndOfLine
872 input list<String> inChars;
873 input LineInfo inLineInfo;
874 output list<String> outChars;
875 output LineInfo outLineInfo;
876 algorithm
877 (outChars, outLineInfo) := matchcontinue(inChars, inLineInfo)
878 local
879 list<String> chars;
880 LineInfo linfo;
881 case (chars, linfo)
882 algorithm
883 ✗ (chars, linfo) := newLine(chars, linfo);
884 then (chars, linfo);
885 case (_ :: chars, linfo)
886 algorithm
887 ✗ (chars, linfo) := toEndOfLine(chars, linfo);
888 then (chars, linfo);
889 ✗ case ({}, linfo) then ({},linfo);
890 end matchcontinue;
891 end toEndOfLine;
892
893
894 //comment:
895 // '*''/'
896 // |
897 // '/''*' comment comment //nesting is possible
898 // |
899 // any comment
900
901 public function comment
902 input list<String> inChars;
903 input LineInfo inLineInfo;
904 output list<String> outChars;
905 output LineInfo outLineInfo;
906 algorithm
907 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo)
908 local
909 list<String> chars, charsRest;
910 LineInfo linfo;
911 ✗ case ("*" :: "/" :: chars, linfo) then (chars, linfo);
912 case ("/" :: "*" :: chars, linfo)
913 algorithm
914 ✗ (chars, linfo) := comment(chars,linfo);
915 ✗ (chars, linfo) := comment(chars,linfo);
916 then (chars, linfo);
917 case (chars, linfo)
918 algorithm
919 ✗ (chars, linfo) := newLine(chars, linfo);
920 ✗ (chars, linfo) := comment(chars,linfo);
921 then (chars, linfo);
922 case (chars as (_ :: charsRest), linfo)
923 algorithm
924 ✗ failure(newLine(chars, linfo));
925 ✗ (chars, linfo) := comment(charsRest,linfo);
926 then (chars, linfo);
927
928 //case ({}, linfo)
929 // equation
930 // true = Flags.isSet(Flags.FAILTRACE); Debug.trace("!!Parse error - TplParser.comment - unmatched /* */ comment - reached end of file.\n");
931 // then fail(); //({}, linfo);
932 end matchcontinue;
933 end comment;
934
935 /*
936 //afterKeyword must not fail after every keyword to be considered as keyword
937 afterKeyword:
938 [_0-9A-Za-z] => fail // if it can be an identifier/other keyword
939 |
940 _ => ()
941 */
942
943 public function afterKeyword
944 input list<String> inChars;
945 algorithm
946 () := match inChars
947 local
948 String c;
949 Integer i;
950
951 case c :: _
952 algorithm
953 ✗ i := stringCharInt(c);
954 //[_0-9A-Za-z]
955 ✗ false := (i == 95/*_*/)
956 or ( 48/*0*/ <= i and i <= 57/*9*/)
957 or ( 65/*A*/ <= i and i <= 90/*Z*/)
958 or ( 97/*a*/ <= i and i <= 122/*z*/);
959 then ();
960
961 case {} then ();
962
963 end match;
964 end afterKeyword;
965
966
967 /*
968 identifier:
969 [_A-Za-z]:c identifier_rest:rest => stringCharListString(c::rest)
970 */
971
972 protected constant list<String> keywords =
973 { "end","if","then","else","match","case","equation","equality","failure","algorithm","input","output","matchcontinue","local","constant","extends","external","for","function","import","package","partial","protected","public","record","as","uniontype","subtypeof"};
974
975 public function identifier
976 input list<String> inChars;
977
978 output list<String> outChars;
979 output TplAbsyn.Ident outIdent;
980 algorithm
981 (outChars, outIdent) := match inChars
982 local
983 list<String> chars, restIdChars;
984 String c, ident;
985 Integer i;
986
987 case c :: chars
988 algorithm
989 ✗ i := stringCharInt(c);
990 //[_A-Za-z]
991 ✗ true := (i == 95/*_*/)
992 or ( 65/*A*/ <= i and i <= 90/*Z*/)
993 or ( 97/*a*/ <= i and i <= 122/*z*/);
994 ✗ (chars, restIdChars) := identifier_rest(chars);
995 ✗ ident := stringCharListString(c :: restIdChars);
996 //false = listMember(ident, keywords);
997 then (chars, ident);
998
999 end match;
1000 end identifier;
1001
1002 /*
1003 identifier_rest:
1004 [_0-9A-Za-z]:c identifier_rest:rest => c::rest
1005 |
1006 _ => {}
1007 */
1008 public function identifier_rest
1009 input list<String> inChars;
1010
1011 output list<String> outChars;
1012 output list<String> outRestIdentChars;
1013 algorithm
1014 (outChars, outRestIdentChars) := match inChars
1015 local
1016 list<String> chars, restIdChars;
1017 String c;
1018 Integer i;
1019
1020 case c :: chars
1021 algorithm
1022 ✗ i := stringCharInt(c);
1023 //[_0-9A-Za-z]
1024 ✗ if (i == 95/*_*/)
1025 or ( 48/*0*/ <= i and i <= 57/*9*/)
1026 or ( 65/*A*/ <= i and i <= 90/*Z*/)
1027 or ( 97/*a*/ <= i and i <= 122/*z*/)
1028 then
1029 ✗ (chars, restIdChars) := identifier_rest(chars);
1030 ✗ restIdChars := c :: restIdChars;
1031 else
1032 chars := inChars;
1033 ✗ restIdChars := {};
1034 end if;
1035 ✗ then (chars, restIdChars);
1036
1037 end match;
1038 end identifier_rest;
1039
1040 /*
1041 pathIdent:
1042 identifier:head pathIdentPath(head):pid => pid
1043 */
1044 public function pathIdent
1045 input list<String> inChars;
1046 input LineInfo inLineInfo;
1047
1048 output list<String> outChars;
1049 output LineInfo outLineInfo;
1050 output TplAbsyn.PathIdent outPathIdent;
1051 algorithm
1052 (outChars, outLineInfo, outPathIdent) := match (inChars, inLineInfo)
1053 local
1054 list<String> chars;
1055 LineInfo linfo;
1056 String head;
1057 TplAbsyn.PathIdent pid;
1058
1059 case (chars, linfo)
1060 algorithm
1061 ✗ (chars, head) := identifier(chars);
1062 ✗ (chars, linfo) := interleave(chars, linfo);
1063 ✗ (chars, linfo, pid) := pathIdentPath(chars, linfo, head);
1064 then (chars, linfo, pid);
1065
1066 end match;
1067 end pathIdent;
1068
1069
1070 /*
1071 pathIdentPath(head):
1072 '.' pathIdent:path => PATH_IDENT(head, path)
1073 |
1074 '.' error "expecting identifier after dot."
1075 => PATH_IDENT(head, TplAbsyn.IDENT("#error#"))
1076 |
1077 _ => IDENT(head)
1078 */
1079 public function pathIdentPath
1080 input list<String> inChars;
1081 input LineInfo inLineInfo;
1082 input TplAbsyn.Ident inHeadIdent;
1083
1084 output list<String> outChars;
1085 output LineInfo outLineInfo;
1086 output TplAbsyn.PathIdent outPathIdent;
1087 algorithm
1088 (outChars, outLineInfo, outPathIdent) := matchcontinue (inChars, inLineInfo,inHeadIdent)
1089 local
1090 list<String> chars;
1091 LineInfo linfo;
1092 String head;
1093 TplAbsyn.PathIdent pid;
1094
1095 case ("." :: chars, linfo, head)
1096 algorithm
1097 ✗ (chars, linfo) := interleave(chars, linfo);
1098 ✗ (chars, linfo, pid) := pathIdent(chars, linfo);
1099 ✗ then (chars, linfo, TplAbsyn.PATH_IDENT(head, pid));
1100
1101 // can be followed by .*, for example
1102 //case ("." :: chars, linfo, head)
1103 // equation
1104 // (chars, linfo) = interleave(chars, linfo);
1105 // failure( (_, _, _) = pathIdent(chars, linfo));
1106 // (linfo) = parseError(chars, linfo, "Expected an identifier after '.' at the position.", true);
1107 // then (chars, linfo, TplAbsyn.PATH_IDENT(head, TplAbsyn.IDENT("#error#")));
1108
1109
1110 ✗ else (inChars, inLineInfo, TplAbsyn.IDENT(inHeadIdent));
1111
1112 end matchcontinue;
1113 end pathIdentPath;
1114
1115
1116 public function identifierNoOpt
1117 input list<String> inChars;
1118 input LineInfo inLineInfo;
1119
1120 output list<String> outChars;
1121 output LineInfo outLineInfo;
1122 output TplAbsyn.Ident outIdent;
1123 algorithm
1124 (outChars, outLineInfo, outIdent) := matchcontinue (inChars, inLineInfo)
1125 local
1126 list<String> chars;
1127 String ident;
1128 LineInfo linfo;
1129
1130 case (chars, linfo)
1131 algorithm
1132 ✗ (chars, ident) := identifier(chars);
1133 ✗ then (chars, linfo, ident);
1134
1135 case (chars, linfo)
1136 algorithm
1137 ✗ failure(identifier(chars));
1138 ✗ linfo := parseError(chars, linfo, "Expected an identifier at the position.", true);
1139 ✗ then (chars, linfo, "#error#");
1140
1141 end matchcontinue;
1142 end identifierNoOpt;
1143
1144
1145 public function pathIdentNoOpt
1146 input list<String> inChars;
1147 input LineInfo inLineInfo;
1148
1149 output list<String> outChars;
1150 output LineInfo outLineInfo;
1151 output TplAbsyn.PathIdent outPathIdent;
1152 algorithm
1153 (outChars, outLineInfo, outPathIdent) := match (inChars, inLineInfo)
1154 local
1155 list<String> chars;
1156 LineInfo linfo;
1157 String head;
1158 TplAbsyn.PathIdent pid;
1159
1160 case (chars, linfo)
1161 algorithm
1162 ✗ (chars, linfo, head) := identifierNoOpt(chars, linfo);
1163 ✗ (chars, linfo) := interleave(chars, linfo);
1164 ✗ (chars, linfo, pid) := pathIdentPath(chars, linfo, head);
1165 then (chars, linfo, pid);
1166
1167 end match;
1168 end pathIdentNoOpt;
1169
1170 /*
1171 templPackage:
1172 'package' pathIdent:pid stringComment
1173 definitions(pid,{},{}):(astDefs,templDefs)
1174 endDefPathIdent(pid)
1175 => TEMPL_PACKAGE(pid, astDefs,templDefs)
1176 */
1177 public function templPackage
1178 input list<String> inChars;
1179 input LineInfo inLineInfo;
1180
1181 output list<String> outChars;
1182 output LineInfo outLineInfo;
1183 output TplAbsyn.TemplPackage outTemplPackage;
1184 input output CacheTree.Tree cachedDefs;
1185 algorithm
1186 (outChars, outLineInfo, outTemplPackage) := matchcontinue (inChars, inLineInfo)
1187 local
1188 list<String> chars;
1189 LineInfo linfo;
1190 TplAbsyn.PathIdent pid;
1191 list<TplAbsyn.ASTDef> astDefs;
1192 list<tuple<TplAbsyn.Ident, TplAbsyn.TemplateDef>> templDefs;
1193 String annotationFooter;
1194
1195 case (chars, linfo)
1196 algorithm
1197 ✗ (chars, linfo) := interleaveExpectKeyWord(chars, linfo, {"p","a","c","k","a","g","e"}, true);
1198 ✗ (chars, linfo) := interleave(chars, linfo);
1199 ✗ (chars, linfo, pid) := pathIdentNoOpt(chars, linfo);
1200 ✗ (chars, linfo) := interleave(chars, linfo);
1201 ✗ (chars, linfo) := stringComment(chars, linfo);
1202 ✗ (chars, linfo) := interleave(chars, linfo);
1203 ✗ (chars, linfo, astDefs,templDefs,cachedDefs) := definitions(chars, linfo,{},{},cachedDefs);
1204 ✗ astDefs := listReverse(astDefs);
1205 ✗ templDefs := listReverse(templDefs);
1206 ✗ (chars, linfo) := interleave(chars, linfo);
1207 ✗ (chars, linfo, annotationFooter) := annotationFooter(chars, linfo);
1208 ✗ (chars, linfo) := interleave(chars, linfo);
1209 ✗ (chars, linfo) := endDefPathIdent(chars, linfo,pid);
1210 ✗ then (chars, linfo, TplAbsyn.TEMPL_PACKAGE(pid, astDefs, templDefs, annotationFooter));
1211
1212 else
1213 algorithm
1214 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!!Parse error - TplParser.templPackage failed.\n");
1215 ✗ then fail();
1216
1217 end matchcontinue;
1218 end templPackage;
1219
1220 /*
1221 definitions(astDefs,templDefs):
1222 'import' 'interface' pathIdent:pid stringComment ';'
1223 { ads = typeviewDefsFromInterfaceFile(packageNameToFileName(pid,".mo"), astDefs) }
1224 definitions(ads, templDefs):(ads,tds)
1225 => (ads,tds)
1226 |
1227 'import' pathIdent:pid unqualImportPostfix:unq stringComment ';'
1228 { ads = typeviewDefsFromTemplateFile(pid, unq, astDefs) }
1229 definitions(ads, templDefs):(ads,tds)
1230 => (ads,tds)
1231 // |
1232 // absynDef:ad definitions(ad::astDefs,templDefs):(ads,tds) => (ads,tds)
1233 |
1234 templDef:(name, td) definitions(astDefs,(name,td)::templDefs):(ads,tds) => (ads,tds)
1235 // |
1236 // error "Expecting 'end' | ['public' | 'protected' ] 'package' definition | template definition starting with an identifier."
1237 */
1238 public function definitions
1239 input list<String> inChars;
1240 input LineInfo inLineInfo;
1241 input list<TplAbsyn.ASTDef> inAccASTDefs;
1242 input list<tuple<TplAbsyn.Ident, TplAbsyn.TemplateDef>> inAccTemplDefs;
1243
1244 output list<String> outChars;
1245 output LineInfo outLineInfo;
1246 output list<TplAbsyn.ASTDef> outASTDefs;
1247 output list<tuple<TplAbsyn.Ident, TplAbsyn.TemplateDef>> outTemplDefs;
1248 input output CacheTree.Tree cachedDefs;
1249 algorithm
1250 (outChars, outLineInfo, outASTDefs, outTemplDefs) := matchcontinue (inChars, inLineInfo, inAccASTDefs, inAccTemplDefs)
1251 local
1252 list<String> chars, startChars;
1253 Option<String> errOptTV;
1254 LineInfo linfo, startLinfo, linfoTV;
1255 Boolean isUnqual;
1256 TplAbsyn.Ident name;
1257 TplAbsyn.PathIdent pid;
1258 TplAbsyn.TemplateDef td;
1259 list<TplAbsyn.ASTDef> astDefs;
1260 list<tuple<TplAbsyn.Ident, TplAbsyn.TemplateDef>> templDefs;
1261
1262 //stop at 'end' ... a little workaround to have the code "nice"
1263 case (startChars as ("e"::"n"::"d":: chars), linfo, astDefs, templDefs)
1264 algorithm
1265 ✗ afterKeyword(chars);
1266 ✗ then (startChars, linfo, astDefs, templDefs);
1267
1268 case ("i"::"m"::"p"::"o"::"r"::"t":: chars, linfo, astDefs, templDefs)
1269 algorithm
1270 ✗ afterKeyword(chars);
1271 ✗ (chars, linfo) := interleave(chars, linfo);
1272 ✗ "i"::"n"::"t"::"e"::"r"::"f"::"a"::"c"::"e" :: chars := chars;
1273 ✗ afterKeyword(chars);
1274 //remember position for a file error
1275 ✗ (startChars, startLinfo) := interleave(chars, linfo);
1276 ✗ (chars, linfo, pid) := pathIdentNoOpt(startChars, startLinfo);
1277 ✗ (chars, linfo) := interleave(chars, linfo);
1278 ✗ (chars, linfo) := stringComment(chars, linfo);
1279 ✗ (chars, linfo) := interleave(chars, linfo);
1280 ✗ (chars, linfo) := semicolon(chars, linfo);
1281
1282 ✗ (astDefs, linfoTV, errOptTV, cachedDefs) := typeviewDefsFromInterfaceFile(pid, astDefs, cachedDefs);
1283 ✗ linfo := parseErrorPrevPositionOpt(startChars, startLinfo, linfo, errOptTV, false);
1284 ✗ linfo := mergeErrors(linfo, linfoTV);
1285 ✗ (chars, linfo) := interleave(chars, linfo);
1286 ✗ (chars, linfo, astDefs, templDefs, cachedDefs) := definitions(chars, linfo, astDefs, templDefs, cachedDefs);
1287 ✗ then (chars, linfo, astDefs, templDefs);
1288
1289 case ("i"::"m"::"p"::"o"::"r"::"t":: chars, linfo, astDefs, templDefs)
1290 algorithm
1291 ✗ afterKeyword(chars);
1292 ✗ (chars, linfo) := interleave(chars, linfo);
1293 //remember position for a file error
1294 ✗ (startChars, startLinfo) := interleave(chars, linfo);
1295 ✗ (chars, linfo, pid) := pathIdentNoOpt(startChars, startLinfo);
1296 ✗ (chars, linfo) := interleave(chars, linfo);
1297 ✗ (chars, linfo, isUnqual) := unqualImportPostfix(chars, linfo);
1298 ✗ (chars, linfo) := stringComment(chars, linfo);
1299 ✗ (chars, linfo) := interleave(chars, linfo);
1300 ✗ (chars, linfo) := semicolon(chars, linfo);
1301
1302 ✗ (astDefs, linfoTV, errOptTV, cachedDefs) := typeviewDefsFromTemplateFile(pid, isUnqual, astDefs, cachedDefs);
1303 ✗ linfo := parseErrorPrevPositionOpt(startChars, startLinfo, linfo, errOptTV, false);
1304 ✗ linfo := mergeErrors(linfo, linfoTV);
1305 ✗ (chars, linfo) := interleave(chars, linfo);
1306 ✗ (chars, linfo, astDefs, templDefs, cachedDefs) := definitions(chars, linfo, astDefs, templDefs, cachedDefs);
1307 ✗ then (chars, linfo, astDefs, templDefs);
1308
1309 case (chars, linfo, astDefs,templDefs)
1310 algorithm
1311 ✗ (chars, linfo, name, td) := templDef(chars, linfo);
1312 ✗ (chars, linfo) := interleave(chars, linfo);
1313 ✗ (chars, linfo, astDefs, templDefs, cachedDefs) := definitions(chars, linfo, astDefs, (name,td)::templDefs, cachedDefs);
1314 ✗ then (chars, linfo, astDefs, templDefs);
1315
1316 else (inChars, inLineInfo, inAccASTDefs, inAccTemplDefs);
1317
1318 end matchcontinue;
1319 end definitions;
1320
1321 /*
1322 unqualImportPostfix:
1323 '.' '*' => true
1324 |
1325 _ => false
1326 */
1327 public function unqualImportPostfix
1328 input list<String> inChars;
1329 input LineInfo inLineInfo;
1330
1331 output list<String> outChars;
1332 output LineInfo outLineInfo;
1333 output Boolean outIsUnqual;
1334 algorithm
1335 (outChars, outLineInfo, outIsUnqual) := matchcontinue (inChars, inLineInfo)
1336 local
1337 list<String> chars;
1338 LineInfo linfo;
1339
1340 case ("." :: chars, linfo)
1341 algorithm
1342 ✗ (chars, linfo) := interleave(chars, linfo);
1343 ✗ "*" :: chars := chars;
1344 ✗ then (chars, linfo, true);
1345 else (inChars, inLineInfo, false);
1346 end matchcontinue;
1347 end unqualImportPostfix;
1348
1349 //optional, may fail
1350 public function typeSig
1351 input list<String> inChars;
1352 input LineInfo inLineInfo;
1353
1354 output list<String> outChars;
1355 output LineInfo outLineInfo;
1356 output TplAbsyn.TypeSignature outTypeSignature;
1357 algorithm
1358 (outChars, outLineInfo, outTypeSignature) := match (inChars, inLineInfo)
1359 local
1360 list<String> chars;
1361 LineInfo linfo;
1362 TplAbsyn.TypeSignature ts;
1363
1364 case (chars, linfo)
1365 algorithm
1366 ✗ (chars, linfo, ts) := typeSig_base(chars, linfo);
1367 ✗ (chars, linfo) := interleave(chars, linfo);
1368 ✗ then (chars, linfo, ts);
1369
1370 end match;
1371 end typeSig;
1372
1373 //must not fail
1374 public function typeSigNoOpt
1375 input list<String> inChars;
1376 input LineInfo inLineInfo;
1377
1378 output list<String> outChars;
1379 output LineInfo outLineInfo;
1380 output TplAbsyn.TypeSignature outTypeSignature;
1381 algorithm
1382 (outChars, outLineInfo, outTypeSignature) := matchcontinue (inChars, inLineInfo)
1383 local
1384 list<String> chars;
1385 LineInfo linfo;
1386 TplAbsyn.TypeSignature ts;
1387
1388 case (chars, linfo)
1389 algorithm
1390 ✗ (chars, linfo, ts) := typeSig(chars, linfo);
1391 then (chars, linfo, ts);
1392
1393 case (chars, linfo)
1394 algorithm
1395 ✗ linfo := parseError(chars, linfo, "Expected a type signature at the position.", true);
1396 ✗ then (chars, linfo, TplAbsyn.UNRESOLVED_TYPE("#parse error#"));
1397
1398 end matchcontinue;
1399 end typeSigNoOpt;
1400
1401 /*
1402 typeSig_base:
1403 'list' '<' typeSig:tof '>' => LIST_TYPE(tof)
1404 |
1405 'Option' '<' typeSig '>' => OPTION_TYPE(tof)
1406 |
1407 'tuple' '<' typeSig:ts typeSig_restList:restLst '>' => TUPLE_TYPE(ts::restLst)
1408 |
1409 'array' '<' typeSig:tof '>' => ARRAY_TYPE(tof)
1410 |
1411 pathIdent:pid => NAMED_TYPE(pid) // +specializations for String, Integer, .... => STRING_TYPE(), ...
1412 */
1413 public function typeSig_base
1414 input list<String> inChars;
1415 input LineInfo inLineInfo;
1416
1417 output list<String> outChars;
1418 output LineInfo outLineInfo;
1419 output TplAbsyn.TypeSignature outTypeSignature;
1420 algorithm
1421 (outChars, outLineInfo, outTypeSignature) := matchcontinue (inChars, inLineInfo)
1422 local
1423 list<String> chars;
1424 LineInfo linfo;
1425 TplAbsyn.TypeSignature ts, tof;
1426 list<TplAbsyn.TypeSignature> restLst;
1427 TplAbsyn.PathIdent pid;
1428
1429 case ("l"::"i"::"s"::"t" :: chars, linfo)
1430 algorithm
1431 ✗ afterKeyword(chars);
1432 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "<");
1433 ✗ (chars, linfo) := interleave(chars, linfo);
1434 ✗ (chars, linfo, tof) := typeSigNoOpt(chars, linfo);
1435 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ">");
1436 ✗ then (chars, linfo, TplAbsyn.LIST_TYPE(tof));
1437
1438 case ("O"::"p"::"t"::"i"::"o"::"n" :: chars, linfo)
1439 algorithm
1440 ✗ afterKeyword(chars);
1441 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "<");
1442 ✗ (chars, linfo) := interleave(chars, linfo);
1443 ✗ (chars, linfo, tof) := typeSigNoOpt(chars, linfo);
1444 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ">");
1445 ✗ then (chars, linfo, TplAbsyn.OPTION_TYPE(tof));
1446
1447 case ("t"::"u"::"p"::"l"::"e" :: chars, linfo)
1448 algorithm
1449 ✗ afterKeyword(chars);
1450 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "<");
1451 ✗ (chars, linfo) := interleave(chars, linfo);
1452 ✗ (chars, linfo, tof) := typeSigNoOpt(chars, linfo);
1453 ✗ (chars, linfo) := interleave(chars, linfo);
1454 ✗ (chars, linfo, restLst) := typeSig_restList(chars, linfo);
1455 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ">");
1456 ✗ then (chars, linfo, TplAbsyn.TUPLE_TYPE(tof::restLst));
1457
1458 case ("a"::"r"::"r"::"a"::"y" :: chars, linfo)
1459 algorithm
1460 ✗ afterKeyword(chars);
1461 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "<");
1462 ✗ (chars, linfo) := interleave(chars, linfo);
1463 ✗ (chars, linfo, tof) := typeSigNoOpt(chars, linfo);
1464 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ">");
1465 ✗ then (chars, linfo, TplAbsyn.ARRAY_TYPE(tof));
1466
1467 case (chars, linfo)
1468 algorithm
1469 ✗ (chars, linfo, pid) := pathIdent(chars, linfo);
1470 ✗ ts := typeSigFromPathIdent(pid);
1471 ✗ then (chars, linfo, ts);
1472
1473 end matchcontinue;
1474 end typeSig_base;
1475
1476 /*
1477 typeSig_restList:
1478 ',' typeSig:ts typeSig_restList:restLst => ts::restLst
1479 |
1480 _ => {}
1481 */
1482 public function typeSig_restList
1483 input list<String> inChars;
1484 input LineInfo inLineInfo;
1485
1486 output list<String> outChars;
1487 output LineInfo outLineInfo;
1488 output list<TplAbsyn.TypeSignature> outTypeSignatureList;
1489 algorithm
1490 (outChars, outLineInfo, outTypeSignatureList) := matchcontinue (inChars, inLineInfo)
1491 local
1492 list<String> chars;
1493 LineInfo linfo;
1494 TplAbsyn.TypeSignature ts;
1495 list<TplAbsyn.TypeSignature> tsLst;
1496
1497 case ("," :: chars, linfo)
1498 algorithm
1499 ✗ (chars, linfo) := interleave(chars, linfo);
1500 ✗ (chars, linfo, ts) := typeSigNoOpt(chars, linfo);
1501 ✗ (chars, linfo) := interleave(chars, linfo);
1502 ✗ (chars, linfo, tsLst) := typeSig_restList(chars, linfo);
1503 ✗ then (chars, linfo, ts::tsLst);
1504
1505 else (inChars, inLineInfo, {});
1506
1507 end matchcontinue;
1508 end typeSig_restList;
1509
1510
1511 public function typeSigFromPathIdent
1512 input TplAbsyn.PathIdent inPathIdent;
1513 output TplAbsyn.TypeSignature outTypeSignature;
1514 algorithm
1515 outTypeSignature := match inPathIdent
1516 case TplAbsyn.IDENT("String") then TplAbsyn.STRING_TYPE();
1517 case TplAbsyn.IDENT("Integer") then TplAbsyn.INTEGER_TYPE();
1518 case TplAbsyn.IDENT("Real") then TplAbsyn.REAL_TYPE();
1519 case TplAbsyn.IDENT("Boolean") then TplAbsyn.BOOLEAN_TYPE();
1520
1521 ✗ else TplAbsyn.NAMED_TYPE(inPathIdent);
1522
1523 end match;
1524 end typeSigFromPathIdent;
1525
1526 /*
1527 publicProtected:
1528 'public' => true
1529 |
1530 'protected' => false
1531 |
1532 _ => true
1533 */
1534 public function publicProtected
1535 input list<String> inChars;
1536
1537 output list<String> outChars;
1538 output Boolean outIsDefault;
1539 algorithm
1540 (outChars, outIsDefault) := matchcontinue inChars
1541 local
1542 list<String> chars;
1543
1544 case "p"::"u"::"b"::"l"::"i"::"c" :: chars
1545 algorithm
1546 ✗ afterKeyword(chars);
1547 then (chars, true);
1548
1549 case "p"::"r"::"o"::"t"::"e"::"c"::"t"::"e"::"d" :: chars
1550 algorithm
1551 ✗ afterKeyword(chars);
1552 then (chars, false);
1553
1554 else (inChars, true);
1555
1556 end matchcontinue;
1557 end publicProtected;
1558
1559 /*
1560 stringComment:
1561 '"' stringCommentRest
1562 |
1563 _
1564 */
1565 public function stringComment
1566 input list<String> inChars;
1567 input LineInfo inLineInfo;
1568
1569 output list<String> outChars;
1570 output LineInfo outLineInfo;
1571 algorithm
1572 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo)
1573 local
1574 list<String> chars, startChars;
1575 LineInfo linfo, startLinfo;
1576 Option<String> optErr;
1577
1578 case (startChars as ("\"" :: chars), startLinfo)
1579 algorithm
1580 ✗ (chars, linfo, optErr) := stringCommentRest(chars, startLinfo);
1581 ✗ linfo := parseErrorPrevPositionOpt(startChars, startLinfo, linfo, optErr, true);
1582 then (chars, linfo);
1583
1584 else (inChars, inLineInfo);
1585
1586 end matchcontinue;
1587 end stringComment;
1588 /*
1589 stringCommentRest:
1590 '\\"' stringCommentRest
1591 |
1592 '\\' stringCommentRest
1593 |
1594 ~'"' stringCommentRest
1595 |
1596 '"'
1597 */
1598 public function stringCommentRest
1599 input list<String> inChars;
1600 input LineInfo inLineInfo;
1601
1602 output list<String> outChars;
1603 output LineInfo outLineInfo;
1604 output Option<String> outError;
1605 algorithm
1606 (outChars, outLineInfo, outError) := matchcontinue (inChars, inLineInfo)
1607 local
1608 list<String> chars, startChars;
1609 LineInfo linfo;
1610 Option<String> optErr;
1611 String strErr;
1612
1613 case ("\"" :: chars, linfo)
1614 ✗ then (chars, linfo,NONE());
1615
1616 case ("\\"::"\"" :: chars, linfo)
1617 algorithm
1618 ✗ (chars, linfo, optErr) := stringCommentRest(chars, linfo);
1619 then (chars, linfo, optErr);
1620
1621 case ("\\"::"\\" :: chars, linfo)
1622 algorithm
1623 ✗ (chars, linfo, optErr) := stringCommentRest(chars, linfo);
1624 then (chars, linfo, optErr);
1625
1626 case (chars, linfo)
1627 algorithm
1628 ✗ (chars, linfo) := newLine(chars, linfo);
1629 ✗ (chars, linfo, optErr) := stringCommentRest(chars, linfo);
1630 then (chars, linfo, optErr);
1631
1632 case (startChars as (_ :: chars), linfo)
1633 algorithm
1634 ✗ failure(newLine(startChars, linfo));
1635 ✗ (chars, linfo, optErr) := stringCommentRest(chars, linfo);
1636 then (chars, linfo, optErr);
1637
1638 case ( {}, linfo )
1639 algorithm
1640 strErr := "Unmatched \" \" comment - reached end of file.";
1641 ✗ if Flags.isSet(Flags.FAILTRACE) then
1642 ✗ Debug.trace("Parse error - TplParser.stringCommentRest - " + strErr + "\n");
1643 end if;
1644 ✗ then ( {}, linfo, SOME(strErr) );
1645
1646 end matchcontinue;
1647 end stringCommentRest;
1648
1649
1650 public function semicolon
1651 input list<String> inChars;
1652 input LineInfo inLineInfo;
1653
1654 output list<String> outChars;
1655 output LineInfo outLineInfo;
1656 algorithm
1657 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo)
1658 local
1659 list<String> chars;
1660 LineInfo linfo;
1661
1662 case (";":: chars, linfo)
1663 then (chars, linfo);
1664
1665 //error expect ; ... only report it if it is the first error
1666 case (chars, linfo)
1667 algorithm
1668 ✗ linfo := parseError(chars, linfo, "Expected semicolon ';' at the position.", false );
1669 then (chars, linfo);
1670
1671 else
1672 algorithm
1673 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!! TplParser.semicolon failed.\n");
1674 ✗ then fail();
1675
1676 end matchcontinue;
1677 end semicolon;
1678
1679
1680 /*
1681 interfacePackage(astDefs):
1682 'interface' 'package' pathIdent:pid stringComment
1683 typeviewDefs(astDefs):ads
1684 endDefPathIdent(pid)
1685 => (pid, ads)
1686 */
1687 public function interfacePackage
1688 input list<String> inChars;
1689 input LineInfo inLineInfo;
1690 input list<TplAbsyn.ASTDef> inAccASTDefs;
1691
1692 output list<String> outChars;
1693 output LineInfo outLineInfo;
1694 output TplAbsyn.PathIdent outPid;
1695 output list<TplAbsyn.ASTDef> outAccASTDefs;
1696 algorithm
1697 (outChars, outLineInfo, outPid, outAccASTDefs)
1698 := matchcontinue (inChars, inLineInfo)
1699 local
1700 list<String> chars;
1701 LineInfo linfo;
1702 TplAbsyn.PathIdent pid;
1703 list<TplAbsyn.ASTDef> astDefs;
1704
1705 case (chars, linfo)
1706 algorithm
1707 ✗ (chars, linfo) := interleaveExpectKeyWord(chars, linfo, {"i","n","t","e","r","f","a","c","e"}, true);
1708 ✗ (chars, linfo) := interleaveExpectKeyWord(chars, linfo, {"p","a","c","k","a","g","e"}, true);
1709 ✗ (chars, linfo) := interleave(chars, linfo);
1710 ✗ (chars, linfo, pid) := pathIdentNoOpt(chars, linfo);
1711 ✗ (chars, linfo) := interleave(chars, linfo);
1712 ✗ (chars, linfo) := stringComment(chars, linfo);
1713 ✗ (chars, linfo) := interleave(chars, linfo);
1714 ✗ (chars, linfo, astDefs) := typeviewDefs(chars, linfo, inAccASTDefs);
1715 ✗ (chars, linfo) := interleave(chars, linfo);
1716 ✗ (chars, linfo) := endDefPathIdent(chars, linfo,pid);
1717 ✗ then (chars, linfo, pid, astDefs);
1718
1719 else
1720 algorithm
1721 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!!Parse error - TplParser.interfacePackage failed.\n");
1722 ✗ then fail();
1723
1724 end matchcontinue;
1725 end interfacePackage;
1726
1727 /*
1728 typeviewDefs(astDefs):
1729 absynDef:ad typeviewDefs(ad::astDefs):ads => ads
1730 |
1731 _ => astDefs
1732 */
1733 public function typeviewDefs
1734 input list<String> inChars;
1735 input LineInfo inLineInfo;
1736 input list<TplAbsyn.ASTDef> inAccASTDefs;
1737
1738 output list<String> outChars;
1739 output LineInfo outLineInfo;
1740 output list<TplAbsyn.ASTDef> outASTDefs;
1741 algorithm
1742 (outChars, outLineInfo, outASTDefs) := matchcontinue (inChars, inLineInfo, inAccASTDefs)
1743 local
1744 list<String> chars;
1745 LineInfo linfo;
1746 TplAbsyn.ASTDef ad;
1747 list<TplAbsyn.ASTDef> astDefs;
1748
1749 case (chars, linfo, astDefs)
1750 algorithm
1751 ✗ (chars, linfo, ad) := absynDef(chars, linfo);
1752 ✗ (chars, linfo) := interleave(chars, linfo);
1753 ✗ (chars, linfo, astDefs) := typeviewDefs(chars, linfo, ad::astDefs);
1754 then (chars, linfo, astDefs);
1755
1756 ✗ else (inChars, inLineInfo, inAccASTDefs);
1757
1758 end matchcontinue;
1759 end typeviewDefs;
1760
1761
1762 /*
1763 absynDef:
1764 publicProtected:isD 'package' pathIdent:pid stringComment
1765 absynTypes:types
1766 endDefPathIdent(pid)
1767 => AST_DEF(pid, isD, true, types)
1768 */
1769 public function absynDef
1770 input list<String> inChars;
1771 input LineInfo inLineInfo;
1772
1773 output list<String> outChars;
1774 output LineInfo outLineInfo;
1775 output TplAbsyn.ASTDef outASTDef;
1776 algorithm
1777 (outChars, outLineInfo, outASTDef) := match (inChars, inLineInfo)
1778 local
1779 list<String> chars;
1780 LineInfo linfo;
1781 Boolean isD;
1782 TplAbsyn.PathIdent pid;
1783 list<tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo>> types;
1784
1785 case (chars, linfo)
1786 algorithm
1787 ✗ (chars, isD) := publicProtected(chars);
1788 ✗ (chars, linfo) := interleave(chars, linfo);
1789 ✗ "p"::"a"::"c"::"k"::"a"::"g"::"e" :: chars := chars;
1790 ✗ afterKeyword(chars);
1791 ✗ (chars, linfo) := interleave(chars, linfo);
1792
1793 ✗ (chars, linfo,pid) := pathIdentNoOpt(chars, linfo);
1794 ✗ (chars, linfo) := interleave(chars, linfo);
1795 ✗ (chars, linfo) := stringComment(chars, linfo);
1796 ✗ (chars, linfo) := interleave(chars, linfo);
1797 ✗ (chars, linfo, types) := absynTypes(chars, linfo);
1798 ✗ (chars, linfo) := interleave(chars, linfo);
1799 ✗ (chars, linfo) := endDefPathIdent(chars, linfo,pid);
1800 ✗ then (chars, linfo, TplAbsyn.AST_DEF(pid, isD, true, types));
1801
1802 end match;
1803 end absynDef;
1804
1805 /*
1806 //not optional, must not fail
1807 endDefPathIdent(pid):
1808 'end' pathIdent:pidEnd ';' // pid == pidEnd | warning
1809 */
1810 public function endDefPathIdent
1811 input list<String> inChars;
1812 input LineInfo inLineInfo;
1813 input TplAbsyn.PathIdent inPathIdentToMatch;
1814
1815 output list<String> outChars;
1816 output LineInfo outLineInfo;
1817 algorithm
1818 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo, inPathIdentToMatch)
1819 local
1820 list<String> chars, startChars;
1821 LineInfo linfo, startLinfo;
1822 TplAbsyn.PathIdent pid, pidToMatch;
1823
1824 case ("e"::"n"::"d" :: chars, linfo, pidToMatch)
1825 algorithm
1826 ✗ afterKeyword(chars);
1827 ✗ (chars, linfo) := interleave(chars, linfo);
1828 ✗ (chars, linfo,pid) := pathIdentNoOpt(chars, linfo);
1829 ✗ true := valueEq(pid, pidToMatch);
1830 ✗ (chars, linfo) := interleave(chars, linfo);
1831 ✗ (chars, linfo) := semicolon(chars, linfo);
1832 then (chars, linfo);
1833
1834 //error unmatched "end"
1835 case ("e"::"n"::"d" :: chars, linfo, pidToMatch)
1836 algorithm
1837 ✗ afterKeyword(chars);
1838 ✗ (startChars, startLinfo) := interleave(chars, linfo);
1839 ✗ (chars, linfo,pid) := pathIdentNoOpt(startChars, startLinfo);
1840 ✗ false := valueEq(pid, pidToMatch);
1841 ✗ linfo := parseErrorPrevPosition(startChars, startLinfo, linfo,
1842 "Unmatched ident for 'end'. Expected '" + TplAbsyn.pathIdentString(pidToMatch) + "', but '" + TplAbsyn.pathIdentString(pid) + "' found instead.",
1843 false);
1844 //true = Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse warning - TplParser.endDefPathIdent - unmatched ident for 'end' of the definition of '" + TplAbsyn.pathIdentString(pidToMatch) + "' ... 'end " + TplAbsyn.pathIdentString(pid) + "' found instead.\n");
1845 ✗ (chars, linfo) := interleave(chars, linfo);
1846 ✗ (chars, linfo) := semicolon(chars, linfo);
1847 then (chars, linfo);
1848
1849 //error "end" expected
1850 case (chars, linfo, _)
1851 algorithm
1852 ✗ (_, false) := isKeyword(chars, "e"::"n"::"d"::{});
1853 ✗ linfo := parseError(chars, linfo, "Expected 'end' keyword at the position.", true);
1854 ✗ then (chars, linfo);
1855
1856 case (chars, linfo, _)
1857 algorithm
1858 ✗ if Flags.isSet(Flags.FAILTRACE) then
1859 ✗ Debug.trace("!!!Parse error - TplParser.endDefPathIdent failed.\n");
1860 end if;
1861 ✗ then (chars, linfo);
1862
1863 end matchcontinue;
1864 end endDefPathIdent;
1865
1866 /*
1867 //not optional ... must not fail
1868 endDefIdent(id):
1869 'end' identifier:idEnd ';' // id == idEnd | warning
1870 */
1871 public function endDefIdent
1872 input list<String> inChars;
1873 input LineInfo inLineInfo;
1874 input TplAbsyn.Ident inIdentToMatch;
1875
1876 output list<String> outChars;
1877 output LineInfo outLineInfo;
1878 algorithm
1879 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo, inIdentToMatch)
1880 local
1881 list<String> chars, startChars;
1882 LineInfo linfo, startLinfo;
1883 TplAbsyn.Ident id, idToMatch;
1884
1885 case ("e"::"n"::"d" :: chars, linfo, idToMatch)
1886 algorithm
1887 ✗ afterKeyword(chars);
1888 ✗ (chars, linfo) := interleave(chars, linfo);
1889 ✗ (chars,linfo,id) := identifierNoOpt(chars,linfo);
1890 ✗ true := valueEq(id, idToMatch);
1891 ✗ (chars, linfo) := interleave(chars, linfo);
1892 ✗ (chars, linfo) := semicolon(chars, linfo);
1893 then (chars, linfo);
1894
1895 //error unmatched ids
1896 case ("e"::"n"::"d" :: chars, linfo, idToMatch)
1897 algorithm
1898 ✗ afterKeyword(chars);
1899 ✗ (startChars, startLinfo) := interleave(chars, linfo);
1900 ✗ (chars,linfo,id) := identifierNoOpt(startChars,startLinfo);
1901 ✗ false := valueEq(id, idToMatch);
1902 ✗ linfo := parseErrorPrevPosition(startChars, startLinfo, linfo,
1903 "Unmatched ident for 'end'. Expected '" + idToMatch + "', but '" + id + "' found instead.",
1904 false);
1905 //true = Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse warning - TplParser.endDefIdent - unmatched ident for 'end' of the definition of " + idToMatch + " ... end " + id + " found instead.\n");
1906 ✗ (chars, linfo) := interleave(chars, linfo);
1907 ✗ (chars, linfo) := semicolon(chars, linfo);
1908 then (chars, linfo);
1909
1910 //error "end" expected
1911 case (chars, linfo, _)
1912 algorithm
1913 ✗ (_, false) := isKeyword(chars, "e"::"n"::"d"::{});
1914 ✗ linfo := parseError(chars, linfo, "Expected 'end' keyword at the position.", true);
1915 ✗ then (chars, linfo);
1916
1917 else
1918 algorithm
1919 ✗ if Flags.isSet(Flags.FAILTRACE) then
1920 ✗ Debug.trace("!!!Parse error - TplParser.endDefIdent failed.\n");
1921 end if;
1922 ✗ then (inChars, inLineInfo);
1923
1924 end matchcontinue;
1925 end endDefIdent;
1926
1927
1928 /*
1929 absynTypes:
1930 absynType:(id,ti) absynTypes:types => (id,ti) :: types
1931 |
1932 _ => {}
1933 */
1934 public function absynTypes
1935 input list<String> inChars;
1936 input LineInfo inLineInfo;
1937
1938 output list<String> outChars;
1939 output LineInfo outLineInfo;
1940 output list<tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo>> outTypes;
1941 algorithm
1942 (outChars, outLineInfo, outTypes) := matchcontinue (inChars, inLineInfo)
1943 local
1944 list<String> chars;
1945 LineInfo linfo;
1946 tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo> idti;
1947 list<tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo>> types;
1948
1949 case (chars, linfo)
1950 algorithm
1951 ✗ (chars, linfo, idti) := absynType(chars, linfo);
1952 ✗ (chars, linfo) := interleave(chars, linfo);
1953 ✗ (chars, linfo, types) := absynTypes(chars, linfo);
1954 ✗ then (chars, linfo, idti :: types);
1955
1956 else (inChars, inLineInfo, {});
1957
1958 end matchcontinue;
1959 end absynTypes;
1960 /*
1961 absynType:
1962 'uniontype' identifier:id stringComment
1963 recordTags(id):rtags
1964 => (id, TI_UNION_TYPE(rtags))
1965 |
1966 recordType:(id,fields)
1967 => (id, TI_RECORD_TYPE(fields))
1968 |
1969 'function' identifier:id stringComment
1970 inputFunArgs:inArgs
1971 outputFunArgs:outArgs
1972 endDefIdent(id)
1973 => (id, TI_FUN_TYPE(inArgs,outArgs))
1974 |
1975 'constant' typeSig:ts identifier:id stringComment ';'
1976 => (id, TI_CONST_TYPE(ts))
1977 |
1978 'type' identifier:id '=' typeSig:ts stringComment ';'
1979 => (id, TI_ALIAS_TYPE(ts))
1980 */
1981 public function absynType
1982 input list<String> inChars;
1983 input LineInfo inLineInfo;
1984
1985 output list<String> outChars;
1986 output LineInfo outLineInfo;
1987 output tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo> outType;
1988 algorithm
1989 (outChars, outLineInfo, outType) := matchcontinue (inChars, inLineInfo)
1990 local
1991 list<String> chars;
1992 LineInfo linfo;
1993 TplAbsyn.Ident id;
1994 TplAbsyn.TypedIdents fields,inargs,outargs;
1995 list<tuple<TplAbsyn.Ident, TplAbsyn.TypedIdents>> rtags;
1996 TplAbsyn.TypeSignature ts;
1997 list<TplAbsyn.Ident> tyvars;
1998
1999 case ("u"::"n"::"i"::"o"::"n"::"t"::"y"::"p"::"e" :: chars, linfo)
2000 algorithm
2001 ✗ afterKeyword(chars);
2002 ✗ (chars, linfo) := interleave(chars, linfo);
2003 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
2004 ✗ (chars, linfo) := interleave(chars, linfo);
2005 ✗ (chars, linfo) := stringComment(chars, linfo);
2006 ✗ (chars, linfo) := interleave(chars, linfo);
2007 ✗ (chars, linfo, rtags) := recordTags(chars, linfo, id);
2008 ✗ then (chars, linfo, (id, TplAbsyn.TI_UNION_TYPE(rtags)));
2009
2010 case (chars, linfo)
2011 algorithm
2012 ✗ (chars, linfo, (id,fields)) := recordType(chars, linfo);
2013 ✗ then (chars, linfo, (id, TplAbsyn.TI_RECORD_TYPE(fields)));
2014
2015 case ("f"::"u"::"n"::"c"::"t"::"i"::"o"::"n":: chars, linfo)
2016 algorithm
2017 ✗ afterKeyword(chars);
2018 ✗ (chars, linfo) := interleave(chars, linfo);
2019 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
2020 ✗ (chars, linfo) := interleave(chars, linfo);
2021 ✗ (chars, linfo) := stringComment(chars, linfo);
2022 ✗ (chars, linfo) := interleave(chars, linfo);
2023 ✗ (chars, linfo, tyvars) := typeVars(chars, linfo, {});
2024 ✗ (chars, linfo) := interleave(chars, linfo);
2025 ✗ (chars, linfo, inargs) := inputFunArgs(chars, linfo);
2026 ✗ (chars, linfo) := interleave(chars, linfo);
2027 ✗ (chars, linfo, outargs) := outputFunArgs(chars, linfo);
2028 ✗ (chars, linfo) := interleave(chars, linfo);
2029 ✗ (chars, linfo, tyvars) := typeVars(chars, linfo, tyvars);
2030 ✗ (chars, linfo) := interleave(chars, linfo);
2031 ✗ (chars, linfo) := endDefIdent(chars, linfo,id);
2032 ✗ then (chars, linfo, (id, TplAbsyn.TI_FUN_TYPE(inargs,outargs,tyvars)));
2033
2034 case ("c"::"o"::"n"::"s"::"t"::"a"::"n"::"t":: chars, linfo)
2035 algorithm
2036 ✗ afterKeyword(chars);
2037 ✗ (chars, linfo) := interleave(chars, linfo);
2038 ✗ (chars, linfo, ts) := typeSigNoOpt(chars, linfo);
2039 ✗ (chars, linfo) := interleave(chars, linfo);
2040 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
2041 ✗ (chars, linfo) := interleave(chars, linfo);
2042 ✗ (chars, linfo) := stringComment(chars, linfo);
2043 ✗ (chars, linfo) := interleave(chars, linfo);
2044 ✗ (chars, linfo) := semicolon(chars, linfo);
2045 ✗ then (chars, linfo, (id, TplAbsyn.TI_CONST_TYPE(ts)));
2046
2047 case ("t"::"y"::"p"::"e":: chars, linfo)
2048 algorithm
2049 ✗ afterKeyword(chars);
2050 ✗ (chars, linfo) := interleave(chars, linfo);
2051 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
2052 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "=");
2053 ✗ (chars, linfo) := interleave(chars, linfo);
2054 ✗ (chars, linfo, ts) := typeSigNoOpt(chars, linfo);
2055 ✗ (chars, linfo) := interleave(chars, linfo);
2056 ✗ (chars, linfo) := stringComment(chars, linfo);
2057 ✗ (chars, linfo) := interleave(chars, linfo);
2058 ✗ (chars, linfo) := semicolon(chars, linfo);
2059 ✗ then (chars, linfo, (id, TplAbsyn.TI_ALIAS_TYPE(ts)));
2060
2061 end matchcontinue;
2062 end absynType;
2063
2064 /*
2065 recordType:
2066 'record' identifier:id stringComment
2067 typeDecls:tids
2068 'end' identifier:idEnd ';' // id == idEnd
2069 => (id,tids)
2070 */
2071 public function recordType
2072 input list<String> inChars;
2073 input LineInfo inLineInfo;
2074
2075 output list<String> outChars;
2076 output LineInfo outLineInfo;
2077 output tuple<TplAbsyn.Ident, TplAbsyn.TypedIdents> outRecordType;
2078 algorithm
2079 (outChars, outLineInfo, outRecordType) := match (inChars, inLineInfo)
2080 local
2081 list<String> chars;
2082 LineInfo linfo;
2083 TplAbsyn.Ident id;
2084 TplAbsyn.TypedIdents fields;
2085
2086 case ("r"::"e"::"c"::"o"::"r"::"d":: chars, linfo)
2087 algorithm
2088 ✗ afterKeyword(chars);
2089 ✗ (chars, linfo) := interleave(chars, linfo);
2090 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
2091 ✗ (chars, linfo) := interleave(chars, linfo);
2092 ✗ (chars, linfo) := stringComment(chars, linfo);
2093 ✗ (chars, linfo) := interleave(chars, linfo);
2094 ✗ (chars, linfo, fields) := typeDecls(chars, linfo);
2095 ✗ (chars, linfo) := interleave(chars, linfo);
2096 ✗ (chars, linfo) := endDefIdent(chars, linfo,id);
2097 ✗ then (chars, linfo, (id, fields));
2098
2099 end match;
2100 end recordType;
2101 /*
2102 typeDecls:
2103 typeSig:ts identifier:id stringComment ';'
2104 typeDecls:tids
2105 => (id,ts) :: tids
2106 |
2107 _ => {}
2108 */
2109 public function typeDecls
2110 input list<String> inChars;
2111 input LineInfo inLineInfo;
2112
2113 output list<String> outChars;
2114 output LineInfo outLineInfo;
2115 output TplAbsyn.TypedIdents outTypeDecls;
2116 algorithm
2117 (outChars, outLineInfo, outTypeDecls) := matchcontinue (inChars, inLineInfo)
2118 local
2119 list<String> chars, startChars;
2120 LineInfo linfo;
2121 TplAbsyn.Ident id;
2122 TplAbsyn.TypedIdents fields;
2123 TplAbsyn.TypeSignature ts;
2124
2125 //stop at 'end' ... a little workaround to have the code "nice"
2126 case (startChars as ("e"::"n"::"d":: chars), linfo)
2127 algorithm
2128 ✗ afterKeyword(chars);
2129 ✗ then (startChars, linfo, {} );
2130
2131 case (chars, linfo)
2132 algorithm
2133 ✗ (chars, linfo, ts) := typeSig(chars, linfo);
2134 ✗ (chars, linfo) := interleave(chars, linfo);
2135 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
2136 ✗ (chars, linfo) := interleave(chars, linfo);
2137 ✗ (chars, linfo) := stringComment(chars, linfo);
2138 ✗ (chars, linfo) := interleave(chars, linfo);
2139 ✗ (chars, linfo) := semicolon(chars, linfo);
2140 ✗ (chars, linfo) := interleave(chars, linfo);
2141 ✗ (chars, linfo, fields) := typeDecls(chars, linfo);
2142 ✗ then (chars, linfo, (id,ts)::fields );
2143
2144 else (inChars, inLineInfo, {});
2145
2146 end matchcontinue;
2147 end typeDecls;
2148 /*
2149 recordTags:
2150 recordType:(id,tids) recordTags:rtags => (id,tids) :: rtags
2151 |
2152 _ => {}
2153 */
2154 public function recordTags
2155 input list<String> inChars;
2156 input LineInfo inLineInfo;
2157 input String id;
2158
2159 output list<String> outChars;
2160 output LineInfo outLineInfo;
2161 output list<tuple<TplAbsyn.Ident, TplAbsyn.TypedIdents>> outRecordTags;
2162 algorithm
2163 (outChars, outLineInfo, outRecordTags) := matchcontinue (inChars, inLineInfo)
2164 local
2165 list<String> chars;
2166 LineInfo linfo;
2167 tuple<TplAbsyn.Ident, TplAbsyn.TypedIdents> rtag;
2168 list<tuple<TplAbsyn.Ident, TplAbsyn.TypedIdents>> rtags;
2169
2170 case (chars, linfo)
2171 algorithm
2172 ✗ (chars, linfo, rtag) := recordType(chars, linfo);
2173 ✗ (chars, linfo) := interleave(chars, linfo);
2174 ✗ (chars, linfo, rtags) := recordTags(chars, linfo, id);
2175 ✗ then (chars, linfo, rtag :: rtags);
2176
2177 case (chars, linfo)
2178 algorithm
2179 ✗ (chars, linfo) := interleave(chars, linfo);
2180 ✗ (chars, linfo) := endDefIdent(chars, linfo, id);
2181 ✗ then (chars, linfo, {});
2182
2183 else
2184 algorithm
2185 ✗ if Flags.isSet(Flags.FAILTRACE) then
2186 ✗ Debug.trace("!!!Parse error - TplParser.recordTags failed at " + inLineInfo.parseInfo.fileName + ": " + String(inLineInfo.lineNumber) + ".\n");
2187 end if;
2188 then (inChars, inLineInfo, {});
2189
2190 end matchcontinue;
2191 end recordTags;
2192 /*
2193 inputFunArgs:
2194 'input' typeSig:ts identifier:id stringComment
2195 inputFunArgs:iargs
2196 => (id,ts) :: iargs
2197 |
2198 _ => {}
2199 */
2200 public function inputFunArgs
2201 input list<String> inChars;
2202 input LineInfo inLineInfo;
2203
2204 output list<String> outChars;
2205 output LineInfo outLineInfo;
2206 output TplAbsyn.TypedIdents outTypedIdents;
2207 algorithm
2208 (outChars, outLineInfo, outTypedIdents) := matchcontinue (inChars, inLineInfo)
2209 local
2210 list<String> chars;
2211 LineInfo linfo;
2212 TplAbsyn.Ident id;
2213 TplAbsyn.TypedIdents inargs;
2214 TplAbsyn.TypeSignature ts;
2215
2216 case ("i"::"n"::"p"::"u"::"t":: chars, linfo)
2217 algorithm
2218 ✗ afterKeyword(chars);
2219 ✗ (chars, linfo) := interleave(chars, linfo);
2220 ✗ (chars, linfo, ts) := typeSigNoOpt(chars, linfo);
2221 ✗ (chars, linfo) := interleave(chars, linfo);
2222 ✗ (chars, linfo, id) := identifierNoOpt(chars,linfo);
2223 ✗ (chars, linfo) := interleave(chars, linfo);
2224 ✗ (chars, linfo) := stringComment(chars, linfo);
2225 ✗ (chars, linfo) := interleave(chars, linfo);
2226 ✗ (chars, linfo) := semicolon(chars, linfo);
2227 ✗ (chars, linfo) := interleave(chars, linfo);
2228 ✗ (chars, linfo, inargs) := inputFunArgs(chars, linfo);
2229 ✗ then (chars, linfo, (id,ts) :: inargs);
2230
2231 else (inChars, inLineInfo, {});
2232
2233 end matchcontinue;
2234 end inputFunArgs;
2235 /*
2236 outputFunArgs:
2237 'output' typeSig:ts identifier:id stringComment ';'
2238 outputFunArgs:oargs
2239 => (id,ts) :: oargs
2240 |
2241 _ => {}
2242 */
2243 public function outputFunArgs
2244 input list<String> inChars;
2245 input LineInfo inLineInfo;
2246
2247 output list<String> outChars;
2248 output LineInfo outLineInfo;
2249 output TplAbsyn.TypedIdents outTypedIdents;
2250 algorithm
2251 (outChars, outLineInfo, outTypedIdents) := matchcontinue (inChars, inLineInfo)
2252 local
2253 list<String> chars;
2254 LineInfo linfo;
2255 TplAbsyn.Ident id;
2256 TplAbsyn.TypedIdents outargs;
2257 TplAbsyn.TypeSignature ts;
2258
2259 case ("o"::"u"::"t"::"p"::"u"::"t":: chars, linfo)
2260 algorithm
2261 ✗ afterKeyword(chars);
2262 ✗ (chars, linfo) := interleave(chars, linfo);
2263 ✗ (chars, linfo, ts) := typeSigNoOpt(chars, linfo);
2264 ✗ (chars, linfo) := interleave(chars, linfo);
2265 ✗ (chars, linfo, id) := identifierNoOpt(chars,linfo);
2266 ✗ (chars, linfo) := interleave(chars, linfo);
2267 ✗ (chars, linfo) := stringComment(chars, linfo);
2268 ✗ (chars, linfo) := interleave(chars, linfo);
2269 ✗ (chars, linfo) := semicolon(chars, linfo);
2270 ✗ (chars, linfo) := interleave(chars, linfo);
2271 ✗ (chars, linfo, outargs) := outputFunArgs(chars, linfo);
2272 ✗ then (chars, linfo, (id,ts) :: outargs);
2273
2274 else (inChars, inLineInfo, {});
2275
2276 end matchcontinue;
2277 end outputFunArgs;
2278
2279 /*
2280 typeVars(tyvars):
2281 'replaceable' 'type' identifier:id 'subtypeof' 'Any' ';'
2282 typeVars(id :: tyvars):tyvars
2283 => tyvars
2284 |
2285 _ => tyvars
2286 */
2287 public function typeVars
2288 input list<String> inChars;
2289 input LineInfo inLineInfo;
2290 input list<TplAbsyn.Ident> inTyVars;
2291
2292 output list<String> outChars;
2293 output LineInfo outLineInfo;
2294 output list<TplAbsyn.Ident> outTyVars;
2295 algorithm
2296 (outChars, outLineInfo, outTyVars) := matchcontinue (inChars, inLineInfo, inTyVars)
2297 local
2298 list<String> chars;
2299 LineInfo linfo;
2300 TplAbsyn.Ident id;
2301 list<TplAbsyn.Ident> tyvars;
2302
2303 case ("r"::"e"::"p"::"l"::"a"::"c"::"e"::"a"::"b"::"l"::"e":: chars, linfo, tyvars)
2304 algorithm
2305 ✗ afterKeyword(chars);
2306 ✗ (chars, linfo) := interleaveExpectKeyWord(chars, linfo, {"t","y","p","e"}, true);
2307 ✗ (chars, linfo) := interleave(chars, linfo);
2308 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
2309 ✗ (chars, linfo) := interleaveExpectKeyWord(chars, linfo, {"s","u","b","t","y","p","e","o","f"}, true);
2310 ✗ (chars, linfo) := interleaveExpectKeyWord(chars, linfo, {"A","n","y"}, true);
2311 ✗ (chars, linfo) := interleave(chars, linfo);
2312 ✗ (chars, linfo) := semicolon(chars,linfo);
2313 ✗ (chars, linfo) := interleave(chars, linfo);
2314 ✗ (chars, linfo, tyvars) := typeVars(chars, linfo, id::tyvars);
2315 then (chars, linfo, tyvars);
2316
2317 ✗ else (inChars, inLineInfo, inTyVars);
2318
2319 end matchcontinue;
2320 end typeVars;
2321
2322 /*
2323 templDef:
2324 'template' identifier:name
2325 '(' templArgs:args ')' stringComment
2326 templDef_Templ:(exp,lesc,resc)
2327 endDefIdent(name)
2328 => (name, TEMPLATE_DEF(args,lesc,resc,exp))
2329 |
2330 'constant' constantType:ctype identifier:name templDef_Const:td //check ctype
2331 stringComment ';'
2332 => (name, td)
2333 */
2334 public function templDef
2335 input list<String> inChars;
2336 input LineInfo inLineInfo;
2337
2338 output list<String> outChars;
2339 output LineInfo outLineInfo;
2340 output TplAbsyn.Ident outTemplName;
2341 output TplAbsyn.TemplateDef outTemplDef;
2342 algorithm
2343 (outChars, outLineInfo, outTemplName, outTemplDef) := match (inChars, inLineInfo)
2344 local
2345 String lesc, resc;
2346 list<String> chars;
2347 LineInfo linfo;
2348 TplAbsyn.Ident name;
2349 TplAbsyn.TemplateDef td;
2350 TplAbsyn.TypeSignature ctype, ctypeLit;
2351 TplAbsyn.TypedIdents args;
2352 TplAbsyn.Expression exp;
2353
2354 case ("t"::"e"::"m"::"p"::"l"::"a"::"t"::"e":: chars, linfo)
2355 algorithm
2356 ✗ afterKeyword(chars);
2357 ✗ (chars, linfo) := interleave(chars, linfo);
2358 ✗ (chars, linfo, name) := identifierNoOpt(chars, linfo);
2359 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "(");
2360 ✗ (chars, linfo) := interleave(chars, linfo);
2361 ✗ (chars, linfo, args) := templArgs(chars, linfo);
2362 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
2363 ✗ (chars, linfo) := interleave(chars, linfo);
2364 ✗ (chars, linfo) := stringComment(chars, linfo);
2365 ✗ (chars, linfo) := interleave(chars, linfo);
2366 ✗ (chars, linfo, exp, lesc, resc) := templDef_Templ(chars, linfo);
2367 ✗ (chars, linfo) := interleave(chars, linfo);
2368 ✗ (chars, linfo) := endDefIdent(chars, linfo, name);
2369 ✗ then (chars, linfo, name, TplAbsyn.TEMPLATE_DEF(args,lesc,resc,exp));
2370
2371 case ("c"::"o"::"n"::"s"::"t"::"a"::"n"::"t" :: chars, linfo)
2372 algorithm
2373 ✗ afterKeyword(chars);
2374 ✗ (chars, linfo) := interleave(chars, linfo);
2375 ✗ (chars, linfo, ctype) := constantType(chars, linfo);
2376 ✗ (chars, linfo) := interleave(chars, linfo);
2377 ✗ (chars, linfo, name) := identifierNoOpt(chars, linfo);
2378 ✗ (chars, linfo) := interleave(chars, linfo);
2379 ✗ (chars, linfo, td, ctypeLit) := templDef_Const(chars, linfo);
2380 ✗ (chars, linfo) := checkConstantType(chars, linfo, ctype, ctypeLit);
2381 ✗ (chars, linfo) := interleave(chars, linfo);
2382 ✗ (chars, linfo) := stringComment(chars, linfo);
2383 ✗ (chars,linfo) := interleave(chars, linfo);
2384 ✗ (chars,linfo) := semicolon(chars, linfo);
2385 ✗ then (chars, linfo, name, td);
2386 end match;
2387 end templDef;
2388
2389 /*
2390 templDef_Const:
2391 '=' stringConstant:strRevList
2392 => STR_TOKEN_DEF(makeStrTokFromRevStrList(strRevList))
2393 |
2394 '=' literalConstant:(str,litType)
2395 => LITERAL_DEF(str, litType)
2396 */
2397 public function templDef_Const
2398 input list<String> inChars;
2399 input LineInfo inLineInfo;
2400
2401 output list<String> outChars;
2402 output LineInfo outLineInfo;
2403 output TplAbsyn.TemplateDef outTemplDef;
2404 output TplAbsyn.TypeSignature outConstType;
2405 algorithm
2406 (outChars, outLineInfo, outTemplDef, outConstType) := matchcontinue (inChars, inLineInfo)
2407 local
2408 String str;
2409 list<String> chars, strRevList;
2410 LineInfo linfo;
2411 Tpl.StringToken st;
2412 TplAbsyn.TypeSignature litType;
2413
2414 case ("=" :: chars, linfo)
2415 algorithm
2416 ✗ (chars, linfo) := interleave(chars, linfo);
2417 ✗ (chars, linfo, strRevList) := stringConstant(chars, linfo);
2418 ✗ st := makeStrTokFromRevStrList(strRevList);
2419 ✗ then (chars, linfo, TplAbsyn.STR_TOKEN_DEF(st), TplAbsyn.STRING_TYPE());
2420
2421 case ("=" :: chars, linfo)
2422 algorithm
2423 ✗ (chars, linfo) := interleave(chars, linfo);
2424 ✗ (chars, linfo, str, litType) := literalConstant(chars, linfo);
2425 ✗ then (chars, linfo, TplAbsyn.LITERAL_DEF(str, litType), litType);
2426
2427 //error after = expect constant
2428 case ("=" :: chars, linfo)
2429 algorithm
2430 ✗ linfo := parseError(chars, linfo, "Expected a constant definition after the '='.", true);
2431 ✗ litType := TplAbsyn.UNRESOLVED_TYPE("#Error#");
2432 ✗ then (chars, linfo, TplAbsyn.LITERAL_DEF("#error#", litType),litType);
2433
2434 //error, cannot follow on
2435 case (chars, linfo)
2436 algorithm
2437 ✗ linfo := parseError(chars, linfo, "Expected a constant definition after the position.", true);
2438 litType := TplAbsyn.UNRESOLVED_TYPE("#Error#");
2439 then (chars, linfo, TplAbsyn.TEMPLATE_DEF({},"","",(TplAbsyn.ERROR_EXP(),dummySourceInfo)), litType);
2440
2441
2442 end matchcontinue;
2443 end templDef_Const;
2444
2445 /*
2446 constantType:
2447 'String' => STRING_TYPE()
2448 'Integer' => INTEGER_TYPE()
2449 'Real' => REAL_TYPE()
2450 'Boolean' => BOOLEAN_TYPE()
2451 */
2452 public function constantType
2453 input list<String> inChars;
2454 input LineInfo inLineInfo;
2455
2456 output list<String> outChars;
2457 output LineInfo outLineInfo;
2458 output TplAbsyn.TypeSignature outConstType;
2459 algorithm
2460 (outChars, outLineInfo, outConstType) := matchcontinue (inChars, inLineInfo)
2461 local
2462 list<String> chars;
2463 LineInfo linfo;
2464
2465 case ("S"::"t"::"r"::"i"::"n"::"g" :: chars, linfo)
2466 algorithm
2467 ✗ afterKeyword(chars);
2468 then (chars, linfo, TplAbsyn.STRING_TYPE());
2469
2470 case ("I"::"n"::"t"::"e"::"g"::"e"::"r" :: chars, linfo)
2471 algorithm
2472 ✗ afterKeyword(chars);
2473 then (chars, linfo, TplAbsyn.INTEGER_TYPE());
2474
2475 case ("R"::"e"::"a"::"l":: chars, linfo)
2476 algorithm
2477 ✗ afterKeyword(chars);
2478 then (chars, linfo, TplAbsyn.REAL_TYPE());
2479
2480 case ("B"::"o"::"o"::"l"::"e"::"a"::"n" :: chars, linfo)
2481 algorithm
2482 ✗ afterKeyword(chars);
2483 then (chars, linfo, TplAbsyn.BOOLEAN_TYPE());
2484
2485 //error, no expected type, cannot follow on
2486 case (chars, linfo)
2487 algorithm
2488 ✗ linfo := parseError(chars, linfo, "Expected 'String', 'Integer', 'Real' or 'Boolean' type specification for the constant definition after the position.", false);
2489 then (chars, linfo, TplAbsyn.UNRESOLVED_TYPE("#Error#"));
2490
2491
2492 end matchcontinue;
2493 end constantType;
2494
2495
2496 public function checkConstantType
2497 input list<String> inChars;
2498 input LineInfo inLineInfo;
2499 input TplAbsyn.TypeSignature inConstType;
2500 input TplAbsyn.TypeSignature inConstTypeLiteral;
2501
2502 output list<String> outChars;
2503 output LineInfo outLineInfo;
2504 algorithm
2505 (outChars, outLineInfo) := match (inChars, inLineInfo, inConstType, inConstTypeLiteral)
2506 local
2507 list<String> chars;
2508 LineInfo linfo;
2509 TplAbsyn.TypeSignature ctype, litType;
2510
2511
2512 case (chars, linfo, TplAbsyn.UNRESOLVED_TYPE(_), _)
2513 then (chars, linfo);
2514
2515 case (chars, linfo, _, TplAbsyn.UNRESOLVED_TYPE(_))
2516 then (chars, linfo);
2517
2518 //types resolved, but not equal
2519 case (chars, linfo, ctype, litType) guard not (valueEq(ctype, litType))
2520 algorithm
2521 ✗ linfo := parseError(chars, linfo, "Declared constant type and the type of the constant's definition literal are different.", false);
2522 then (chars, linfo);
2523
2524 //otherwise, error is already reported
2525 else (inChars, inLineInfo);
2526
2527 end match;
2528 end checkConstantType;
2529
2530
2531
2532 /*
2533 templDef_Templ:
2534 '::=' expression(LEsc = '<',REsc = '>'):exp => (exp,'<','>')
2535 ///|
2536 //'$$=' expression(LEsc = '$',REsc = '$'):exp => (exp,'$','$')
2537 */
2538 public function templDef_Templ
2539 input list<String> inChars;
2540 input LineInfo inLineInfo;
2541
2542 output list<String> outChars;
2543 output LineInfo outLineInfo;
2544 output TplAbsyn.Expression outExpression;
2545 output String outLeftEsc;
2546 output String outRightEsc;
2547 algorithm
2548 (outChars, outLineInfo, outExpression, outLeftEsc, outRightEsc) := matchcontinue (inChars, inLineInfo)
2549 local
2550 list<String> chars;
2551 LineInfo linfo;
2552 TplAbsyn.Expression exp;
2553
2554 case (":"::":"::"=" :: chars, linfo)
2555 algorithm
2556 ✗ (chars, linfo) := interleave(chars, linfo);
2557 ✗ (chars, linfo, exp) := expression(chars, linfo, "<", ">", false);
2558 ✗ then (chars, linfo, exp, "<", ">");
2559
2560 //case ("$"::"$"::"=" :: chars, linfo)
2561 // equation
2562 // (chars, linfo) = interleave(chars, linfo);
2563 // (chars, linfo, exp) = expression(chars, linfo, "$", "$", false);
2564 // then (chars, linfo, exp, "$", "$");
2565
2566 //error expect ::= or $$=, try ::=
2567 case (chars, linfo)
2568 algorithm
2569 ✗ failure(":"::":"::"=" :: _ := chars);
2570 //failure("$"::"$"::"=" :: _ = chars);
2571 ✗ linfo := parseError(chars, linfo, "Expected '::=' symbol before a template definition body at the position.", false);
2572 //try the ::= path
2573 ✗ (chars, linfo, exp) := expression(chars, linfo, "<", ">", false);
2574 ✗ then (chars, linfo, exp, "<", ">");
2575
2576 else
2577 algorithm
2578 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!!Parse error - TplParser.templDef_Templ failed.\n");
2579 ✗ then fail();
2580
2581 end matchcontinue;
2582 end templDef_Templ;
2583 /*
2584 templArgs:
2585 //TODO: to be TEXT_REF ... for now only syntax
2586 'Text' '&' identifier:name templArgs_rest:args => (name,TEXT_TYPE())::args
2587 |
2588 typeSig:ts identifier:name templArgs_rest:args => (name,ts)::args
2589 |
2590 _ => {}
2591 */
2592 public function templArgs
2593 input list<String> inChars;
2594 input LineInfo inLineInfo;
2595
2596 output list<String> outChars;
2597 output LineInfo outLineInfo;
2598 output TplAbsyn.TypedIdents outArgs;
2599 algorithm
2600 (outChars, outLineInfo, outArgs) := matchcontinue (inChars, inLineInfo)
2601 local
2602 list<String> chars;
2603 LineInfo linfo;
2604 TplAbsyn.Ident name;
2605 TplAbsyn.TypedIdents args;
2606 TplAbsyn.TypeSignature ts;
2607
2608 //TODO: a HACK!! ... just for now
2609 case ("T"::"e"::"x"::"t":: chars, linfo)
2610 algorithm
2611 ✗ afterKeyword(chars);
2612 ✗ (chars, linfo) := interleave(chars, linfo);
2613 ✗ "&":: chars := chars;
2614 ✗ (chars, linfo) := interleave(chars, linfo);
2615 ✗ (chars, linfo, name) := identifierNoOpt(chars, linfo);
2616 ✗ (chars, linfo) := interleave(chars, linfo);
2617 ✗ (chars, linfo, args) := templArgs_rest(chars, linfo);
2618 ✗ then (chars, linfo, (name,TplAbsyn.TEXT_TYPE())::args);
2619
2620 case (chars, linfo)
2621 algorithm
2622 ✗ (chars, linfo, ts) := typeSig(chars, linfo);
2623 ✗ (chars, linfo) := interleave(chars, linfo);
2624 ✗ (chars, linfo, name) := identifierNoOpt(chars, linfo);
2625 ✗ (chars, linfo) := interleave(chars, linfo);
2626 ✗ (chars, linfo, args) := templArgs_rest(chars, linfo);
2627 ✗ then (chars, linfo, (name,ts)::args);
2628
2629 else (inChars, inLineInfo, {});
2630
2631 end matchcontinue;
2632 end templArgs;
2633 /*
2634 templArg0:
2635 typeSig:ts implicitArgName:name => (name,ts)
2636
2637 */
2638 /*
2639 public function templArg0
2640 input list<String> inChars;
2641 input LineInfo inLineInfo;
2642
2643 output list<String> outChars;
2644 output LineInfo outLineInfo;
2645 output tuple<TplAbsyn.Ident, TplAbsyn.TypeSignature> outArg;
2646 algorithm
2647 (outChars, outLineInfo, outArg) := matchcontinue (inChars, inLineInfo)
2648 local
2649 String lesc, resc;
2650 list<String> chars;
2651 LineInfo linfo;
2652 Boolean isD;
2653 TplAbsyn.PathIdent pid;
2654 list<tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo>> types;
2655 TplAbsyn.Ident name;
2656 TplAbsyn.TemplateDef td;
2657 TplAbsyn.TypedIdents args;
2658 TplAbsyn.Expression exp;
2659 TplAbsyn.TypeSignature ts;
2660
2661 case (chars, linfo)
2662 algorithm
2663 (chars, linfo, ts) = typeSig(chars, linfo);
2664 (chars, linfo) = interleave(chars, linfo);
2665 (chars, name) = implicitArgName(chars);
2666 then (chars, linfo, (name,ts));
2667
2668 end matchcontinue;
2669 end templArg0;
2670 */
2671 /*
2672 implicitArgName:
2673 IDENT:id => id //maybe 'it' explicitly
2674 |
2675 _ => 'it'
2676
2677
2678 public function implicitArgName
2679 input list<String> inChars;
2680
2681 output list<String> outChars;
2682 output TplAbsyn.Ident outArgName;
2683 algorithm
2684 (outChars, outArgName) := matchcontinue (inChars)
2685 local
2686 String lesc, resc;
2687 list<String> chars;
2688 Boolean isD;
2689 TplAbsyn.PathIdent pid;
2690 list<tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo>> types;
2691 TplAbsyn.Ident name;
2692 TplAbsyn.TemplateDef td;
2693 TplAbsyn.TypedIdents args;
2694 TplAbsyn.Expression exp;
2695 TplAbsyn.TypeSignature ts;
2696
2697 case (chars)
2698 algorithm
2699 (chars, name) = identifier(chars);
2700 then (chars, name);
2701
2702 else (inChars, "it");
2703
2704 end matchcontinue;
2705 end implicitArgName;
2706 */
2707
2708
2709 /*
2710 templArgs_rest
2711 ',' typeSig:ts argName_nonIt:name templArgs_rest:rest => (name,ts)::rest
2712 |
2713 _ => {}
2714 */
2715 public function templArgs_rest
2716 input list<String> inChars;
2717 input LineInfo inLineInfo;
2718
2719 output list<String> outChars;
2720 output LineInfo outLineInfo;
2721 output TplAbsyn.TypedIdents outArgs;
2722 algorithm
2723 (outChars, outLineInfo, outArgs) := matchcontinue (inChars, inLineInfo)
2724 local
2725 list<String> chars;
2726 LineInfo linfo;
2727 TplAbsyn.Ident name;
2728 TplAbsyn.TypedIdents args;
2729 TplAbsyn.TypeSignature ts;
2730 TplAbsyn.TypedIdents rest;
2731
2732 //TODO: a HACK!! ... just for now
2733 case ("," :: chars, linfo)
2734 algorithm
2735 ✗ (chars, linfo) := interleave(chars, linfo);
2736 ✗ "T"::"e"::"x"::"t":: chars := chars;
2737 ✗ afterKeyword(chars);
2738 ✗ (chars, linfo) := interleave(chars, linfo);
2739 ✗ "&":: chars := chars;
2740 ✗ (chars, linfo) := interleave(chars, linfo);
2741 ✗ (chars, linfo, name) := identifierNoOpt(chars, linfo);
2742 ✗ (chars, linfo) := interleave(chars, linfo);
2743 ✗ (chars, linfo, args) := templArgs_rest(chars, linfo);
2744 ✗ then (chars, linfo, (name,TplAbsyn.TEXT_TYPE())::args);
2745
2746 case ("," :: chars, linfo)
2747 algorithm
2748 ✗ (chars, linfo) := interleave(chars, linfo);
2749 ✗ (chars, linfo, ts) := typeSigNoOpt(chars, linfo);
2750 ✗ (chars, linfo) := interleave(chars, linfo);
2751 ✗ (chars, linfo, name) := identifierNoOpt(chars, linfo);
2752 //(chars, linfo, name) = argName_nonIt(chars, linfo);
2753 ✗ (chars, linfo) := interleave(chars, linfo);
2754 ✗ (chars, linfo, rest) := templArgs_rest(chars, linfo);
2755 ✗ then (chars, linfo, (name,ts) :: rest);
2756
2757 else (inChars, inLineInfo, {});
2758
2759 end matchcontinue;
2760 end templArgs_rest;
2761
2762 /*
2763 argName_nonIt:
2764 'it' => Error("Implicit argument 'it' appeared at non-fist position in the template argument list. 'it' can be explicitly only as the first argument.")
2765 |
2766 IDENT:id => id
2767 */
2768 /*
2769 public function argName_nonIt
2770 input list<String> inChars;
2771 input LineInfo inLineInfo;
2772
2773 output list<String> outChars;
2774 output LineInfo outLineInfo;
2775 output TplAbsyn.Ident outArgName;
2776 algorithm
2777 (outChars, outLineInfo, outArgName) := matchcontinue (inChars, inLineInfo)
2778 local
2779 String lesc, resc;
2780 list<String> chars, startChars;
2781 LineInfo linfo;
2782 Boolean isD;
2783 TplAbsyn.PathIdent pid;
2784 list<tuple<TplAbsyn.Ident, TplAbsyn.TypeInfo>> types;
2785 TplAbsyn.Ident name;
2786 TplAbsyn.TemplateDef td;
2787 TplAbsyn.TypedIdents args;
2788 TplAbsyn.Expression exp;
2789 TplAbsyn.TypeSignature ts;
2790 TplAbsyn.TypedIdents rest;
2791
2792 case (startChars as ("i"::"t":: chars), linfo)
2793 algorithm
2794 afterKeyword(chars);
2795 (linfo) = parseError(startChars, linfo, "Implicit argument 'it' appeared at non-first position in the template argument list. 'it' can be explicitly only as the first argument.",
2796 false);
2797 //true = Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse error - implicit argument 'it' appeared at non-first position in the template argument list. 'it' can be explicitly only as the first argument.\n");
2798 then (chars, linfo, "#Error-displaced it#");
2799
2800 case (chars, linfo)
2801 algorithm
2802 (chars, linfo, name) = identifierNoOpt(chars, linfo);
2803 then (chars, linfo, name);
2804
2805 end matchcontinue;
2806 end argName_nonIt;
2807 */
2808
2809 /*
2810 expression(lesc,resc):
2811 expressionNoOptions(lesc,resc):exp escapedOptions:opts
2812 => makeEscapedExp(exp, opts)
2813 */
2814 public function expression
2815 input list<String> inChars;
2816 input LineInfo inLineInfo;
2817 input String inLeftEsc;
2818 input String inRightEsc;
2819 input Boolean isOptional;
2820
2821 output list<String> outChars;
2822 output LineInfo outLineInfo;
2823 output TplAbsyn.Expression outExpression;
2824 algorithm
2825 (outChars, outLineInfo, outExpression) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc, isOptional)
2826 local
2827 list<String> chars;
2828 LineInfo linfo;
2829 String lesc, resc;
2830 TplAbsyn.Expression exp;
2831 list<TplAbsyn.EscOption> opts, indexOffsetOption;
2832 //LineColumnNumber startLCN;
2833
2834 case (chars, linfo, lesc, resc, _)
2835 algorithm
2836 //startLCN = captureStartPosition(chars, linfo, 0);
2837 ✗ (chars, linfo, exp, indexOffsetOption) := expressionNoOptions(chars, linfo, lesc, resc);
2838 ✗ (chars, linfo, opts) := escapedOptions(chars, linfo, lesc, resc);
2839 ✗ opts := listAppend(indexOffsetOption, opts);
2840 //exp = makeEscapedExp(exp, listAppend(sopt,opts));
2841 ✗ exp := makeEscapedExp(chars, linfo, exp, opts);
2842 ✗ then (chars, linfo, exp);
2843
2844 case (chars, linfo, _, _, false)
2845 algorithm
2846 ✗ linfo := parseError(chars, linfo, "Expecting an expression - not able to parse from this point.", true);
2847 then (chars, linfo, (TplAbsyn.ERROR_EXP(), dummySourceInfo));
2848
2849 end matchcontinue;
2850 end expression;
2851
2852
2853 public function makeEscapedExp
2854 input list<String> inEndChars;
2855 input LineInfo inEndLineInfo;
2856 input TplAbsyn.Expression inExpression;
2857 input list<TplAbsyn.EscOption> inOptions;
2858 output TplAbsyn.Expression outExpression;
2859 algorithm
2860 outExpression := match (inExpression, inOptions)
2861 local
2862 TplAbsyn.Expression exp;
2863 list<TplAbsyn.EscOption> opts;
2864 SourceInfo sinfo;
2865 case (exp, {}) then exp;
2866 case (exp, opts as (_::_))
2867 algorithm
2868 ✗ sinfo := tplSourceInfo(startPositionFromExp(exp), inEndChars, inEndLineInfo);
2869 ✗ then ((TplAbsyn.ESCAPED(exp, opts), sinfo));
2870 end match;
2871 end makeEscapedExp;
2872
2873 /*
2874 escapedOptions(lesc,resc):
2875 ';' identifier:id escOptionExp(lesc,resc):expOpt escapedOptions(lesc,resc):opts
2876 => (id, expOpt) :: opts
2877 |
2878 _ => {}
2879
2880 */
2881 public function escapedOptions
2882 input list<String> inChars;
2883 input LineInfo inLineInfo;
2884 input String inLeftEsc;
2885 input String inRightEsc;
2886
2887 output list<String> outChars;
2888 output LineInfo outLineInfo;
2889 output list<TplAbsyn.EscOption> outOptions;
2890 algorithm
2891 (outChars, outLineInfo, outOptions) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
2892 local
2893 list<String> chars;
2894 LineInfo linfo;
2895 String lesc, resc;
2896 TplAbsyn.Ident id;
2897 Option<TplAbsyn.Expression> expOpt;
2898 list<TplAbsyn.EscOption> opts;
2899
2900 case (";" :: chars, linfo, lesc, resc)
2901 algorithm
2902 ✗ (chars, linfo) := interleave(chars, linfo);
2903 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
2904 ✗ (chars, linfo) := interleave(chars, linfo);
2905 ✗ (chars, linfo, expOpt) := escOptionExp(chars, linfo, lesc, resc);
2906 ✗ (chars, linfo) := interleave(chars, linfo);
2907 ✗ (chars, linfo, opts) := escapedOptions(chars, linfo, lesc, resc);
2908 ✗ then (chars, linfo, (id, expOpt) :: opts);
2909
2910 else (inChars, inLineInfo, {});
2911
2912 end matchcontinue;
2913 end escapedOptions;
2914
2915 /*
2916 escOptionExp(lesc,resc):
2917 '=' expressionLet(lesc,resc):exp
2918 => SOME(exp)
2919 |
2920 _ => NONE
2921 */
2922 public function escOptionExp
2923 input list<String> inChars;
2924 input LineInfo inLineInfo;
2925 input String inLeftEsc;
2926 input String inRightEsc;
2927
2928 output list<String> outChars;
2929 output LineInfo outLineInfo;
2930 output Option<TplAbsyn.Expression> outExpOption;
2931 algorithm
2932 (outChars, outLineInfo, outExpOption) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
2933 local
2934 list<String> chars;
2935 LineInfo linfo;
2936 String lesc, resc;
2937 TplAbsyn.Expression exp;
2938
2939 case ("=" :: chars, linfo, lesc, resc)
2940 algorithm
2941 ✗ (chars, linfo) := interleave(chars, linfo);
2942 ✗ (chars, linfo, exp) := expressionLet(chars, linfo, lesc, resc);
2943 ✗ then (chars, linfo, SOME(exp));
2944
2945 else (inChars, inLineInfo, NONE());
2946
2947 end matchcontinue;
2948 end escOptionExp;
2949
2950
2951 /* not optional
2952 expressionNoOptions(lesc,resc):
2953 expressionLet(lesc,resc):expLet mapTailOpt(lesc,resc,expLet):exp
2954 => exp
2955 */
2956 public function expressionNoOptions
2957 input list<String> inChars;
2958 input LineInfo inLineInfo;
2959 input String inLeftEsc;
2960 input String inRightEsc;
2961
2962 output list<String> outChars;
2963 output LineInfo outLineInfo;
2964 output TplAbsyn.Expression outExpression;
2965 output list<TplAbsyn.EscOption> outIndexOffsetOption;
2966 algorithm
2967 (outChars, outLineInfo, outExpression, outIndexOffsetOption)
2968 := match (inChars, inLineInfo, inLeftEsc, inRightEsc)
2969 local
2970 list<String> chars;
2971 LineInfo linfo;
2972 String lesc, resc;
2973 TplAbsyn.Expression exp;
2974
2975
2976 case (chars, linfo, lesc, resc)
2977 algorithm
2978 ✗ (chars, linfo, exp) := expressionLet(chars, linfo, lesc, resc);
2979 ✗ (chars, linfo) := interleave(chars, linfo);
2980 ✗ (chars, linfo, exp, outIndexOffsetOption)
2981 := mapTailOpt(chars, linfo, exp, lesc, resc);
2982 then (chars, linfo, exp, outIndexOffsetOption);
2983
2984 end match;
2985 end expressionNoOptions;
2986
2987 /*
2988 mapTailOpt(headExp,lesc,resc):
2989 '|>' matchBinding:mexp
2990 indexedByOpt:idxNmOpt
2991 '=>' expressionLet(lesc,resc):exp => MAP(headExp,mexp,exp)
2992 |
2993 _ => headExp
2994 */
2995 public function mapTailOpt
2996 input list<String> inChars;
2997 input LineInfo inLineInfo;
2998 input TplAbsyn.Expression inHeadExpression;
2999 input String inLeftEsc;
3000 input String inRightEsc;
3001
3002 output list<String> outChars;
3003 output LineInfo outLineInfo;
3004 output TplAbsyn.Expression outExpression;
3005 output list<TplAbsyn.EscOption> outIndexOffsetOption;
3006 algorithm
3007 (outChars, outLineInfo, outExpression, outIndexOffsetOption) := matchcontinue (inChars, inLineInfo, inHeadExpression, inLeftEsc, inRightEsc)
3008 local
3009 list<String> chars;
3010 LineInfo linfo;
3011 String lesc, resc;
3012 Option<TplAbsyn.Ident> idxNmOpt;
3013 TplAbsyn.Expression exp, headExp;
3014 TplAbsyn.MatchingExp mexp;
3015 SourceInfo sinfo;
3016
3017 case ("|"::">":: chars, linfo, headExp, lesc, resc)
3018 algorithm
3019 //afterKeyword(chars);
3020 ✗ (chars, linfo) := interleave(chars, linfo);
3021 ✗ (chars, linfo, mexp) := matchBinding(chars, linfo);
3022 ✗ (chars, linfo) := interleave(chars, linfo);
3023 ✗ (chars, linfo, idxNmOpt, outIndexOffsetOption) := indexedByOpt(chars, linfo, lesc, resc);
3024 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "=");
3025 ✗ (chars, linfo) := expectChar(chars, linfo, ">");
3026 ✗ (chars, linfo) := interleave(chars, linfo);
3027 ✗ (chars, linfo, exp) := expressionLet(chars, linfo, lesc, resc);
3028 ✗ sinfo := tplSourceInfo(startPositionFromExp(headExp), chars, linfo);
3029 ✗ then (chars, linfo, (TplAbsyn.MAP(headExp, mexp, exp, idxNmOpt), sinfo), outIndexOffsetOption);
3030
3031 else (inChars, inLineInfo, inHeadExpression, {});
3032
3033 end matchcontinue;
3034 end mapTailOpt;
3035
3036 /*
3037 indexedByOpt:
3038 'hasindex' identifier:id
3039 => SOME(id)
3040 |
3041 _ => NONE
3042 */
3043 public function indexedByOpt
3044 input list<String> inChars;
3045 input LineInfo inLineInfo;
3046 input String inLeftEsc;
3047 input String inRightEsc;
3048
3049 output list<String> outChars;
3050 output LineInfo outLineInfo;
3051 output Option<TplAbsyn.Ident> outIndexNameOpt;
3052 output list<TplAbsyn.EscOption> outIndexOffsetOption;
3053 algorithm
3054 (outChars, outLineInfo, outIndexNameOpt, outIndexOffsetOption)
3055 := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3056 local
3057 list<String> chars;
3058 LineInfo linfo;
3059 String lesc, resc;
3060 TplAbsyn.Ident id;
3061
3062 case ("h"::"a"::"s"::"i"::"n"::"d"::"e"::"x":: chars, linfo, lesc, resc)
3063 algorithm
3064 ✗ afterKeyword(chars);
3065 ✗ (chars, linfo) := interleave(chars, linfo);
3066 ✗ (chars,linfo,id) := identifierNoOpt(chars,linfo);
3067 ✗ (chars, linfo) := interleave(chars, linfo);
3068 ✗ (chars, linfo, outIndexOffsetOption) := fromOpt(chars, linfo, lesc, resc);
3069 ✗ then (chars, linfo, SOME(id), outIndexOffsetOption);
3070
3071 else (inChars, inLineInfo, NONE(), {});
3072
3073 end matchcontinue;
3074 end indexedByOpt;
3075
3076 /*
3077 fromOpt:
3078 'fromindex' expression_base:expFrom
3079 => { ("$indexOffset", SOME(expFrom)) }
3080 |
3081 _ => {}
3082 */
3083 public function fromOpt
3084 input list<String> inChars;
3085 input LineInfo inLineInfo;
3086 input String inLeftEsc;
3087 input String inRightEsc;
3088
3089 output list<String> outChars;
3090 output LineInfo outLineInfo;
3091 output list<TplAbsyn.EscOption> outIndexOffsetOption;
3092 algorithm
3093 (outChars, outLineInfo, outIndexOffsetOption)
3094 := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3095 local
3096 list<String> chars;
3097 LineInfo linfo;
3098 String lesc, resc;
3099 TplAbsyn.Expression exp;
3100
3101 case ("f"::"r"::"o"::"m"::"i"::"n"::"d"::"e"::"x":: chars, linfo, lesc, resc)
3102 algorithm
3103 ✗ afterKeyword(chars);
3104 ✗ (chars, linfo) := interleave(chars, linfo);
3105 ✗ (chars, linfo, exp) := expression_base(chars, linfo, lesc, resc);
3106 ✗ then (chars, linfo, {(TplAbsyn.indexOffsetOptionId, SOME(exp))});
3107
3108 //deprecated keyword, this check will be removed after some time (if needed)
3109 case ("f"::"r"::"o"::"m":: chars, linfo, lesc, resc)
3110 algorithm
3111 ✗ afterKeyword(chars);
3112 ✗ linfo := parseError(chars, linfo, "Keyword 'from' was changed to 'fromindex', please update your source code here.", false);
3113 ✗ (chars, linfo) := interleave(chars, linfo);
3114 ✗ (chars, linfo, exp) := expression_base(chars, linfo, lesc, resc);
3115 ✗ then (chars, linfo, {(TplAbsyn.indexOffsetOptionId, SOME(exp))});
3116
3117 else (inChars, inLineInfo, {});
3118
3119 end matchcontinue;
3120 end fromOpt;
3121
3122
3123 /*
3124 expressionLet(lesc,resc):
3125 'let' letExp(lesc,resc):lexp concatLetExp_rest(lesc,resc):expLst
3126 => TEMPLATE(lexp::expLst}, "let", ""); //TODO: should be a LET_EXPRESSION()
3127 |
3128 expressionMatch(lesc,resc):exp
3129 */
3130 public function expressionLet
3131 input list<String> inChars;
3132 input LineInfo inLineInfo;
3133 input String inLeftEsc;
3134 input String inRightEsc;
3135
3136 output list<String> outChars;
3137 output LineInfo outLineInfo;
3138 output TplAbsyn.Expression outExpression;
3139 algorithm
3140 (outChars, outLineInfo, outExpression) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3141 local
3142 list<String> chars, startChars;
3143 LineInfo linfo, startLInfo;
3144 String lesc, resc;
3145 TplAbsyn.Expression exp, lexp;
3146 SourceInfo sinfo;
3147
3148 case ("l"::"e"::"t" :: startChars, startLInfo, lesc, resc)
3149 algorithm
3150 ✗ afterKeyword(startChars);
3151 ✗ (chars, linfo) := interleave(startChars, startLInfo);
3152 ✗ (chars, linfo, lexp) := letExp(chars, linfo, lesc, resc);
3153 ✗ (chars, linfo) := interleave(chars, linfo);
3154 ✗ (chars, linfo, exp) := expressionLet(chars, linfo, lesc, resc);
3155 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 3), chars, linfo);
3156 //(chars, linfo, expLst) = concatLetExp_rest(chars, linfo, lesc, resc);
3157 ✗ then (chars, linfo, (TplAbsyn.LET(lexp, exp), sinfo));
3158
3159 case (chars, linfo, lesc, resc)
3160 algorithm
3161 ✗ (chars, linfo, exp) := expressionMatch(chars, linfo, lesc, resc);
3162 then (chars, linfo, exp);
3163
3164 end matchcontinue;
3165 end expressionLet;
3166
3167 /*
3168 concatLetExp_rest(lesc,resc):
3169 'let' letExp(lesc,resc):lexp concatLetExp_rest(lesc,resc):expLst
3170 => lexp::expLst
3171 |
3172 expression(lesc,resc):exp
3173 => {exp}
3174 */
3175 /*
3176 public function concatLetExp_rest
3177 input list<String> inChars;
3178 input LineInfo inLineInfo;
3179 input String inLeftEsc;
3180 input String inRightEsc;
3181
3182 output list<String> outChars;
3183 output LineInfo outLineInfo;
3184 output list<TplAbsyn.Expression> outExpressionList;
3185 algorithm
3186 (outChars, outLineInfo, outExpressionList) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3187 local
3188 list<String> chars;
3189 LineInfo linfo;
3190 String c, lesc, resc;
3191 Boolean isD;
3192 TplAbsyn.Ident id;
3193 TplAbsyn.PathIdent name;
3194 TplAbsyn.TypedIdents fields,inargs,outargs;
3195 TplAbsyn.TypeSignature ts;
3196 Tpl.StringToken st;
3197 TplAbsyn.Expression exp, lexp;
3198 list<TplAbsyn.Expression> expLst;
3199 TplAbsyn.MatchingExp mexp;
3200
3201 case ("l"::"e"::"t":: chars, linfo, lesc, resc)
3202 algorithm
3203 afterKeyword(chars);
3204 (chars, linfo) = interleave(chars, linfo);
3205 (chars, linfo, lexp) = letExp(chars, linfo, lesc, resc);
3206 (chars, linfo) = interleave(chars, linfo);
3207 (chars, linfo, expLst) = concatLetExp_rest(chars, linfo, lesc, resc);
3208 then (chars, linfo, lexp::expLst);
3209
3210 case (chars, linfo, lesc, resc)
3211 algorithm
3212 (chars, linfo, exp) = expressionMatch(chars, linfo, lesc, resc);
3213 then (chars, linfo, {exp});
3214
3215 end matchcontinue;
3216 end concatLetExp_rest;
3217 */
3218
3219 /*
3220 must not fail - not optional, at least one must match
3221 letExp(lesc,resc):
3222 '&' identifier:id '=' 'buffer' expression(lesc,resc):exp
3223 => TEXT_CREATE(id,exp)
3224 |
3225 '&' identifier:id '+=' expression(lesc,resc):exp
3226 => TEXT_ADD(id,exp)
3227 |
3228 '()' '=' pathIdent:name funCall(name,lesc,resc):exp
3229 => exp //TODO: noRetCall expression should be here
3230 |
3231 identifier:id '=' expression(lesc,resc):exp
3232 => TEXT_CREATE(id,exp) //TODO: !! a HACK for now
3233
3234 //TODO:
3235 |
3236 letBinding:bd '=' expression(lesc,resc):exp
3237 => LET_BINDING(bd, exp)
3238 */
3239 public function letExp
3240 input list<String> inChars;
3241 input LineInfo inLineInfo;
3242 input String inLeftEsc;
3243 input String inRightEsc;
3244
3245 output list<String> outChars;
3246 output LineInfo outLineInfo;
3247 output TplAbsyn.Expression outExpression;
3248 algorithm
3249 (outChars, outLineInfo, outExpression) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3250 local
3251 list<String> chars, startChars;
3252 LineInfo linfo, startLInfo;
3253 String lesc, resc;
3254 TplAbsyn.PathIdent name;
3255 TplAbsyn.Expression exp;
3256 list<TplAbsyn.Expression> args;
3257 TplAbsyn.Ident id;
3258 //LineColumnNumber startLCN;
3259 SourceInfo sinfo;
3260
3261 case ("&":: startChars, startLInfo, lesc, resc)
3262 algorithm
3263 ✗ (chars, linfo) := interleave(startChars, startLInfo);
3264 ✗ (chars, id) := identifier(chars);
3265 //capture only ident span for the letExp, the exp will have its own span
3266 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 1), chars, linfo);
3267 ✗ (chars, linfo) := interleave(chars, linfo);
3268 ✗ "=":: chars := chars;
3269 ✗ (chars, linfo) := interleaveExpectKeyWord(chars, linfo, {"b","u","f","f","e","r"}, false);
3270 ✗ (chars, linfo) := interleave(chars, linfo);
3271 ✗ (chars, linfo, exp) := expression(chars, linfo, lesc, resc, false);
3272 ✗ then (chars, linfo, (TplAbsyn.TEXT_CREATE(id, exp), sinfo));
3273
3274 case ("&":: startChars, startLInfo, lesc, resc)
3275 algorithm
3276 ✗ (chars, linfo) := interleave(startChars, startLInfo);
3277 ✗ (chars, id) := identifier(chars);
3278 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 1), chars, linfo);
3279 ✗ (chars, linfo) := interleave(chars, linfo);
3280 ✗ "+"::"=":: chars := chars;
3281 ✗ (chars, linfo) := interleave(chars, linfo);
3282 ✗ (chars, linfo, exp) := expression(chars, linfo, lesc, resc, false);
3283 ✗ then (chars, linfo, (TplAbsyn.TEXT_ADD(id, exp), sinfo));
3284
3285 case ("&":: startChars, startLInfo, _, _)
3286 algorithm
3287 ✗ (chars, linfo) := interleave(startChars, startLInfo);
3288 ✗ (chars, linfo,_) := identifierNoOpt(chars, linfo);
3289 ✗ linfo := parseError(chars, linfo, "Expecting a '=' or '+=' text variable creation/addition (&var = exp or &var += exp) at the position.", true);
3290 then (chars, linfo, (TplAbsyn.ERROR_EXP(), dummySourceInfo));
3291
3292
3293 case ("("::")":: startChars, startLInfo, lesc, resc)
3294 algorithm
3295 ✗ (chars, linfo) := interleaveExpectChar(startChars, startLInfo, "=");
3296 ✗ (chars, linfo) := interleave(chars, linfo);
3297 ✗ (chars, linfo, name) := pathIdentNoOpt(chars, linfo);
3298 ✗ (chars, linfo) := interleave(chars, linfo);
3299 ✗ (chars, linfo, TplAbsyn.FUN_CALL(name, args)) := funCall(chars, linfo, name, lesc, resc);
3300 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 2), chars, linfo);
3301 ✗ then (chars, linfo, (TplAbsyn.NORET_CALL(name, args), sinfo));
3302
3303 case ("("::")":: startChars, startLInfo, _, _)
3304 algorithm
3305 ✗ (chars, linfo) := interleaveExpectChar(startChars, startLInfo, "=");
3306 ✗ (chars, linfo) := interleave(chars, linfo);
3307 ✗ (chars, linfo,_) := pathIdentNoOpt(chars, linfo);
3308 //(chars, linfo) = interleaveExpectChar(chars, linfo, "(");
3309 ✗ linfo := parseError(chars, linfo, "Expecting a non-return function call( let () = [package.]funName(args,...) ) at the position.", true);
3310 then (chars, linfo, (TplAbsyn.ERROR_EXP(), dummySourceInfo));
3311
3312 //TODO: to be letBinding:bd '=' expression(lesc,resc):exp => LET_BINDING(bd, exp)
3313 case (startChars, startLInfo, lesc, resc)
3314 algorithm
3315 ✗ (chars, linfo, id) := identifierNoOpt(startChars, startLInfo);
3316 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 0), chars, linfo);
3317 ✗ (chars, linfo) := interleave(chars, linfo);
3318 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "=");
3319 ✗ (chars, linfo) := interleave(chars, linfo);
3320 ✗ (chars, linfo, exp) := expression(chars, linfo, lesc, resc, false);
3321 ✗ then (chars, linfo, (TplAbsyn.TEXT_CREATE(id, exp), sinfo));
3322
3323 //case (chars, linfo, lesc, resc)
3324 // equation
3325 // linfo = parseError(chars, linfo, "Expecting a let-expression: no-return function call ( ()=funName(...) ) or text variable binding/creation/addition (var = exp, &var = exp or &var += exp) at the position.", true);
3326 // then (chars, linfo, TplAbsyn.ERROR_EXP());
3327
3328
3329 else
3330 algorithm
3331 ✗ if Flags.isSet(Flags.FAILTRACE) then
3332 ✗ Debug.trace("!!!Parse error - TplParser.letExp failed.\n");
3333 end if;
3334 ✗ then fail();
3335 end matchcontinue;
3336 end letExp;
3337
3338
3339 /*
3340 expressionMatch(lesc,resc):
3341 matchExp(lesc,resc):exp
3342 => exp
3343 |
3344 expressionIf(lesc,resc):exp
3345 => exp
3346 */
3347 public function expressionMatch
3348 input list<String> inChars;
3349 input LineInfo inLineInfo;
3350 input String inLeftEsc;
3351 input String inRightEsc;
3352
3353 output list<String> outChars;
3354 output LineInfo outLineInfo;
3355 output TplAbsyn.Expression outExpression;
3356 algorithm
3357 (outChars, outLineInfo, outExpression) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3358 local
3359 list<String> chars;
3360 LineInfo linfo;
3361 String lesc, resc;
3362 TplAbsyn.Expression exp;
3363
3364 case (chars, linfo, lesc, resc)
3365 algorithm
3366 ✗ (chars, linfo, exp) := matchExp(chars, linfo, lesc, resc);
3367 then (chars, linfo, exp);
3368
3369 case (chars, linfo, lesc, resc)
3370 algorithm
3371 ✗ (chars, linfo, exp) := expressionIf(chars, linfo, lesc, resc);
3372 then (chars, linfo, exp);
3373
3374 end matchcontinue;
3375 end expressionMatch;
3376
3377 /*
3378 expressionIf(lesc,resc):
3379 conditionExp(lesc,resc):exp
3380 => exp
3381 |
3382 expressionPlus(lesc,resc):exp
3383 => exp
3384 */
3385 public function expressionIf
3386 input list<String> inChars;
3387 input LineInfo inLineInfo;
3388 input String inLeftEsc;
3389 input String inRightEsc;
3390
3391 output list<String> outChars;
3392 output LineInfo outLineInfo;
3393 output TplAbsyn.Expression outExpression;
3394 algorithm
3395 (outChars, outLineInfo, outExpression) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3396 local
3397 list<String> chars;
3398 LineInfo linfo;
3399 String lesc, resc;
3400 TplAbsyn.Expression exp;
3401
3402 case (chars, linfo, lesc, resc)
3403 algorithm
3404 ✗ (chars, linfo, exp) := conditionExp(chars, linfo, lesc, resc);
3405 then (chars, linfo, exp);
3406
3407 case (chars, linfo, lesc, resc)
3408 algorithm
3409 ✗ (chars, linfo, exp) := expressionPlus(chars, linfo, lesc, resc);
3410 then (chars, linfo, exp);
3411
3412 end matchcontinue;
3413 end expressionIf;
3414
3415
3416 /*
3417 expressionPlus(lesc,resc):
3418 expression_base(lesc,resc):bexp plusTailOpt(lesc,resc,bexp):exp
3419 => exp
3420 */
3421 public function expressionPlus
3422 input list<String> inChars;
3423 input LineInfo inLineInfo;
3424 input String inLeftEsc;
3425 input String inRightEsc;
3426
3427 output list<String> outChars;
3428 output LineInfo outLineInfo;
3429 output TplAbsyn.Expression outExpression;
3430 algorithm
3431 (outChars, outLineInfo, outExpression) := match (inChars, inLineInfo, inLeftEsc, inRightEsc)
3432 local
3433 list<String> chars;
3434 LineInfo linfo;
3435 String lesc, resc;
3436 TplAbsyn.Expression exp;
3437
3438 case (chars, linfo, lesc, resc)
3439 algorithm
3440 ✗ (chars, linfo, exp) := expression_base(chars, linfo, lesc, resc);
3441 ✗ (chars, linfo) := interleave(chars, linfo);
3442 ✗ (chars, linfo, exp) := plusTailOpt(chars, linfo, exp, lesc, resc);
3443 then (chars, linfo, exp);
3444
3445 end match;
3446 end expressionPlus;
3447
3448 /*
3449 plusTailOpt(lesc,resc,bexp):
3450 '+' expression_base(lesc,resc):exp concatExp_rest(lesc,resc):expLst // concatenation same as "<expression><expression>"
3451 => TEMPLATE(bexp::exp::expLst, "+", "");
3452 |
3453 _ => bexp
3454 */
3455 public function plusTailOpt
3456 input list<String> inChars;
3457 input LineInfo inLineInfo;
3458 input TplAbsyn.Expression inBaseExpression;
3459 input String inLeftEsc;
3460 input String inRightEsc;
3461
3462 output list<String> outChars;
3463 output LineInfo outLineInfo;
3464 output TplAbsyn.Expression outExpression;
3465 algorithm
3466 (outChars, outLineInfo, outExpression) := matchcontinue (inChars, inLineInfo, inBaseExpression, inLeftEsc, inRightEsc)
3467 local
3468 list<String> chars;
3469 LineInfo linfo;
3470 String lesc, resc;
3471 TplAbsyn.Expression exp, bexp;
3472 list<TplAbsyn.Expression> expLst;
3473 SourceInfo sinfo;
3474
3475 case ("+" :: chars, linfo, bexp, lesc, resc)
3476 algorithm
3477 ✗ (chars, linfo) := interleave(chars, linfo);
3478 ✗ (chars, linfo, exp) := expression_base(chars, linfo, lesc, resc);
3479 ✗ (chars, linfo) := interleave(chars, linfo);
3480 ✗ (chars, linfo, expLst) := concatExp_rest(chars, linfo, lesc, resc);
3481 ✗ sinfo := tplSourceInfo(startPositionFromExp(bexp), chars, linfo);
3482 ✗ then (chars, linfo, (TplAbsyn.TEMPLATE(bexp::exp::expLst, "+", ""), sinfo));
3483
3484 else (inChars, inLineInfo, inBaseExpression);
3485
3486 end matchcontinue;
3487 end plusTailOpt;
3488
3489
3490 /*
3491 concatExp_rest(lesc,resc):
3492 '+' expression_base(lesc,resc):exp concatExp_rest(lesc,resc):expLst => exp::expLst
3493 |
3494 _ => {}
3495 */
3496 public function concatExp_rest
3497 input list<String> inChars;
3498 input LineInfo inLineInfo;
3499 input String inLeftEsc;
3500 input String inRightEsc;
3501
3502 output list<String> outChars;
3503 output LineInfo outLineInfo;
3504 output list<TplAbsyn.Expression> outExpressionList;
3505 algorithm
3506 (outChars, outLineInfo, outExpressionList) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3507 local
3508 list<String> chars;
3509 LineInfo linfo;
3510 String lesc, resc;
3511 TplAbsyn.Expression exp;
3512 list<TplAbsyn.Expression> expLst;
3513
3514 case ("+":: chars, linfo, lesc, resc)
3515 algorithm
3516 ✗ (chars, linfo) := interleave(chars, linfo);
3517 ✗ (chars, linfo, exp) := expression_base(chars, linfo, lesc, resc);
3518 ✗ (chars, linfo) := interleave(chars, linfo);
3519 ✗ (chars, linfo, expLst) := concatExp_rest(chars, linfo, lesc, resc);
3520 ✗ then (chars, linfo, exp::expLst);
3521
3522 else (inChars, inLineInfo, {});
3523
3524 end matchcontinue;
3525 end concatExp_rest;
3526
3527
3528 /*
3529 expression_base(lesc,resc):
3530 stringConstant:strRevList
3531 => STR_TOKEN(makeStrTokFromRevStrList(strRevList))
3532 |
3533 literalConstant:(str,litType)
3534 => LITERAL(str,litType)
3535 |
3536 templateExp(lesc,resc)
3537 |
3538 '{' '}' => MAP_ARG_LIST({})
3539 |
3540 '{' expressionPlus(lesc,resc):exp expressionList_rest(lesc,resc):expLst '}' // list construction with possible mixed scalars and lists
3541 // useful in map/concatenation context
3542 => MAP_ARG_LIST(exp::expLst)
3543 |
3544 '(' expression(lesc,resc):exp ')'
3545 => exp
3546 |
3547 '&' identifier:id
3548 => BOUND_VALUE(IDENT(name)) //TODO: ref Text buffer
3549 |// TODO: create an optional/error reporting variant of pathIdent
3550 pathIdent:name boundValueOrFunCall(name,lesc,resc):exp => exp
3551 */
3552 public function expression_base
3553 input list<String> inChars;
3554 input LineInfo inLineInfo;
3555 input String inLeftEsc;
3556 input String inRightEsc;
3557
3558 output list<String> outChars;
3559 output LineInfo outLineInfo;
3560 output TplAbsyn.Expression outExpression;
3561 algorithm
3562 (outChars, outLineInfo, outExpression) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3563 local
3564 list<String> chars, startChars, strRevList;
3565 LineInfo linfo, startLInfo;
3566 String lesc, resc, str;
3567 TplAbsyn.Ident id;
3568 TplAbsyn.PathIdent name;
3569 TplAbsyn.TypeSignature ts;
3570 Tpl.StringToken st;
3571 TplAbsyn.Expression exp;
3572 TplAbsyn.ExpressionBase expB;
3573 list<TplAbsyn.Expression> expLst;
3574 //LineColumnNumber startLCN;
3575 SourceInfo sinfo;
3576
3577 case (startChars, startLInfo, _, _)
3578 algorithm
3579 //startLCN = captureStartPosition(chars, linfo, 0);
3580 ✗ (chars, linfo, strRevList) := stringConstant(startChars, startLInfo);
3581 ✗ st := makeStrTokFromRevStrList(strRevList);
3582 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 0), chars, linfo);
3583 ✗ then (chars, linfo, (TplAbsyn.STR_TOKEN(st), sinfo));
3584
3585 case (startChars, startLInfo, _, _)
3586 algorithm
3587 ✗ (chars, linfo, str, ts) := literalConstant(startChars, startLInfo);
3588 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 0), chars, linfo);
3589 ✗ then (chars, linfo, (TplAbsyn.LITERAL(str, ts), sinfo));
3590
3591 case (chars, linfo, lesc, resc)
3592 algorithm
3593 ✗ (chars, linfo, exp) := templateExp(chars, linfo, lesc, resc);
3594 then (chars, linfo, exp);
3595
3596 case ("{" :: startChars, startLInfo, _, _)
3597 algorithm
3598 ✗ (chars, linfo) := interleave(startChars, startLInfo);
3599 ✗ "}" :: chars := chars;
3600 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 1), chars, linfo);
3601 ✗ then (chars, linfo, (TplAbsyn.MAP_ARG_LIST({}), sinfo));
3602
3603 case ("{" :: startChars, startLInfo, lesc, resc)
3604 algorithm
3605 ✗ (chars, linfo) := interleave(startChars, startLInfo);
3606 ✗ (chars, linfo, exp) := expressionPlus(chars, linfo, lesc, resc);
3607 ✗ (chars, linfo) := interleave(chars, linfo);
3608 ✗ (chars, linfo, expLst) := expressionList_rest(chars, linfo, lesc, resc);
3609 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "}");
3610 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 1), chars, linfo);
3611 ✗ then (chars, linfo, (TplAbsyn.MAP_ARG_LIST(exp::expLst), sinfo));
3612
3613 case ("(" :: startChars, startLInfo, lesc, resc)
3614 algorithm
3615 ✗ (chars, linfo) := interleave(startChars, startLInfo);
3616 ✗ (chars, linfo, exp) := expression(chars, linfo, lesc, resc, false);
3617 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
3618 ✗ then (chars, linfo, exp);
3619
3620 //TODO: be a ref Text buffer
3621 case ("&" :: startChars, startLInfo, _, _)
3622 algorithm
3623 ✗ (chars, linfo) := interleave(startChars, startLInfo);
3624 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
3625 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 1), chars, linfo);
3626 ✗ then (chars, linfo, (TplAbsyn.BOUND_VALUE(TplAbsyn.IDENT(id)), sinfo));
3627
3628 case (startChars, startLInfo, lesc, resc)
3629 algorithm
3630 ✗ (chars, linfo, name) := pathIdent(startChars, startLInfo);
3631 ✗ (chars, linfo) := interleave(chars, linfo);
3632 ✗ (chars, linfo, expB) := boundValueOrFunCall(chars, linfo, name, lesc, resc);
3633 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 0), chars, linfo);
3634 ✗ then (chars, linfo, (expB, sinfo));
3635
3636 end matchcontinue;
3637 end expression_base;
3638
3639
3640 /*
3641 boundValueOrFunCall(name,lesc,resc):
3642 funCall(name,lesc,resc):exp => exp
3643 |
3644 _ => BOUND_VALUE(name)
3645 */
3646 public function boundValueOrFunCall
3647 input list<String> inChars;
3648 input LineInfo inLineInfo;
3649 input TplAbsyn.PathIdent inName;
3650 input String inLeftEsc;
3651 input String inRightEsc;
3652
3653 output list<String> outChars;
3654 output LineInfo outLineInfo;
3655 output TplAbsyn.ExpressionBase outExpressionBase;
3656 algorithm
3657 (outChars, outLineInfo, outExpressionBase) :=
3658 matchcontinue (inChars, inLineInfo, inName, inLeftEsc, inRightEsc)
3659 local
3660 list<String> chars;
3661 LineInfo linfo;
3662 String lesc, resc;
3663 TplAbsyn.PathIdent name;
3664 TplAbsyn.ExpressionBase expB;
3665
3666 case (chars, linfo, name, lesc, resc)
3667 algorithm
3668 ✗ (chars, linfo, expB) := funCall(chars, linfo, name, lesc, resc);
3669 then (chars, linfo, expB);
3670
3671 ✗ else (inChars, inLineInfo, TplAbsyn.BOUND_VALUE(inName));
3672
3673 end matchcontinue;
3674 end boundValueOrFunCall;
3675
3676 /*
3677 //may fail
3678 funCall(name,lesc,resc):
3679 '(' ')' => FUN_CALL(name,{})
3680 |
3681 '(' expression(lesc,resc):exp expressionList_rest(lesc,resc):expLst ')' //template or intrinsic function
3682 => FUN_CALL(name,exp::expLst)
3683 */
3684 public function funCall
3685 input list<String> inChars;
3686 input LineInfo inLineInfo;
3687 input TplAbsyn.PathIdent inName;
3688 input String inLeftEsc;
3689 input String inRightEsc;
3690
3691 output list<String> outChars;
3692 output LineInfo outLineInfo;
3693 output TplAbsyn.ExpressionBase outExpressionBase;
3694 algorithm
3695 (outChars, outLineInfo, outExpressionBase) := matchcontinue (inChars, inLineInfo, inName, inLeftEsc, inRightEsc)
3696 local
3697 list<String> chars;
3698 LineInfo linfo;
3699 String lesc, resc;
3700 TplAbsyn.PathIdent name;
3701 TplAbsyn.Expression exp;
3702 list<TplAbsyn.Expression> expLst;
3703
3704 case ("(":: chars, linfo, name, _, _)
3705 algorithm
3706 ✗ (chars, linfo) := interleave(chars, linfo);
3707 ✗ ")" :: chars := chars;
3708 ✗ then (chars, linfo, TplAbsyn.FUN_CALL(name,{}));
3709
3710 case ("(":: chars, linfo, name, lesc, resc)
3711 algorithm
3712 ✗ (chars, linfo) := interleave(chars, linfo);
3713 ✗ (chars, linfo, exp) := expressionPlus(chars, linfo, lesc, resc);
3714 ✗ (chars, linfo) := interleave(chars, linfo);
3715 ✗ (chars, linfo, expLst) := expressionList_rest(chars, linfo, lesc, resc);
3716 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
3717 ✗ then (chars, linfo, TplAbsyn.FUN_CALL(name, exp::expLst));
3718
3719 end matchcontinue;
3720 end funCall;
3721
3722 /*
3723 expressionList_rest(lesc,resc):
3724 ',' expressionPlus(lesc,resc):exp expressionList_rest(lesc,resc):expLst => exp::expLst
3725 |
3726 _ => {}
3727 */
3728 public function expressionList_rest
3729 input list<String> inChars;
3730 input LineInfo inLineInfo;
3731 input String inLeftEsc;
3732 input String inRightEsc;
3733
3734 output list<String> outChars;
3735 output LineInfo outLineInfo;
3736 output list<TplAbsyn.Expression> outExpressionList;
3737 algorithm
3738 (outChars, outLineInfo, outExpressionList) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
3739 local
3740 list<String> chars;
3741 LineInfo linfo;
3742 String lesc, resc;
3743 TplAbsyn.Expression exp;
3744 list<TplAbsyn.Expression> expLst;
3745
3746 case (",":: chars, linfo, lesc, resc)
3747 algorithm
3748 ✗ (chars, linfo) := interleave(chars, linfo);
3749 ✗ (chars, linfo, exp) := expressionPlus(chars, linfo, lesc, resc);
3750 ✗ (chars, linfo) := interleave(chars, linfo);
3751 ✗ (chars, linfo, expLst) := expressionList_rest(chars, linfo, lesc, resc);
3752 ✗ then (chars, linfo, exp::expLst);
3753
3754 else (inChars, inLineInfo, {});
3755
3756 end matchcontinue;
3757 end expressionList_rest;
3758
3759
3760 /*
3761 stringConstant:
3762 '"' doubleQuoteConst({},{}):stRevLst
3763 => stRevLst
3764 |
3765 //'%'(lquot) stripFirstNewLine verbatimConst(Rquote(lquot),{},{}):stRevLst
3766 // => stRevLst
3767 //|
3768 '\\n' escUnquotedChars({}, {"\n"}):stRevLst
3769 => stRevLst
3770 |
3771 '\\' escChar:c escUnquotedChars({c}, {}):stRevLst
3772 => stRevLst
3773 */
3774 public function stringConstant
3775 input list<String> inChars;
3776 input LineInfo inLineInfo;
3777
3778 output list<String> outChars;
3779 output LineInfo outLineInfo;
3780 output list<String> outStrRevList;
3781 algorithm
3782 (outChars, outLineInfo, outStrRevList) := matchcontinue (inChars, inLineInfo)
3783 local
3784 list<String> chars, startChars, stRevLst;
3785 LineInfo linfo, startLinfo;
3786 String c;
3787 Option<String> optError;
3788
3789 case (startChars as ("\"" :: chars), startLinfo)
3790 algorithm
3791 ✗ (chars, linfo, stRevLst, optError) := doubleQuoteConst(chars, startLinfo,{},{});
3792 ✗ linfo := parseErrorPrevPositionOpt(startChars, startLinfo, linfo, optError, true);
3793 ✗ then (chars, linfo, stRevLst);
3794
3795 /*
3796 case (startChars as ("%"::lquot:: chars), startLinfo)
3797 algorithm
3798 (chars, linfo) = stripFirstNewLine(chars, startLinfo);
3799 rquot = rightVerbatimConstQuote(lquot);
3800 (chars, linfo, stRevLst, optError) = verbatimConst(chars, linfo, rquot,{},{});
3801 linfo = parseErrorPrevPositionOpt(startChars, startLinfo, linfo, optError, true);
3802 then (chars, linfo, stRevLst);
3803 */
3804
3805 case ("\\"::"n":: chars, linfo)
3806 algorithm
3807 ✗ (chars, linfo, stRevLst) := escUnquotedChars(chars, linfo, {},{"\n"});
3808 then (chars, linfo, stRevLst);
3809
3810 case ("\\":: c :: chars, linfo)
3811 algorithm
3812 ✗ c := escChar(c);
3813 ✗ (chars, linfo,stRevLst) := escUnquotedChars(chars, linfo, {c},{});
3814 then (chars, linfo, stRevLst);
3815
3816 end matchcontinue;
3817 end stringConstant;
3818
3819 /*
3820 //not optional, must not fail
3821 literalConstant:
3822 //(+|-)?d*(.d+)?(('e'|'E')(+|-)?d+)?
3823 plusMinus:pm digits:ds dotNumber:(dn,ts) exponent(ts):(ex,ts)
3824 => (pm+ stringCharListString(ds)+dn+ex, ts) //validate the number - must have integer part or dotpart
3825 |
3826 'true' => ("true", BOOLEAN_TYPE())
3827 |
3828 'false' => ("false", BOOLEAN_TYPE())
3829 */
3830 public function literalConstant
3831 input list<String> inChars;
3832 input LineInfo inLineInfo;
3833
3834 output list<String> outChars;
3835 output LineInfo outLineInfo;
3836 output String outConstantValue;
3837 output TplAbsyn.TypeSignature outConstantType;
3838 algorithm
3839 (outChars, outLineInfo, outConstantValue, outConstantType) := matchcontinue (inChars, inLineInfo)
3840 local
3841 list<String> chars, ds;
3842 LineInfo linfo;
3843 String pm, dn,ex, num;
3844 TplAbsyn.TypeSignature ts;
3845
3846 case (chars, linfo)
3847 algorithm
3848 ✗ (chars, pm) := plusMinus(chars);
3849 ✗ (chars, linfo) := interleave(chars, linfo);
3850 ✗ (chars, ds) := digits(chars);
3851 ✗ (chars, dn, ts) := dotNumber(chars);
3852 //validate the number - must have integer part or dotpart
3853 ✗ num := stringCharListString(ds)+dn;
3854 ✗ true := stringLength(num) > 0;
3855 ✗ (chars, ex, ts) := exponent(chars,ts);
3856 ✗ num := pm + num + ex;
3857 ✗ then (chars, linfo, num, ts);
3858
3859 case ("t"::"r"::"u"::"e" :: chars, linfo)
3860 algorithm
3861 ✗ afterKeyword(chars);
3862 ✗ then (chars, linfo, "true",TplAbsyn.BOOLEAN_TYPE());
3863
3864 case ("f"::"a"::"l"::"s"::"e" :: chars, linfo)
3865 algorithm
3866 ✗ afterKeyword(chars);
3867 ✗ then (chars, linfo, "false",TplAbsyn.BOOLEAN_TYPE());
3868
3869 end matchcontinue;
3870 end literalConstant;
3871
3872
3873 public function stripFirstNewLine
3874 input list<String> inChars;
3875 input LineInfo inLineInfo;
3876 output list<String> outChars;
3877 output LineInfo outLineInfo;
3878 algorithm
3879 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo)
3880 local
3881 list<String> chars;
3882 LineInfo linfo;
3883 case (chars, linfo)
3884 algorithm
3885 ✗ (chars, linfo) := newLine(chars, linfo);
3886 then (chars, linfo);
3887 ✗ else (inChars, inLineInfo);
3888 end matchcontinue;
3889 end stripFirstNewLine;
3890
3891 public function rightVerbatimConstQuote
3892 input String inLeftQuote;
3893 output String outRightQuote;
3894 algorithm
3895 outRightQuote := match inLeftQuote
3896 case "(" then ")";
3897 case "{" then "}";
3898 case "<" then ">";
3899 case "[" then "]";
3900 else inLeftQuote;
3901 end match;
3902 end rightVerbatimConstQuote;
3903
3904 /*
3905 doubleQuoteConst(accChars,accStrList):
3906 '"' => stringCharListString(listReverse(accChars)) :: accStrList
3907 |
3908 newLine doubleQuoteConst({}, stringCharListString(listReverse('\n'::accChars))::accStrList):stRevLst
3909 => stRevLst
3910 |
3911 '\\n' doubleQuoteConst({}, stringCharListString(listReverse('\n'::accChars))::accStrList):stRevLst
3912 => stRevLst
3913 |
3914 '\\'escChar:c doubleQuoteConst(c::accChars,accStrList):stRevLst
3915 => stRevLst
3916 |
3917 c doubleQuoteConst(c::accChars,accStrList):stRevLst
3918 => stRevLst
3919 |
3920 Error end of file
3921 */
3922 public function doubleQuoteConst
3923 input list<String> inChars;
3924 input LineInfo inLineInfo;
3925 input list<String> inAccChars;
3926 input list<String> inAccStrList;
3927
3928 output list<String> outChars;
3929 output LineInfo outLineInfo;
3930 output list<String> outStrRevList;
3931 output Option<String> outError;
3932 algorithm
3933 (outChars, outLineInfo, outStrRevList, outError) := matchcontinue (inChars, inLineInfo, inAccChars, inAccStrList)
3934 local
3935 list<String> chars, restChars, accChars, accStrList, stRevLst;
3936 LineInfo linfo;
3937 String c, str, errStr;
3938 Option<String> optError;
3939
3940 case ("\"" :: chars, linfo, accChars, accStrList)
3941 algorithm
3942 ✗ str := stringCharListString(listReverse(accChars));
3943 ✗ then (chars, linfo, str :: accStrList,NONE());
3944
3945 //escaped new line
3946 case ("\\"::"n" :: chars, linfo, accChars, accStrList)
3947 algorithm
3948 ✗ str := stringCharListString(listReverse("\n"::accChars));
3949 ✗ (chars, linfo,stRevLst, optError) := doubleQuoteConst(chars, linfo,{},str :: accStrList);
3950 then (chars, linfo, stRevLst, optError);
3951
3952 case ("\\":: c :: chars, linfo, accChars, accStrList)
3953 algorithm
3954 ✗ c := escChar(c);
3955 ✗ (chars, linfo,stRevLst,optError) := doubleQuoteConst(chars, linfo, c::accChars, accStrList);
3956 then (chars, linfo, stRevLst,optError);
3957
3958 //inline new line
3959 case (chars, linfo, accChars, accStrList)
3960 algorithm
3961 ✗ (chars, linfo) := newLine(chars, linfo);
3962 ✗ str := stringCharListString(listReverse("\n"::accChars));
3963 ✗ (chars, linfo,stRevLst,optError) := doubleQuoteConst(chars, linfo,{},str :: accStrList);
3964 then (chars, linfo, stRevLst, optError);
3965
3966 case (chars as (c :: restChars), linfo, accChars, accStrList)
3967 algorithm
3968 ✗ failure(newLine(chars, linfo));
3969 ✗ (chars, linfo,stRevLst,optError) := doubleQuoteConst(restChars, linfo, c::accChars, accStrList);
3970 then (chars, linfo, stRevLst,optError);
3971
3972 case ( {}, linfo, accChars, accStrList)
3973 algorithm
3974 ✗ str := stringCharListString(listReverse(accChars));
3975 errStr := "Unmatched \" \" quotes for a string constant - reached end of file.";
3976 ✗ if Flags.isSet(Flags.FAILTRACE) then
3977 ✗ Debug.trace("Parse error - TplParser.doubleQuoteConst - " + errStr + "\n");
3978 end if;
3979 ✗ then ({}, linfo, str :: accStrList, SOME(errStr));
3980
3981 end matchcontinue;
3982 end doubleQuoteConst;
3983
3984 /*
3985 escChar:
3986 ( '\'' | '"' | '?' | '\\' | 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | ' ' )
3987 => the escaped char
3988
3989 */
3990 public function escChar
3991 input String inEscChar;
3992 output String outTheChar;
3993 algorithm
3994 outTheChar := match inEscChar
3995 case "'" then "'";
3996 case "\"" then "\"";
3997 case "?" then "?";
3998 case "\\" then "\\";
3999 /*
4000 //TODO: Error in the .srz or .c compilation(\r)
4001 case ("a" ) then "\a";
4002 case ("b" ) then "\b";
4003 case ("f" ) then "\f";
4004 case ("r" ) then "\r";
4005 case ("v" ) then "\v";
4006 */
4007 case "n" then "\n";
4008 case "t" then "\t";
4009 case " " then " ";
4010 end match;
4011 end escChar;
4012
4013 /*
4014 verbatimConst(rquot, accChars, accStrList):
4015 //strip a last inline new line
4016 newLine (rquot)'%' => stringCharListString(listReverse(accChars)) :: accStrList
4017 |
4018 (rquot)'%' => stringCharListString(listReverse(accChars)) :: accStrList
4019 |
4020 newLine verbatimConst(rquot, {}, stringCharListString(listReverse('\n'::accChars))::accStrList):stRevLst
4021 => stRevLst
4022 |
4023 c verbatimConst(rquot, c::accChars,accStrList):stRevLst
4024 => stRevLst
4025 |
4026 Error end of file
4027 */
4028 public function verbatimConst
4029 input list<String> inChars;
4030 input LineInfo inLineInfo;
4031 input String inRightQuote;
4032 input list<String> inAccChars;
4033 input list<String> inAccStrList;
4034
4035 output list<String> outChars;
4036 output LineInfo outLineInfo;
4037 output list<String> outStrRevList;
4038 output Option<String> outError;
4039 algorithm
4040 (outChars, outLineInfo, outStrRevList, outError) := matchcontinue (inChars, inLineInfo, inRightQuote, inAccChars, inAccStrList)
4041 local
4042 list<String> chars, restChars, accChars, accStrList, stRevLst;
4043 LineInfo linfo;
4044 String rquot,c,str, errStr;
4045 Option<String> optError;
4046
4047 //strip a last inline new line
4048 case (chars, linfo, rquot, accChars, accStrList)
4049 algorithm
4050 ✗ (chars, linfo) := newLine(chars, linfo);
4051 ✗ c :: "%" :: chars := chars;
4052 ✗ true := stringEq(c, rquot);
4053 ✗ str := stringCharListString(listReverse(accChars));
4054 ✗ then (chars, linfo, str :: accStrList,NONE());
4055
4056 case (c :: "%" :: chars, linfo, rquot, accChars, accStrList)
4057 algorithm
4058 ✗ true := stringEq(c, rquot);
4059 ✗ str := stringCharListString(listReverse(accChars));
4060 ✗ then (chars, linfo, str :: accStrList,NONE());
4061
4062 case (chars, linfo, rquot, accChars, accStrList)
4063 algorithm
4064 ✗ (chars, linfo) := newLine(chars, linfo);
4065 ✗ str := stringCharListString(listReverse("\n"::accChars));
4066 ✗ (chars, linfo, stRevLst, optError) := verbatimConst(chars, linfo,rquot,{}, str :: accStrList);
4067 then (chars, linfo, stRevLst, optError);
4068
4069 case (chars as (c :: restChars), linfo, rquot, accChars, accStrList)
4070 algorithm
4071 ✗ failure(newLine(chars, linfo));
4072 ✗ (chars, linfo, stRevLst, optError) := verbatimConst(restChars, linfo, rquot, c::accChars, accStrList);
4073 then (chars, linfo, stRevLst, optError);
4074
4075 case ( {}, linfo, rquot, accChars, accStrList)
4076 algorithm
4077 ✗ str := stringCharListString(listReverse(accChars));
4078 ✗ errStr := "Unmatched %"+rquot+" "+rquot+"% quotes for a verbatim string constant - reached end of file.";
4079 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse error - TplParser.verbatimConst - " + errStr + "\n");
4080 ✗ then ({}, linfo, str :: accStrList, SOME(errStr));
4081
4082 end matchcontinue;
4083 end verbatimConst;
4084
4085 /*
4086 escUnquotedChars(accChars,accStrList):
4087 '\\n' escUnquotedChars({}, stringCharListString(listReverse('\n'::accChars)) :: accStrList):stRevLst
4088 => stRevLst
4089 |
4090 '\\' escChar:c escUnquotedChars(c::accChars, accStrList):stRevLst
4091 => stRevLst
4092 |
4093 _ => stringCharListString(listReverse(accChars)) :: accStrList
4094
4095 */
4096 public function escUnquotedChars
4097 input list<String> inChars;
4098 input LineInfo inLineInfo;
4099 input list<String> inAccChars;
4100 input list<String> inAccStrList;
4101
4102 output list<String> outChars;
4103 output LineInfo outLineInfo;
4104 output list<String> outStrRevList;
4105 algorithm
4106 (outChars, outLineInfo, outStrRevList) := matchcontinue (inChars, inLineInfo, inAccChars, inAccStrList)
4107 local
4108 list<String> chars, accChars, accStrList, stRevLst;
4109 LineInfo linfo;
4110 String c, str;
4111
4112 case ("\\":: "n" :: chars, linfo, accChars, accStrList)
4113 algorithm
4114 ✗ str := stringCharListString(listReverse("\n"::accChars));
4115 ✗ (chars, linfo,stRevLst) := escUnquotedChars(chars, linfo,{},str :: accStrList);
4116 then (chars, linfo, stRevLst);
4117
4118 case ("\\":: c :: chars, linfo, accChars, accStrList)
4119 algorithm
4120 ✗ c := escChar(c);
4121 ✗ (chars, linfo,stRevLst) := escUnquotedChars(chars, linfo, c::accChars, accStrList);
4122 then (chars, linfo, stRevLst);
4123
4124 case (chars, linfo, accChars, accStrList)
4125 algorithm
4126 ✗ str := stringCharListString(listReverse(accChars));
4127 ✗ then (chars, linfo, str :: accStrList);
4128
4129 end matchcontinue;
4130 end escUnquotedChars;
4131
4132
4133 public function makeStrTokFromRevStrList
4134 input list<String> inRevStrList;
4135 output Tpl.StringToken outStringToken;
4136 algorithm
4137 outStringToken := match inRevStrList
4138 local
4139 list<String> strList;
4140 String str;
4141
4142 case { str }
4143 ✗ then Tpl.ST_STRING(str);
4144
4145 case { "", "\n" }
4146 then Tpl.ST_NEW_LINE();
4147
4148 case { "" , str}
4149 ✗ then Tpl.ST_LINE(str);
4150
4151 case "" :: strList
4152 algorithm
4153 ✗ strList := listReverse(strList);
4154 ✗ then Tpl.ST_STRING_LIST(strList, true);
4155
4156 case strList as (_ :: _)
4157 algorithm
4158 ✗ strList := listReverse(strList);
4159 ✗ then Tpl.ST_STRING_LIST(strList, false);
4160
4161 // should not ever happen
4162 else
4163 algorithm
4164 ✗ true := Flags.isSet(Flags.FAILTRACE);
4165 ✗ Debug.trace("Parse invalid operation error - TplParser.makeStrTokFromRevStrList failed (an empty string list passed?) .\n");
4166 ✗ then fail();
4167
4168 end match;
4169 end makeStrTokFromRevStrList;
4170
4171 /*
4172 plusMinus:
4173 '+' => "+"
4174 |
4175 '-' => "-"
4176 |
4177 _ => ""
4178 */
4179 public function plusMinus
4180 input list<String> inChars;
4181
4182 output list<String> outChars;
4183 output String outSign;
4184 algorithm
4185 (outChars, outSign) := match inChars
4186 local
4187 list<String> chars;
4188 String char;
4189
4190 case char :: chars guard char=="+" or char=="-"
4191 then (chars, char);
4192
4193 else
4194 then (inChars, "");
4195
4196 end match;
4197 end plusMinus;
4198 /*
4199 digits:
4200 [0-9]:d digits:ds => d::ds
4201 |
4202 _ => {}
4203 */
4204 public function digits
4205 input list<String> inChars;
4206
4207 output list<String> outChars;
4208 output list<String> outDigits;
4209 algorithm
4210 (outChars, outDigits) := matchcontinue inChars
4211 local
4212 String d;
4213 list<String> chars, ds;
4214 Integer i;
4215
4216 case d :: chars
4217 algorithm
4218 ✗ i := stringCharInt(d);
4219 //[0-9]
4220 ✗ true := ( 48/*0*/ <= i and i <= 57/*9*/);
4221 ✗ (chars,ds) := digits(chars);
4222 ✗ then (chars, d::ds);
4223
4224 case chars
4225 then (chars, {});
4226
4227 end matchcontinue;
4228 end digits;
4229 /*
4230 dotNumber:
4231 '.' digits:ds => (stringCharListString(ds), REAL_TYPE())
4232 |
4233 _ => INTEGER_TYPE()
4234 */
4235 public function dotNumber
4236 input list<String> inChars;
4237
4238 output list<String> outChars;
4239 output String outDotNumber;
4240 output TplAbsyn.TypeSignature outLitType;
4241 algorithm
4242 (outChars, outDotNumber, outLitType) := matchcontinue inChars
4243 local
4244 String dn;
4245 list<String> chars, ds;
4246
4247 case "." :: chars
4248 algorithm
4249 ✗ (chars,ds) := digits(chars);
4250 ✗ _::_ := ds; //some digits must be there
4251 ✗ dn := "." + stringCharListString(ds);
4252 then (chars, dn, TplAbsyn.REAL_TYPE());
4253
4254 else (inChars, "", TplAbsyn.INTEGER_TYPE());
4255
4256 end matchcontinue;
4257 end dotNumber;
4258
4259 /*
4260 exponent(typ):
4261 'e' plusMinus:pm digits:ds => ("e"+pm+stringCharListString(ds), REAL_TYPE())
4262 |
4263 'E' plusMinus:pm digits:ds => ("E"+pm+stringCharListString(ds), REAL_TYPE())
4264 |
4265 => ("",typ)
4266 */
4267 public function exponent
4268 input list<String> inChars;
4269 input TplAbsyn.TypeSignature inLitType;
4270
4271 output list<String> outChars;
4272 output String outExponent;
4273 output TplAbsyn.TypeSignature outLitType;
4274 algorithm
4275 (outChars,outExponent,outLitType) := matchcontinue inChars
4276 local
4277 String ex,pm;
4278 list<String> chars, ds;
4279
4280 case "e" :: chars
4281 algorithm
4282 ✗ (chars,pm) := plusMinus(chars);
4283 ✗ (chars,ds) := digits(chars);
4284 ✗ _::_ := ds; //some digits must be there
4285 ✗ ex := "e" + pm + stringCharListString(ds);
4286 then (chars, ex, TplAbsyn.REAL_TYPE());
4287
4288 case "E" :: chars
4289 algorithm
4290 ✗ (chars,pm) := plusMinus(chars);
4291 ✗ (chars,ds) := digits(chars);
4292 ✗ _::_ := ds; //some digits must be there
4293 ✗ ex := "E" + pm + stringCharListString(ds);
4294 then (chars, ex, TplAbsyn.REAL_TYPE());
4295
4296 else (inChars, "", inLitType);
4297
4298 end matchcontinue;
4299 end exponent;
4300
4301 /*
4302 templateExp(lesc, resc):
4303 "'" stripFirstNewLine templateBody(lesc, resc, isSingleQuote = true, {},{},0)
4304 |
4305 '<<' stripFirstNewLine templateBody(lesc, resc, isSingleQuote = false,{},{},0 )
4306 */
4307 public function templateExp
4308 input list<String> inChars;
4309 input LineInfo inLineInfo;
4310 input String inLeftEsc;
4311 input String inRightEsc;
4312
4313 output list<String> outChars;
4314 output LineInfo outLineInfo;
4315 output TplAbsyn.Expression outExpression;
4316 algorithm
4317 (outChars, outLineInfo, outExpression) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
4318 local
4319 list<String> chars, startChars, solChars;
4320 LineInfo linfo, startLInfo;
4321 String lesc, resc;
4322 TplAbsyn.ExpressionBase expB;
4323 Integer baseInd, lineInd;
4324 SourceInfo sinfo;
4325
4326 case ("'" :: startChars, startLInfo, lesc, resc)
4327 algorithm
4328 //single quotes has no special treatment of indent and new lines
4329 //i.e., it takes O as the base indent, and it counts every new line
4330 ✗ (chars, linfo, expB) := templateBody(startChars, startLInfo, lesc, resc, true, {},{},0);
4331 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 1), chars, linfo);
4332 ✗ then (chars, linfo, (expB, sinfo));
4333
4334 case ("<"::"<":: startChars, startLInfo as LINE_INFO(startOfLineChars = solChars), lesc, resc)
4335 algorithm
4336 //the base indent is the indent of the line where the << appears
4337 ✗ (_, baseInd) := lineIndent(solChars,0);
4338 //the case when nothing visible is after <<
4339 ✗ (chars, linfo) := takeSpaceAndNewLine(startChars, startLInfo);
4340 //(chars, linfo) = templStripFirstNewLine(chars, linfo);
4341 ✗ (chars, linfo, expB) := templateBody(chars, linfo, lesc, resc, false, {}, {}, baseInd);
4342 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 2), chars, linfo);
4343 ✗ then (chars, linfo, (expB, sinfo));
4344
4345 //special treatment when some non-space is right after <<
4346 case ("<"::"<":: startChars, startLInfo as LINE_INFO(startOfLineChars = solChars), lesc, resc)
4347 algorithm
4348 //the base indent is the indent of the line where the << appears
4349 ✗ (_, baseInd) := lineIndent(solChars,0);
4350 //some non-space char(s) is after <<
4351 ✗ failure( takeSpaceAndNewLine(startChars, startLInfo) );
4352 ✗ (chars, lineInd) := lineIndent(startChars,0);
4353 //correct the indent of the line right after << to baseInd
4354 ✗ lineInd := lineInd + baseInd;
4355 ✗ (chars, linfo, expB) := restOfTemplLine(chars, startLInfo, lesc, resc, false, {}, {}, baseInd, lineInd);
4356 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 2), chars, linfo);
4357 ✗ then (chars, linfo, (expB, sinfo));
4358 end matchcontinue;
4359 end templateExp;
4360
4361
4362
4363 /*
4364 //optional, may fail
4365 takeSpaceAndNewLine:
4366 newLine
4367 |
4368 ' ' takeSpaceAndNewLine
4369 |
4370 '\t' takeSpaceAndNewLine
4371 */
4372 public function takeSpaceAndNewLine
4373 input list<String> inChars;
4374 input LineInfo inLineInfo;
4375 output list<String> outChars;
4376 output LineInfo outLineInfo;
4377 algorithm
4378 (outChars, outLineInfo) := matchcontinue (inChars, inLineInfo)
4379 local
4380 list<String> chars;
4381 LineInfo linfo;
4382 String char;
4383
4384 case (chars, linfo)
4385 algorithm
4386 ✗ (chars, linfo) := newLine(chars, linfo);
4387 then (chars, linfo);
4388
4389 case (char :: chars, linfo) guard char==" " or char =="\t"
4390 algorithm
4391 ✗ (chars, linfo) := takeSpaceAndNewLine(chars, linfo);
4392 then (chars, linfo);
4393 end matchcontinue;
4394 end takeSpaceAndNewLine;
4395
4396 /*
4397 templateBody(lesc, resc, isSingleQuote, expList, indStack, actInd):
4398 lineIndent(0):lineInd
4399 restOfTemplLine(lesc, resc, isSingleQuote, expList, indStack, actInd, lineInd, {}):exp
4400 => exp
4401 */
4402 public function templateBody
4403 input list<String> inChars;
4404 input LineInfo inLineInfo;
4405 input String inLeftEsc;
4406 input String inRightEsc;
4407 input Boolean inIsSingleQuote;
4408 input list<TplAbsyn.Expression> inExpressionList;
4409 input list<tuple<Integer,list<TplAbsyn.Expression>>> inIndentStack;
4410 input Integer inActualIndent;
4411
4412 output list<String> outChars;
4413 output LineInfo outLineInfo;
4414 output TplAbsyn.ExpressionBase outExpressionBase;
4415 protected
4416 Integer lindent;
4417 algorithm
4418 ✗ (outChars, lindent) := lineIndent(inChars, 0);
4419 ✗ (outChars, outLineInfo, outExpressionBase) := restOfTemplLine(outChars,
4420 inLineInfo, inLeftEsc, inRightEsc, inIsSingleQuote, inExpressionList,
4421 inIndentStack, inActualIndent, lindent);
4422 end templateBody;
4423
4424 /*
4425 lineIndent(ind):
4426 ' ' lineIndent(ind+1):n => n
4427 |
4428 '\t' lineIndent(ind+4):n => n
4429 |
4430 _ => ind
4431
4432 */
4433 public function lineIndent
4434 input list<String> inChars;
4435 input Integer inLineIndent;
4436
4437 output list<String> outChars;
4438 output Integer outLineIndent;
4439 algorithm
4440 (outChars, outLineIndent) := match inChars
4441 ✗ case " " :: outChars then lineIndent(outChars, inLineIndent + 1);
4442 ✗ case "\t" :: outChars then lineIndent(outChars, inLineIndent + TabSpaces);
4443 else (inChars, inLineIndent);
4444 end match;
4445 end lineIndent;
4446 /*
4447 // & ... no interleave
4448 restOfTemplLine(lesc, resc, isSingleQuote, expList, indStack, actInd, lineInd, accStrChars):
4449 //(lesc)'#' nonTemplateExprWithOpts(lesc,resc):eexp '#'(resc)
4450 // { (expList, indStack, actInd) = onEscapedExp(eexp, expList, indStack, actInd, lineInd, accStrChars) }
4451 // & restOfTemplLine(lesc,resc,isSingleQuote, expList, indStack, actInd, actInd, {}):exp
4452 // => exp
4453 //
4454 //|
4455 (lesc) (resc) // a comment | empty expression ... ignore completely
4456 & restOfTemplLineAfterEmptyExp(lesc,resc,isSingleQuote, expList, indStack, actInd, lineInd, accStrChars):exp
4457 => exp
4458 |
4459 (lesc) '%' expression(lesc,resc):eexp (resc)
4460 { (expList, indStack, actInd) = onEscapedExp(eexp, expList, indStack, actInd, lineInd, accStrChars) }
4461 & restOfTemplLine(lesc,resc,isSingleQuote, expList, indStack, actInd, actInd, {}):exp
4462 => exp
4463
4464 | // on \n
4465 newLine
4466 { (expList, indStack, actInd) = onNewLine(expList, indStack, actInd, lineInd, accStrChars) }
4467 & templateBody(lesc, resc, isSingleQuote, expList, indStack, actInd):exp
4468 => exp
4469
4470 | //end
4471 (isSingleQuote = true) "'"
4472 =>
4473 onTemplEnd(expList, indStack, actInd, lineInd, accStrChars)
4474
4475 | //end
4476 (isSingleQuote = false) '>>'
4477 =>
4478 onTemplEnd(expList, indStack, actInd, lineInd, accStrChars)
4479
4480 |
4481 '\' & ( '\' | "'" | (lesc) | (resc) ):c
4482 & restOfTemplLine(lesc, resc, isSingleQuote, expList, indStack, actInd, lineInd, c :: accStrChars) : exp
4483 => exp
4484 |
4485 any:c
4486 & restOfTemplLine(lesc, resc, isSingleQuote, expList, indStack, actInd, lineInd, c :: accStrChars) : exp
4487 => exp
4488 */
4489 public function restOfTemplLine
4490 input list<String> inChars;
4491 input LineInfo inLineInfo;
4492 input String inLeftEsc;
4493 input String inRightEsc;
4494 input Boolean inIsSingleQuote;
4495 input list<TplAbsyn.Expression> inExpressionList;
4496 input list<tuple<Integer,list<TplAbsyn.Expression>>> inIndentStack;
4497 input Integer inActualIndent;
4498 input Integer inLineIndent;
4499
4500 output list<String> outChars = inChars;
4501 output LineInfo outLineInfo = inLineInfo;
4502 output TplAbsyn.ExpressionBase outExpressionBase;
4503 protected
4504 list<TplAbsyn.Expression> expl = inExpressionList;
4505 Integer lindent = inLineIndent;
4506 Integer aindent = inActualIndent;
4507 list<tuple<Integer, list<TplAbsyn.Expression>>> ind_stack = inIndentStack;
4508
4509 String char, next_char;
4510 TplAbsyn.Expression exp;
4511 list<String> chars, acc_chars = {};
4512 Option<String> err_opt;
4513 LineInfo linfo;
4514 algorithm
4515 try
4516 while true loop
4517 ✗ char :: outChars := outChars;
4518
4519 // isSingleQuote = true
4520 ✗ if inIsSingleQuote and char == "'" then
4521 ✗ expl := onTemplEnd(false, expl, ind_stack, aindent, lindent, acc_chars);
4522 ✗ outExpressionBase := makeTemplateFromExpList(expl, "'", "'");
4523 ✗ return;
4524 end if;
4525
4526 // Peek at the next character.
4527 ✗ next_char :: chars := outChars;
4528
4529 // isSingleQuote = false => << >>
4530 ✗ if not inIsSingleQuote and char == ">" and next_char == ">" then
4531 ✗ expl := onTemplEnd(true, expl, ind_stack, aindent, lindent, acc_chars);
4532 ✗ outExpressionBase := makeTemplateFromExpList(expl, "<<", ">>");
4533 outChars := chars;
4534 ✗ return;
4535 // New line.
4536 elseif char == "\r" or char == "\n" then
4537 ✗ (outChars, linfo) := newLine(char :: outChars, outLineInfo);
4538 ✗ (expl, ind_stack, aindent, err_opt) := onNewLine(expl, ind_stack, aindent, lindent, acc_chars);
4539 ✗ outLineInfo := parseErrorPrevPositionOptInfoChars(outLineInfo, linfo, err_opt, false);
4540 ✗ (outChars, lindent) := lineIndent(outChars, 0);
4541 acc_chars := {};
4542 // <% something %>
4543 elseif char == inLeftEsc and next_char == "%" then
4544 ✗ (outChars, linfo) := interleave(chars, outLineInfo);
4545 ✗ char :: next_char :: chars := outChars;
4546
4547 // <% %> empty expression ... i.e. comment or a break in line that is not parsed.
4548 ✗ if char == "%" and next_char == inRightEsc then
4549 ✗ (outChars, outLineInfo, lindent) :=
4550 dropNewLineAfterEmptyExp(chars, linfo, lindent, acc_chars);
4551 else // <% expression %>
4552 ✗ (outChars, linfo, exp) := expression(outChars, linfo, inLeftEsc, inRightEsc, false);
4553 ✗ (outChars, linfo) := interleaveExpectChar(outChars, linfo, "%");
4554 ✗ (outChars, linfo) := expectChar(outChars, linfo, inRightEsc);
4555 ✗ (expl, ind_stack, aindent, err_opt) :=
4556 onEscapedExp(exp, expl, ind_stack, aindent, lindent, acc_chars);
4557 ✗ outLineInfo := parseErrorPrevPositionOptInfoChars(outLineInfo, linfo, err_opt, false);
4558 acc_chars := {};
4559 end if;
4560 // Anything else.
4561 else
4562 acc_chars := char :: acc_chars;
4563 end if;
4564 end while;
4565 else
4566 end try;
4567 ✗ outChars := {};
4568 ✗ outLineInfo := parseError({}, inLineInfo, "Not able to parse the text template expression from the point.", true);
4569 outExpressionBase := TplAbsyn.ERROR_EXP();
4570
4571 // //<# #> or $# #$
4572 // /*
4573 // case (startChars as (c :: "#" :: chars), startLinfo, lesc, resc, isSQ, expLst, indStack, actInd, lineInd, accChars)
4574 // equation
4575 // equality( c = lesc );
4576 // (chars, linfo) = interleave(chars, startLinfo);
4577 // (chars, linfo, eexp) = nonTemplateExprWithOpts(chars, linfo, lesc, resc);
4578 // (chars, linfo) = interleaveExpectChar(chars, linfo, "#");
4579 // (chars, linfo) = expectChar(chars, linfo, resc);
4580 // //("#" :: c :: chars) = chars;
4581 // //equality( c = resc );
4582 // (chars, linfo, lineInd) = dropNewLineAfterEmptyExp(chars, linfo, lineInd, accChars);
4583 // (expLst, indStack, actInd, errOpt) = onEscapedExp(eexp, expLst, indStack, actInd, lineInd, accChars);
4584 // LINE_INFO(startOfLineChars = solChars) = startLinfo;
4585 // linfo = parseErrorPrevPositionOpt(solChars, startLinfo, linfo, errOpt, false);
4586 // (chars, linfo, exp) = restOfTemplLine(chars, linfo, lesc, resc, isSQ, expLst, indStack, actInd, actInd, {});
4587 // then (chars, linfo, exp);
4588 // */
4589 //
4590 // //??? should we allow escaping at all ??
4591 // /* experimentally we will disallow it ... use "" constants in like 'hey son<%"'"%>s brother'
4592 // // \ will be taken literally, '\\' and <<\\>> are both double-backslash !
4593 // case ("\\":: c :: chars, linfo, lesc, resc, isSQ, expLst, indStack, actInd, lineInd, accChars)
4594 // equation
4595 // true = (c == "\\" or c == "'" or c == lesc or c == resc);
4596 // (chars, linfo, exp) = restOfTemplLine(chars, linfo, lesc, resc, isSQ, expLst, indStack, actInd, lineInd, c :: accChars);
4597 // then (chars, linfo, exp);
4598 // */
4599 end restOfTemplLine;
4600
4601 public function dropNewLineAfterEmptyExp
4602 input list<String> inChars;
4603 input LineInfo inLineInfo;
4604 input Integer inLineIndent;
4605 input list<String> inAccStringChars;
4606
4607 output list<String> outChars;
4608 output LineInfo outLineInfo;
4609 output Integer outLineIndent;
4610 algorithm
4611 (outChars, outLineInfo, outLineIndent)
4612 := matchcontinue (inChars, inLineInfo, inAccStringChars)
4613 local
4614 list<String> chars;
4615 LineInfo linfo;
4616 Integer lineInd;
4617
4618 //ignore a pure-empty-exp line
4619 //accChars = {} nothing before the empty exp
4620 //and [space] and newLine() after it
4621 case (chars, linfo, {})
4622 algorithm
4623 ✗ (chars, linfo) := takeSpaceAndNewLine(chars, linfo);
4624 ✗ (chars,lineInd) := lineIndent(chars, 0);
4625 ✗ then (chars, linfo, lineInd);
4626
4627 //do nothing otherwise ... i.e. continue parsing after the empty exp
4628 else (inChars, inLineInfo, inLineIndent);
4629
4630 end matchcontinue;
4631 end dropNewLineAfterEmptyExp;
4632
4633
4634 public function makeTemplateFromExpList
4635 input list<TplAbsyn.Expression> inExpressionList;
4636 input String inLeftQuote;
4637 input String inRightQuote;
4638
4639 output TplAbsyn.ExpressionBase outExpressionBase;
4640 algorithm
4641 outExpressionBase
4642 := match (inExpressionList, inLeftQuote,inRightQuote)
4643 local
4644 String lquote, rquote;
4645 TplAbsyn.ExpressionBase expB;
4646 list<TplAbsyn.Expression> expLst;
4647
4648 case ( { } , _ , _)
4649 then TplAbsyn.STR_TOKEN(Tpl.ST_STRING(""));
4650
4651 //the outer boundings will be used for the SourceInfo
4652 case ( { (expB,_) } , _ , _)
4653 then expB;
4654
4655 case (expLst, lquote, rquote)
4656 algorithm
4657 ✗ expLst := listReverse(expLst);
4658 ✗ then TplAbsyn.TEMPLATE(expLst, lquote, rquote);
4659
4660 end match;
4661 end makeTemplateFromExpList;
4662
4663
4664 public function onEscapedExp
4665 input TplAbsyn.Expression inExpression;
4666 input list<TplAbsyn.Expression> inExpressionList;
4667 input list<tuple<Integer,list<TplAbsyn.Expression>>> inIndentStack;
4668 input Integer inActualIndent;
4669 input Integer inLineIndent;
4670 input list<String> inAccStringChars;
4671
4672 output list<TplAbsyn.Expression> outExpressionList;
4673 output list<tuple<Integer,list<TplAbsyn.Expression>>> outIndentStack;
4674 output Integer outActualIndent;
4675 output Option<String> outError;
4676 algorithm
4677 (outExpressionList, outIndentStack, outActualIndent, outError)
4678 := matchcontinue (inExpression, inExpressionList, inIndentStack,
4679 inActualIndent, inLineIndent, inAccStringChars)
4680 local
4681 list<String> accChars;
4682 String errStr;
4683 Option<String> errOpt;
4684 Integer actInd, lineInd, baseInd;
4685 TplAbsyn.Expression exp;
4686 list<TplAbsyn.Expression> expLst;
4687 list<tuple<Integer,list<TplAbsyn.Expression>>> indStack;
4688
4689
4690 //TODO: optimization for <\n>
4691 //we need a flag for having something non-space on the line
4692 //case (TplAbsyn.STR_TOKEN(value = Tpl.ST_NEW_LINE()), expLst, indStack, actInd, lineInd, accChars)
4693 // equation
4694 // // true = intEq( lineInd, actInd);
4695 // expLst = addAccStringChars(expLst, "\n" :: accChars);
4696 // then (expLst, indStack, actInd);
4697
4698 //the same indent level
4699 case (exp, expLst, indStack, actInd, lineInd, accChars)
4700 algorithm
4701 ✗ true := intEq( lineInd, actInd );
4702 ✗ expLst := addAccStringChars(expLst, accChars);
4703 ✗ expLst := finalizeLastStringToken(expLst);
4704 expLst := exp :: expLst;
4705 ✗ then (expLst, indStack, actInd,NONE());
4706
4707 //push new indent level
4708 case (exp, expLst, indStack, actInd, lineInd, accChars)
4709 algorithm
4710 ✗ true := ( lineInd > actInd );
4711 ✗ expLst := finalizeLastStringToken(expLst);
4712 ✗ indStack := (actInd, expLst) :: indStack;
4713 ✗ expLst := addAccStringChars({}, accChars);
4714 ✗ expLst := finalizeLastStringToken(expLst);
4715 expLst := exp :: expLst;
4716 ✗ then (expLst, indStack, lineInd,NONE());
4717
4718 //if the indent is under the base indent level, warn and make it 0 level
4719 case (exp, expLst, {}, baseInd, lineInd, accChars)
4720 algorithm
4721 ✗ true := ( lineInd < baseInd );
4722 ✗ errStr := "Indent level is under the level of the '<<' determined level (by "+ intString(baseInd - lineInd)+ " chars).";
4723 ✗ errOpt := SOME(errStr);
4724 //true = Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse warning onEscapedExp() - indent level is under the level of the '<<' determined level.\n");
4725 //call again as lineInd = baseInd
4726 ✗ (expLst, indStack, actInd, _) := onEscapedExp(exp, expLst, {}, baseInd, baseInd, accChars);
4727 ✗ then (expLst, indStack, actInd, errOpt);
4728
4729 //pop indent level and try again (indStack must have at least one pushed indent level)
4730 case (exp, expLst, indStack as (_::_), actInd, lineInd, accChars)
4731 algorithm
4732 ✗ true := ( lineInd < actInd );
4733 ✗ expLst := finalizeLastStringToken(expLst);
4734 ✗ (expLst, indStack, actInd) := popIndentStack(expLst, indStack, actInd, lineInd);
4735 ✗ (expLst, indStack, actInd, errOpt) := onEscapedExp(exp, expLst, indStack, actInd, lineInd, accChars);
4736 ✗ then (expLst, indStack, lineInd, errOpt);
4737
4738 //should not happen
4739 else
4740 algorithm
4741 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse unexpected error - TplParser.onEscapedExp failed .\n");
4742 ✗ then fail();
4743
4744 end matchcontinue;
4745 end onEscapedExp;
4746
4747
4748 public function onNewLine
4749 input list<TplAbsyn.Expression> inExpressionList;
4750 input list<tuple<Integer,list<TplAbsyn.Expression>>> inIndentStack;
4751 input Integer inActualIndent;
4752 input Integer inLineIndent;
4753 input list<String> inAccStringChars;
4754
4755 output list<TplAbsyn.Expression> outExpressionList;
4756 output list<tuple<Integer,list<TplAbsyn.Expression>>> outIndentStack;
4757 output Integer outActualIndent;
4758 output Option<String> outError;
4759 algorithm
4760 (outExpressionList, outIndentStack, outActualIndent, outError)
4761 := matchcontinue (inExpressionList, inIndentStack, inActualIndent, inLineIndent, inAccStringChars)
4762 local
4763 list<String> accChars, strLst;
4764 String c, errStr;
4765 Option<String> errOpt;
4766 Integer actInd, lineInd, baseInd;
4767 list<TplAbsyn.Expression> expLst;
4768 list<tuple<Integer,list<TplAbsyn.Expression>>> indStack;
4769
4770 //drop invisible space before new line
4771 case (expLst, indStack, actInd, lineInd, c :: accChars)
4772 algorithm
4773 ✗ true := (c == " " or c == "\t");
4774 ✗ (expLst, indStack, actInd, errOpt)
4775 := onNewLine(expLst, indStack, actInd, lineInd, accChars);
4776 then (expLst, indStack, actInd, errOpt);
4777
4778 //AccStringChars = {}
4779 // expLst = {} -> the 1. and the only \n in the template (special case) - make permanent
4780 // ignore lineInd - actInd and lineInd should be 0, anyway
4781 case ( {}, indStack, actInd, _, {})
4782 algorithm
4783 ✗ expLst := addAccStringChars({}, {"\n"} );
4784 ✗ then (expLst, indStack, actInd,NONE());
4785
4786 //AccStringChars = {}
4787 // expLst = ST opened :: _ -> a standalone \n on the line - make permanent
4788 // ignore lineInd
4789 case (expLst as ( (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = (""::_))),_) :: _),
4790 indStack, actInd, _, {})
4791 algorithm
4792 ✗ expLst := addAccStringChars(expLst, {"\n"} );
4793 ✗ then (expLst, indStack, actInd,NONE());
4794
4795 //TODO: this does not work, because the <\n> finalizes the previous ST to be closed
4796 //AccStringChars = {}
4797 // expLst = <\n> :: _ -> a forced new line - make permanent - replace with \n
4798 // ignore lineInd - must be lineInd = actInd (because the <\n> exp made it so)
4799 case ( (TplAbsyn.STR_TOKEN(value = Tpl.ST_NEW_LINE()),_) :: expLst,
4800 indStack, actInd, _, {})
4801 algorithm
4802 ✗ expLst := addAccStringChars(expLst, {"\n"} );
4803 ✗ then (expLst, indStack, actInd,NONE());
4804
4805 //AccStringChars = {}
4806 // expLst = SNL :: _ -> a standalone \n on the line - make permanent
4807 // ignore lineInd
4808 case (expLst as ( (TplAbsyn.SOFT_NEW_LINE(),_) :: _) , indStack, actInd, _, {})
4809 algorithm
4810 ✗ expLst := addAccStringChars(expLst, {"\n"} );
4811 ✗ then (expLst, indStack, actInd,NONE());
4812
4813 //AccStringChars = {}
4814 // expLst = some expression :: _ -> an exp must be last --> Soft new line
4815 // ignore lineInd - must be lineInd = actInd (because the exp made it so)
4816 case (expLst as (_ :: _) , indStack, actInd, _, {})
4817 algorithm
4818 expLst := (TplAbsyn.SOFT_NEW_LINE(), dummySourceInfo) :: expLst;
4819 ✗ then (expLst, indStack, actInd,NONE());
4820
4821 //AccStringChars = (_::_)
4822 // lineInd >= actInd
4823 // align the string with prefixed space
4824 // put a disposable new line - may be disposed by onTemplEnd() or hardened by addAccStringChars() or finalizeLastStringToken()
4825 case (expLst, indStack, actInd, lineInd, accChars as (_::_) )
4826 algorithm
4827 ✗ true := ( lineInd >= actInd );
4828 ✗ accChars := listAppend(accChars, List.fill(" ",lineInd - actInd)) annotation(__OpenModelica_DisableListAppendWarning=true);
4829 ✗ (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST(strLst, false)),_) :: expLst
4830 := addAccStringChars(expLst, accChars); //must create the ST becase of accChars as (_::_)
4831 //make the opened last ST be disposable new line
4832 ✗ expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST(strLst, true)), dummySourceInfo) :: expLst;
4833 ✗ then (expLst, indStack, actInd,NONE());
4834
4835 //if the indent is under base indent level, warn and make it 0 level
4836 //AccStringChars = (_::_)
4837 // lineInd < actInd
4838 //pop indent level and try again
4839 case (expLst, {}, baseInd, lineInd, accChars as (_ :: _))
4840 algorithm
4841 ✗ true := ( lineInd < baseInd );
4842 ✗ errStr := "Indent level is under the level of the '<<' determined level (by "+ intString(baseInd - lineInd)+ " chars).";
4843 errOpt := SOME(errStr);
4844 //true = Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse warning onNewLine() - indent level is under the level of the '<<' determined level.\n");
4845 //call again as lineInd = baseInd
4846 ✗ (expLst, indStack, actInd, _) := onNewLine(expLst, {}, baseInd, baseInd, accChars);
4847 ✗ then (expLst, indStack, actInd, errOpt);
4848
4849 //AccStringChars = (_::_)
4850 // lineInd < actInd
4851 //pop indent level and try again
4852 //(indStack must have at least one pushed indent level)
4853 case (expLst, indStack as (_::_), actInd, lineInd, accChars as (_ :: _))
4854 algorithm
4855 ✗ true := ( lineInd < actInd );
4856 ✗ expLst := finalizeLastStringToken(expLst);
4857 ✗ (expLst, indStack, actInd) := popIndentStack(expLst, indStack, actInd, lineInd);
4858 ✗ (expLst, indStack, actInd, errOpt) := onNewLine(expLst, indStack, actInd, lineInd, accChars);
4859 then (expLst, indStack, actInd, errOpt);
4860
4861 //should not happen
4862 else
4863 algorithm
4864 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse unexpected error - TplParser.onNewLine failed .\n");
4865 ✗ then fail();
4866
4867 end matchcontinue;
4868 end onNewLine;
4869
4870
4871 public function onTemplEnd
4872 input Boolean inDropLastNewLine;
4873 input list<TplAbsyn.Expression> inExpressionList;
4874 input list<tuple<Integer,list<TplAbsyn.Expression>>> inIndentStack;
4875 input Integer inActualIndent;
4876 input Integer inLineIndent;
4877 input list<String> inAccStringChars;
4878
4879 output list<TplAbsyn.Expression> outExpressionList;
4880 algorithm
4881 outExpressionList
4882 := matchcontinue (inDropLastNewLine, inExpressionList, inIndentStack, inActualIndent,
4883 inLineIndent, inAccStringChars)
4884 local
4885 list<String> accChars, strLst;
4886 Boolean dropLastNL;
4887 Integer actInd, lineInd, baseInd;
4888 list<TplAbsyn.Expression> expLst;
4889 list<tuple<Integer,list<TplAbsyn.Expression>>> indStack;
4890
4891 //AccStringChars = {}
4892 // expLst = {} - special case, only space in the template
4893 // make the space and take it
4894 case (_, {}, {}, baseInd, lineInd, {})
4895 algorithm
4896 ✗ true := (lineInd >= baseInd);
4897 ✗ expLst := addAccStringChars({}, List.fill(" ",lineInd-baseInd));
4898 ✗ expLst := finalizeLastStringToken(expLst);
4899 then expLst;
4900
4901 //if drop-the-last-new-line is set
4902 //AccStringChars = {}
4903 // expLst = SNL :: _ -> dispose the SNL
4904 // ignore lineInd
4905 // pop all indent
4906 case (true, (TplAbsyn.SOFT_NEW_LINE(),_) :: expLst, indStack, actInd, _, {})
4907 algorithm
4908 ✗ (expLst, {}, _) := popIndentStack(expLst, indStack, actInd, 0);
4909 then expLst;
4910
4911 //if drop-the-last-new-line is set
4912 //AccStringChars = {}
4913 // expLst = ST opened with disposable new line :: _ -> dispose the \n on the line
4914 // ignore lineInd
4915 // pop all indent
4916 case (true, (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = strLst as (""::_), lastHasNewLine = true)),_) :: expLst,
4917 indStack, actInd, _, {})
4918 algorithm
4919 ✗ expLst := finalizeLastStringToken( (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST(strLst, false)), dummySourceInfo) :: expLst);
4920 ✗ (expLst, {},_) := popIndentStack(expLst, indStack, actInd, 0);
4921 //TODO: warn when >> is under << determined indent
4922 then expLst;
4923
4924 //if drop-the-last-new-line is set
4925 //AccStringChars = {}
4926 // expLst = nothing to be stripped
4927 // ignore lineInd - it should be the same as actInd
4928 // pop all indent
4929 case (true, expLst, indStack, actInd, _, {})
4930 algorithm
4931 ✗ expLst := finalizeLastStringToken(expLst);
4932 ✗ (expLst, {}, _) := popIndentStack(expLst, indStack, actInd, 0);
4933 then expLst;
4934
4935 //AccStringChars = (_::_) or drop-the-last-new-line is set
4936 // lineInd >= actInd
4937 // align the string with prefixed space
4938 // pop all indent
4939 case (_, expLst, indStack, actInd, lineInd, accChars)
4940 algorithm
4941 ✗ true := ( lineInd >= actInd );
4942 ✗ accChars := listAppend(accChars, List.fill(" ",lineInd - actInd)) annotation(__OpenModelica_DisableListAppendWarning=true);
4943 ✗ expLst := addAccStringChars(expLst, accChars);
4944 ✗ expLst := finalizeLastStringToken(expLst);
4945 ✗ (expLst, {}, _) := popIndentStack(expLst, indStack, actInd, 0);
4946 then expLst;
4947
4948 // lineInd < baseInd
4949 // the indent is under the base indent level,
4950 // warn and make it 0 level
4951 //pop indent level and try again (only the previous case will be the end of the recursion)
4952 case (dropLastNL, expLst, {}, baseInd, lineInd, accChars)
4953 algorithm
4954 ✗ true := ( lineInd < baseInd );
4955 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse warning onTemplEnd() - indent level is under the level of the '<<' determined level.\n");
4956 ✗ expLst := onTemplEnd(dropLastNL, expLst, {}, baseInd, baseInd, accChars);
4957 then expLst;
4958
4959 // lineInd < actInd
4960 //pop indent level and try again (only the previous case will be the end of the recursion)
4961 case (dropLastNL, expLst, indStack as (_::_), actInd, lineInd, accChars)
4962 algorithm
4963 ✗ true := ( lineInd < actInd );
4964 ✗ expLst := finalizeLastStringToken(expLst);
4965 ✗ (expLst, indStack, actInd) := popIndentStack(expLst, indStack, actInd, lineInd);
4966 ✗ expLst := onTemplEnd(dropLastNL, expLst, indStack, actInd, lineInd, accChars);
4967 then expLst;
4968
4969 //should not happen
4970 else
4971 algorithm
4972 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!!Parse error - TplParser.onTemplEnd failed .\n");
4973 ✗ then fail();
4974
4975 end matchcontinue;
4976 end onTemplEnd;
4977
4978
4979 public function popIndentStack
4980 input list<TplAbsyn.Expression> inExpressionList;
4981 input list<tuple<Integer,list<TplAbsyn.Expression>>> inIndentStack;
4982 input Integer inActualIndent;
4983 input Integer inLineIndent;
4984
4985 output list<TplAbsyn.Expression> outExpressionList;
4986 output list<tuple<Integer,list<TplAbsyn.Expression>>> outIndentStack;
4987 output Integer outActualIndent;
4988 algorithm
4989 (outExpressionList, outIndentStack, outActualIndent)
4990 := matchcontinue (inExpressionList, inIndentStack, inActualIndent, inLineIndent)
4991 local
4992 Integer actInd, lineInd, baseInd, d, prevInd;
4993 list<TplAbsyn.Expression> expLst, prevExpLst;
4994 list<tuple<Integer,list<TplAbsyn.Expression>>> indStack;
4995
4996
4997 case (expLst, (prevInd, prevExpLst) :: indStack, actInd, lineInd)
4998 algorithm
4999 ✗ true := (lineInd < actInd); //when actInd > 0 --> something has to be on the stack
5000 ✗ d := actInd - prevInd; //must be positive
5001 ✗ expLst := listReverse(expLst);
5002 ✗ expLst := (TplAbsyn.INDENTATION(d, expLst), dummySourceInfo) :: prevExpLst;
5003 ✗ (expLst, indStack, actInd) := popIndentStack(expLst, indStack, prevInd, lineInd);
5004 then (expLst, indStack, actInd);
5005
5006 case (expLst, indStack, actInd, lineInd)
5007 algorithm
5008 ✗ true := (lineInd >= actInd);
5009 ✗ then (expLst, indStack, actInd);
5010
5011 //base indent
5012 case (expLst, {}, baseInd, _)
5013 ✗ then (expLst, {}, baseInd);
5014
5015
5016 //should not happen
5017 else
5018 algorithm
5019 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!!Parse error - TplParser.popIndentStack failed .\n");
5020 ✗ then fail();
5021
5022 end matchcontinue;
5023 end popIndentStack;
5024
5025
5026 public function addAccStringChars
5027 input list<TplAbsyn.Expression> inExpressionList;
5028 input list<String> inAccStringChars;
5029
5030 output list<TplAbsyn.Expression> outExpressionList;
5031 algorithm
5032 outExpressionList
5033 := matchcontinue (inExpressionList, inAccStringChars)
5034 local
5035 list<String> accChars, strLst;
5036 String str, strNonNl;
5037 list<TplAbsyn.Expression> expLst;
5038
5039 //AccStringChars = {}
5040 // nothing
5041 case ( expLst, {})
5042 then expLst;
5043
5044
5045 // add a string
5046 // expLst = ST opened with new line :: _
5047 // merge the pushed new line with previous string without new line
5048 case ( (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = ("" :: strNonNl :: strLst), lastHasNewLine = true)),_) :: expLst,
5049 accChars as (_::_))
5050 algorithm
5051 ✗ failure("\n" := stringGetStringChar(strNonNl, stringLength(strNonNl)));
5052 // push the disposable new line
5053 ✗ strNonNl := strNonNl + "\n";
5054 ✗ str := stringCharListString(listReverse(accChars));
5055 ✗ expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST("" :: str :: strNonNl :: strLst, false)), dummySourceInfo) :: expLst;
5056 then expLst;
5057
5058 // add a string
5059 // expLst = ST opened with new line :: _
5060 // push the disposable new line - previous string has new line
5061 case ( (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = ("" :: strLst), lastHasNewLine = true)),_) :: expLst,
5062 accChars as (_::_))
5063 algorithm
5064 //"\n" = stringGetStringChar(strNonNl, stringLength(strNonNl));
5065 ✗ str := stringCharListString(listReverse(accChars));
5066 ✗ expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST("" :: str :: "\n" :: strLst, false)), dummySourceInfo) :: expLst;
5067 then expLst;
5068
5069
5070 // add a string
5071 // expLst = ST opened without new line :: _
5072 case ( (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = ("" :: strLst), lastHasNewLine = false)),_) :: expLst,
5073 accChars as (_::_))
5074 algorithm
5075 ✗ str := stringCharListString(listReverse(accChars));
5076 ✗ expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST("" :: str :: strLst, false)), dummySourceInfo) :: expLst;
5077 then expLst;
5078
5079
5080 // add a string
5081 // expLst = no opened ST :: _
5082 case ( expLst, accChars as (_::_))
5083 algorithm
5084 ✗ str := stringCharListString(listReverse(accChars));
5085 ✗ expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST({"", str}, false)), dummySourceInfo) :: expLst;
5086 then expLst;
5087
5088
5089 //should not happen
5090 else
5091 algorithm
5092 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!!Parse error - TplParser.addAccStringChars failed .\n");
5093 ✗ then fail();
5094
5095 end matchcontinue;
5096 end addAccStringChars;
5097
5098
5099 public function finalizeLastStringToken
5100 input list<TplAbsyn.Expression> inExpressionList;
5101
5102 output list<TplAbsyn.Expression> outExpressionList;
5103 algorithm
5104 outExpressionList
5105 := matchcontinue inExpressionList
5106 local
5107 list<String> strLst;
5108 String str, strNonNl;
5109 list<TplAbsyn.Expression> expLst;
5110 Boolean hasNL;
5111
5112
5113 // expLst = ST opened with new line :: _
5114 // merge the pushed new line with previous string without new line
5115 case (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = ("" :: strNonNl :: strLst), lastHasNewLine = true)),_) :: expLst
5116 algorithm
5117 ✗ failure("\n" := stringGetStringChar(strNonNl, stringLength(strNonNl)));
5118 // push the disposable new line
5119 ✗ str := strNonNl + "\n";
5120 ✗ expLst := finalizeLastStringToken( (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST( ""::str::strLst, false)), dummySourceInfo) :: expLst);
5121 then expLst;
5122
5123 // expLst = ST opened with new line :: _
5124 // the last string has new line (or empty - should not happen)
5125 case (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = ("" :: strLst), lastHasNewLine = true)),_) :: expLst
5126 algorithm
5127 //"\n" = stringGetStringChar(str, stringLength(str));
5128 ✗ expLst := finalizeLastStringToken( (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST( ""::"\n"::strLst, false)), dummySourceInfo) :: expLst);
5129 then expLst;
5130
5131
5132 // expLst = ST opened with new line :: _
5133 // empty ST - for sure - should not happen
5134 case (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = { "" }, lastHasNewLine = false)),_) :: expLst
5135 then expLst;
5136
5137
5138 // expLst = ST opened with new line :: _
5139 // the last and only string has new line
5140 case (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = { "" , "\n" }, lastHasNewLine = false)),_) :: expLst
5141 algorithm
5142 expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_NEW_LINE()), dummySourceInfo) :: expLst;
5143 then expLst;
5144
5145
5146 // expLst = ST opened with new line :: _
5147 // the last and only string has new line => ST_LINE
5148 case (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = { "" , str }, lastHasNewLine = false)),_) :: expLst
5149 algorithm
5150 ✗ "\n" := stringGetStringChar(str, stringLength(str));
5151 ✗ expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_LINE(str)), dummySourceInfo) :: expLst;
5152 then expLst;
5153
5154 // expLst = ST opened with new line :: _
5155 // the last and only string has NOT a new line => ST_STRING
5156 case (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST(strList = { "" , str }, lastHasNewLine = false)),_) :: expLst
5157 algorithm
5158 ✗ failure("\n" := stringGetStringChar(str, stringLength(str)));
5159 ✗ expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_STRING(str)), dummySourceInfo) :: expLst;
5160 then expLst;
5161
5162
5163 // expLst = ST is string list :: _
5164 // make it a ST_STRING_LIST with properly set lastHasNewLine
5165 case (TplAbsyn.STR_TOKEN(value = Tpl.ST_STRING_LIST( strList = ("" :: (strLst as (str :: _))), lastHasNewLine = false)),_) :: expLst
5166 algorithm
5167 ✗ hasNL := ("\n" == stringGetStringChar(str, stringLength(str)));
5168 ✗ strLst := listReverse(strLst);
5169 ✗ expLst := (TplAbsyn.STR_TOKEN(Tpl.ST_STRING_LIST( strLst, hasNL)), dummySourceInfo) :: expLst;
5170 then expLst;
5171
5172 //nothing to be finalized
5173 else inExpressionList;
5174
5175 end matchcontinue;
5176 end finalizeLastStringToken;
5177
5178
5179 /*
5180 conditionExp(lesc,resc):
5181 'if' condArgExp(lesc,resc):(isNot, lhsExp, rhsMExpOpt)
5182 'then' expressionLet(lesc,resc):trueBr
5183 elseBranch(lesc,resc):elseBrOpt
5184 => CONDITION(isNot, lhsExp, rhsMExpOpt, trueBr, elseBrOpt)
5185 */
5186 public function conditionExp
5187 input list<String> inChars;
5188 input LineInfo inLineInfo;
5189 input String inLeftEsc;
5190 input String inRightEsc;
5191
5192 output list<String> outChars;
5193 output LineInfo outLineInfo;
5194 output TplAbsyn.Expression outExpression;
5195 algorithm
5196 (outChars, outLineInfo, outExpression) := match (inChars, inLineInfo, inLeftEsc, inRightEsc)
5197 local
5198 list<String> chars, startChars;
5199 LineInfo linfo, startLInfo;
5200 String lesc, resc;
5201 Boolean isNot;
5202 TplAbsyn.Expression lhsExp, trueBr;
5203 Option<TplAbsyn.MatchingExp> rhsMExpOpt;
5204 Option<TplAbsyn.Expression> elseBrOpt;
5205 SourceInfo sinfo;
5206
5207 case ("i"::"f":: startChars, startLInfo, lesc, resc)
5208 algorithm
5209 ✗ afterKeyword(startChars);
5210 ✗ (chars, linfo) := interleave(startChars, startLInfo);
5211 ✗ (chars, linfo, isNot, lhsExp, rhsMExpOpt) := condArgExp(chars, linfo, lesc, resc);
5212 ✗ (chars, linfo) := interleave(chars, linfo);
5213 ✗ (chars, linfo, trueBr) := thenBranch(chars, linfo, lesc, resc);
5214 ✗ (chars, linfo) := interleave(chars, linfo);
5215 ✗ (chars, linfo, elseBrOpt) := elseBranch(chars, linfo, lesc, resc);
5216 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 2), chars, linfo);
5217 ✗ then (chars, linfo, (TplAbsyn.CONDITION(isNot, lhsExp, rhsMExpOpt, trueBr, elseBrOpt), sinfo));
5218
5219 end match;
5220 end conditionExp;
5221
5222
5223 public function thenBranch
5224 input list<String> inChars;
5225 input LineInfo inLineInfo;
5226 input String inLeftEsc;
5227 input String inRightEsc;
5228
5229 output list<String> outChars;
5230 output LineInfo outLineInfo;
5231 output TplAbsyn.Expression outTrueBranch;
5232 algorithm
5233 (outChars, outLineInfo, outTrueBranch) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
5234 local
5235 list<String> chars;
5236 LineInfo linfo;
5237 String lesc, resc;
5238 TplAbsyn.Expression exp;
5239
5240 case ("t"::"h"::"e"::"n":: chars, linfo, lesc, resc)
5241 algorithm
5242 ✗ afterKeyword(chars);
5243 ✗ (chars, linfo) := interleave(chars, linfo);
5244 ✗ (chars, linfo, exp) := expressionLet(chars, linfo, lesc, resc);
5245 then (chars, linfo, exp);
5246
5247 //error not a keyword
5248 //try move on ?
5249 case (chars, linfo, lesc, resc)
5250 algorithm
5251 ✗ (_, false) := isKeyword(chars, "t"::"h"::"e"::"n"::{});
5252 ✗ linfo := parseError(chars, linfo, "Expected 'then' keyword at the position.", false);
5253 ✗ (chars, linfo, exp) := expressionLet(chars, linfo, lesc, resc);
5254 then (chars, linfo, exp);
5255
5256 else
5257 algorithm
5258 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("- !!! TplParser.thenBranch failed.\n");
5259 ✗ then fail();
5260
5261 end matchcontinue;
5262 end thenBranch;
5263
5264
5265 /*
5266 elseBranch(lesc,resc):
5267 'else' expressionLet(lesc,resc):elseBr
5268 => SOME(elseBr)
5269 |
5270 _ => NONE
5271
5272 */
5273 public function elseBranch
5274 input list<String> inChars;
5275 input LineInfo inLineInfo;
5276 input String inLeftEsc;
5277 input String inRightEsc;
5278
5279 output list<String> outChars;
5280 output LineInfo outLineInfo;
5281 output Option<TplAbsyn.Expression> outElseBranchOpt;
5282 algorithm
5283 (outChars, outLineInfo, outElseBranchOpt) := matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
5284 local
5285 list<String> chars;
5286 LineInfo linfo;
5287 String lesc, resc;
5288 TplAbsyn.Expression elseBr;
5289
5290 case ("e"::"l"::"s"::"e":: chars, linfo, lesc, resc)
5291 algorithm
5292 ✗ afterKeyword(chars);
5293 ✗ (chars, linfo) := interleave(chars, linfo);
5294 ✗ (chars, linfo, elseBr) := expressionLet(chars, linfo, lesc, resc);
5295 ✗ then (chars, linfo, SOME(elseBr));
5296
5297 else (inChars, inLineInfo, NONE());
5298
5299 end matchcontinue;
5300 end elseBranch;
5301 /*
5302 must not fail
5303 condArgExp:
5304 'not' expressionPlus(lesc,resc):lhsExp
5305 => (true, lhsExp,NONE())
5306 |
5307 expressionPlus(lesc,resc):lhsExp
5308 // condArgRHS:(isNot, rshMExpOpt)
5309 { isNot = false }
5310 => (isNot,lhsExp, rhsMExpOpt)
5311 */
5312 public function condArgExp
5313 input list<String> inChars;
5314 input LineInfo inLineInfo;
5315 input String inLeftEsc;
5316 input String inRightEsc;
5317
5318 output list<String> outChars;
5319 output LineInfo outLineInfo;
5320 output Boolean outIsNot;
5321 output TplAbsyn.Expression outLHSExpression;
5322 output Option<TplAbsyn.MatchingExp> outRHSMExpOpt;
5323 algorithm
5324 (outChars, outLineInfo, outIsNot, outLHSExpression, outRHSMExpOpt) :=
5325 matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
5326 local
5327 list<String> chars;
5328 LineInfo linfo;
5329 String lesc, resc;
5330 TplAbsyn.Expression lhsExp;
5331
5332 //TODO: perhaps, we should record the start of the expression from the 'not'
5333 //but for now, we don't have other operators, so it is non an issue here
5334 case ("n"::"o"::"t":: chars, linfo, lesc, resc)
5335 algorithm
5336 ✗ afterKeyword(chars);
5337 ✗ (chars, linfo) := interleave(chars, linfo);
5338 ✗ (chars, linfo, lhsExp) := expressionPlus(chars, linfo, lesc, resc);
5339 ✗ then (chars, linfo, true, lhsExp,NONE());
5340
5341 case (chars, linfo, lesc, resc)
5342 algorithm
5343 ✗ (chars, linfo, lhsExp) := expressionPlus(chars, linfo, lesc, resc);
5344 //(chars, linfo) = interleave(chars, linfo);
5345 //(chars, linfo, isNot, rhsMExpOpt) = condArgRHS(chars, linfo);
5346 //isNot = false;
5347 ✗ then (chars, linfo, false, lhsExp,NONE());
5348
5349 end matchcontinue;
5350 end condArgExp;
5351 /*
5352 condArgRHS:
5353 'is' 'not' matchBinding:rhsMExp => (true, SOME(rhsMexp))
5354 |
5355 'is' matchBinding:rhsMExp => (false, SOME(rhsMexp))
5356 |
5357 _ => (false,NONE())
5358 */
5359 /*
5360 public function condArgRHS
5361 input list<String> inChars;
5362 input LineInfo inLineInfo;
5363
5364 output list<String> outChars;
5365 output LineInfo outLineInfo;
5366 output Boolean outIsNot;
5367 output Option<TplAbsyn.MatchingExp> outRHSMExpOpt;
5368 algorithm
5369 (outChars, outLineInfo, outIsNot, outRHSMExpOpt) :=
5370 matchcontinue (inChars, inLineInfo)
5371 local
5372 list<String> chars;
5373 LineInfo linfo;
5374 String c, lesc, resc;
5375 Boolean isD, isNot;
5376 TplAbsyn.Ident id;
5377 TplAbsyn.PathIdent name;
5378 TplAbsyn.TypedIdents fields,inargs,outargs;
5379 TplAbsyn.TypeSignature ts;
5380 Tpl.StringToken st;
5381 TplAbsyn.Expression exp, bexp, lhsExp, elseBr;
5382 TplAbsyn.MatchingExp rhsMExp;
5383 Option<TplAbsyn.MatchingExp> rhsMExpOpt;
5384 Option<TplAbsyn.Expression> elseBrOpt;
5385 list<TplAbsyn.Expression> expLst;
5386 TplAbsyn.EscOption sopt;
5387 list<TplAbsyn.EscOption> opts;
5388
5389 case ("i"::"s":: chars, linfo)
5390 algorithm
5391 afterKeyword(chars);
5392 (chars, linfo) = interleave(chars, linfo);
5393 ("n"::"o"::"t":: chars) = chars;
5394 afterKeyword(chars);
5395 (chars, linfo) = interleave(chars, linfo);
5396 (chars, linfo, rhsMExp) = matchBinding(chars, linfo);
5397 then (chars, linfo, true, SOME(rhsMExp));
5398
5399 case ("i"::"s":: chars, linfo)
5400 algorithm
5401 afterKeyword(chars);
5402 (chars, linfo) = interleave(chars, linfo);
5403 (chars, linfo, rhsMExp) = matchBinding(chars, linfo);
5404 then (chars, linfo, false, SOME(rhsMExp));
5405
5406
5407 else (inChars, inLineInfo, false, NONE());
5408
5409 end matchcontinue;
5410 end condArgRHS;
5411 */
5412
5413
5414 /*
5415 optional, can fail
5416 matchExp(lesc,resc):
5417 'match' expressionIf:exp
5418 matchCaseList(lesc,resc):mcaseLst { (_::_) = mcaseLst }//not optional
5419 matchElseCase(lesc,resc):elseLst
5420 matchEndMatch
5421 => MATCH(exp, listAppend(mcaseLst, elseLst))
5422 //|
5423 //matchCaseList(lesc,resc):mcaseLst { (_::_) = mcaseLst }
5424 //=> MATCH(BOUND_VALUE(IDENT("it")), mcaseLst)
5425 */
5426 public function matchExp
5427 input list<String> inChars;
5428 input LineInfo inLineInfo;
5429 input String inLeftEsc;
5430 input String inRightEsc;
5431
5432 output list<String> outChars;
5433 output LineInfo outLineInfo;
5434 output TplAbsyn.Expression outExpression;
5435 algorithm
5436 (outChars, outLineInfo, outExpression) := match (inChars, inLineInfo, inLeftEsc, inRightEsc)
5437 local
5438 list<String> chars, startChars;
5439 LineInfo linfo, startLInfo;
5440 String lesc, resc;
5441 TplAbsyn.Expression exp;
5442 list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> mcaseLst, elseLst;
5443 SourceInfo sinfo;
5444
5445 case ("m"::"a"::"t"::"c"::"h":: startChars, startLInfo, lesc, resc)
5446 algorithm
5447 ✗ afterKeyword(startChars);
5448 ✗ (chars, linfo) := interleave(startChars, startLInfo);
5449 ✗ (chars, linfo, exp) := expressionIf(chars, linfo, lesc, resc);
5450 ✗ (chars, linfo, mcaseLst) := matchCaseListNoOpt(chars, linfo, lesc, resc);
5451 ✗ (chars, linfo) := interleave(chars, linfo);
5452 ✗ (chars, linfo, elseLst) := matchElseCase(chars, linfo, lesc, resc);
5453 ✗ mcaseLst := listAppend(mcaseLst, elseLst) annotation(__OpenModelica_DisableListAppendWarning=true);
5454 ✗ (chars, linfo) := interleave(chars, linfo);
5455 ✗ (chars, linfo) := matchEndMatch(chars, linfo);
5456 ✗ sinfo := tplSourceInfo(captureStartPosition(startChars, startLInfo, 5), chars, linfo);
5457 ✗ then (chars, linfo, (TplAbsyn.MATCH(exp, mcaseLst), sinfo));
5458
5459 //implicit without 'match' keyword -> match it
5460 //case (chars, linfo, lesc, resc)
5461 // equation
5462 // (chars, linfo, mcaseLst) = matchCaseList(chars, linfo, lesc, resc);
5463 // (_::_) = mcaseLst;
5464 // then (chars, linfo, TplAbsyn.MATCH(TplAbsyn.BOUND_VALUE(TplAbsyn.IDENT("it")), mcaseLst));
5465
5466 end match;
5467 end matchExp;
5468
5469
5470 /*
5471 matchCase(lesc,resc):
5472 'case' matchBinding:mexp matchCaseHeads(): mexpHeadLst
5473 'then' expression:exp
5474 => makeMatchCaseLst(mexp::mexpHeadLst,exp)
5475 */
5476 public function matchCase
5477 input list<String> inChars;
5478 input LineInfo inLineInfo;
5479 input String inLeftEsc;
5480 input String inRightEsc;
5481
5482 output list<String> outChars;
5483 output LineInfo outLineInfo;
5484 output list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> outMatchCaseLst;
5485 algorithm
5486 (outChars, outLineInfo, outMatchCaseLst) :=
5487 match (inChars, inLineInfo, inLeftEsc, inRightEsc)
5488 local
5489 list<String> chars;
5490 LineInfo linfo;
5491 String lesc, resc;
5492 TplAbsyn.Expression exp;
5493 TplAbsyn.MatchingExp mexp;
5494 list<TplAbsyn.MatchingExp> mexpHeadList;
5495 list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> matchCaseLst;
5496
5497 case ("c"::"a"::"s"::"e":: chars, linfo, lesc, resc)
5498 algorithm
5499 ✗ afterKeyword(chars);
5500 ✗ (chars, linfo) := interleave(chars, linfo);
5501 ✗ (chars, linfo, mexp) := matchBinding(chars, linfo);
5502 ✗ (chars, linfo) := interleave(chars, linfo);
5503 ✗ (chars, linfo, mexpHeadList) := matchCaseHeads(chars, linfo);
5504 ✗ (chars, linfo) := interleave(chars, linfo);
5505 ✗ (chars, linfo, exp) := thenBranch(chars, linfo, lesc, resc);
5506 ✗ matchCaseLst := makeMatchCaseLst(mexp::mexpHeadList,exp);
5507 ✗ then (chars, linfo, matchCaseLst);
5508
5509 end match;
5510 end matchCase;
5511
5512 /*
5513 matchElseCase(lesc,resc):
5514 'else' expression:exp
5515 => {(REST_MATCH(), exp)}
5516 |
5517 _ => {}
5518 */
5519 public function matchElseCase
5520 input list<String> inChars;
5521 input LineInfo inLineInfo;
5522 input String inLeftEsc;
5523 input String inRightEsc;
5524
5525 output list<String> outChars;
5526 output LineInfo outLineInfo;
5527 output list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> outMatchCaseLst;
5528 algorithm
5529 (outChars, outLineInfo, outMatchCaseLst) :=
5530 matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
5531 local
5532 list<String> chars;
5533 LineInfo linfo;
5534 String lesc, resc;
5535 TplAbsyn.Expression exp;
5536
5537 case ("e"::"l"::"s"::"e":: chars, linfo, lesc, resc)
5538 algorithm
5539 ✗ afterKeyword(chars);
5540 ✗ (chars, linfo) := interleave(chars, linfo);
5541 ✗ (chars,linfo,exp) := expressionLet(chars, linfo, lesc, resc);
5542 ✗ then (chars, linfo, { (TplAbsyn.REST_MATCH(), exp) } );
5543
5544 else (inChars, inLineInfo, {});
5545
5546 end matchcontinue;
5547 end matchElseCase;
5548
5549 /*
5550 matchEndMatch:
5551 'end' 'match'
5552 |
5553 _
5554 */
5555 public function matchEndMatch
5556 input list<String> inChars;
5557 input LineInfo inLineInfo;
5558
5559 output list<String> outChars;
5560 output LineInfo outLineInfo;
5561 algorithm
5562 (outChars, outLineInfo) :=
5563 matchcontinue (inChars, inLineInfo)
5564 local
5565 list<String> chars;
5566 LineInfo linfo;
5567
5568 case ("e"::"n"::"d":: chars, linfo)
5569 algorithm
5570 ✗ afterKeyword(chars);
5571 ✗ (chars, linfo) := interleave(chars, linfo);
5572 //both keywords are optional ... the match cannot be "expected" as there can be 'end' indentifier ';'
5573 ✗ "m"::"a"::"t"::"c"::"h" :: chars := chars; // interleaveExpectKeyWord(chars, linfo, {"m","a","t","c","h"}, false);
5574 ✗ afterKeyword(chars);
5575 ✗ then (chars, linfo);
5576
5577 else (inChars, inLineInfo);
5578
5579 end matchcontinue;
5580 end matchEndMatch;
5581
5582 /*
5583 matchCaseHeads(lesc,resc):
5584 'case' matchBinding:mexp matchCaseHeads(): mexpHeadLst
5585 => mexp :: mexpHeadLst
5586 |
5587 _ => {}
5588 */
5589 public function matchCaseHeads
5590 input list<String> inChars;
5591 input LineInfo inLineInfo;
5592
5593 output list<String> outChars;
5594 output LineInfo outLineInfo;
5595 output list<TplAbsyn.MatchingExp> outMExpHeadLst;
5596 algorithm
5597 (outChars, outLineInfo, outMExpHeadLst) :=
5598 matchcontinue (inChars, inLineInfo)
5599 local
5600 list<String> chars;
5601 LineInfo linfo;
5602 TplAbsyn.MatchingExp mexp;
5603 list<TplAbsyn.MatchingExp> mexpHeadList;
5604
5605 case ("c"::"a"::"s"::"e":: chars, linfo)
5606 algorithm
5607 ✗ afterKeyword(chars);
5608 ✗ (chars, linfo) := interleave(chars, linfo);
5609 ✗ (chars, linfo, mexp) := matchBinding(chars, linfo);
5610 ✗ (chars, linfo) := interleave(chars, linfo);
5611 ✗ (chars, linfo, mexpHeadList) := matchCaseHeads(chars, linfo);
5612 ✗ then (chars, linfo, mexp :: mexpHeadList);
5613
5614 else (inChars, inLineInfo, {});
5615
5616 end matchcontinue;
5617 end matchCaseHeads;
5618
5619
5620 public function makeMatchCaseLst
5621 input list<TplAbsyn.MatchingExp> inMExpHeadLst;
5622 input TplAbsyn.Expression inExpression;
5623
5624 output list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> outMatchCaseLst;
5625 algorithm
5626 outMatchCaseLst :=
5627 match (inMExpHeadLst, inExpression)
5628 local
5629 TplAbsyn.Expression exp;
5630 TplAbsyn.MatchingExp mexp;
5631 list<TplAbsyn.MatchingExp> mexpHeadList;
5632 list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> matchCaseLst;
5633
5634 case ({}, _) then {};
5635
5636 case (mexp :: mexpHeadList, exp)
5637 algorithm
5638 ✗ matchCaseLst := makeMatchCaseLst(mexpHeadList,exp);
5639 ✗ then ((mexp, exp) :: matchCaseLst);
5640
5641 end match;
5642 end makeMatchCaseLst;
5643
5644 /*
5645 matchCaseList(lesc,resc):
5646 matchCase(lesc,resc):mcaseLst matchCaseList(lesc,resc):mcrest
5647 => listAppend(mcaseLst, mcrest)
5648 |
5649 _ => {}
5650 */
5651 public function matchCaseList
5652 input list<String> inChars;
5653 input LineInfo inLineInfo;
5654 input String inLeftEsc;
5655 input String inRightEsc;
5656
5657 output list<String> outChars;
5658 output LineInfo outLineInfo;
5659 output list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> outMatchCases;
5660 algorithm
5661 (outChars, outLineInfo, outMatchCases) :=
5662 matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
5663 local
5664 list<String> chars;
5665 LineInfo linfo;
5666 String lesc, resc;
5667 list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> mcaseLst, mcrest;
5668
5669 case (chars, linfo, lesc, resc)
5670 algorithm
5671 ✗ (chars, linfo, mcaseLst) := matchCase(chars, linfo, lesc, resc);
5672 ✗ (chars, linfo) := interleave(chars, linfo);
5673 ✗ (chars, linfo, mcrest) := matchCaseList(chars, linfo, lesc, resc);
5674 ✗ mcaseLst := listAppend(mcaseLst, mcrest) annotation(__OpenModelica_DisableListAppendWarning=true);
5675 ✗ then (chars, linfo, mcaseLst);
5676
5677 else (inChars, inLineInfo, {});
5678
5679 end matchcontinue;
5680 end matchCaseList;
5681
5682
5683 public function matchCaseListNoOpt
5684 input list<String> inChars;
5685 input LineInfo inLineInfo;
5686 input String inLeftEsc;
5687 input String inRightEsc;
5688
5689 output list<String> outChars;
5690 output LineInfo outLineInfo;
5691 output list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> outMatchCases;
5692 algorithm
5693 (outChars, outLineInfo, outMatchCases) :=
5694 matchcontinue (inChars, inLineInfo, inLeftEsc, inRightEsc)
5695 local
5696 list<String> chars;
5697 LineInfo linfo;
5698 String lesc, resc;
5699 list<tuple<TplAbsyn.MatchingExp, TplAbsyn.Expression>> mcaseLst;
5700
5701 case (chars, linfo, lesc, resc)
5702 algorithm
5703 ✗ (chars, linfo, mcaseLst) := matchCaseList(chars, linfo, lesc, resc);
5704 ✗ _::_ := mcaseLst;
5705 ✗ then (chars, linfo, mcaseLst);
5706
5707 case (chars, linfo, _, _)
5708 algorithm
5709 ✗ (_, false) := isKeyword(chars, "c"::"a"::"s"::"e"::{});
5710 ✗ linfo := parseError(chars, linfo, "Expected keyword 'case' at the position.", true);
5711 then (chars, linfo, {});
5712
5713 else
5714 algorithm
5715 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!! TplParser.matchCaseListNoOpt failed.\n");
5716 ✗ then fail();
5717
5718 end matchcontinue;
5719 end matchCaseListNoOpt;
5720
5721 /*
5722 matchBinding:
5723 matchBinding_base:headMExp matchBinding_tail(headMExp):mexp
5724 => mexp
5725
5726 */
5727 public function matchBinding
5728 input list<String> inChars;
5729 input LineInfo inLineInfo;
5730
5731 output list<String> outChars;
5732 output LineInfo outLineInfo;
5733 output TplAbsyn.MatchingExp outMatchingExp;
5734 algorithm
5735 (outChars, outLineInfo, outMatchingExp) :=
5736 match (inChars, inLineInfo)
5737 local
5738 list<String> chars;
5739 LineInfo linfo;
5740 TplAbsyn.MatchingExp headMExp, mexp;
5741
5742 case (chars, linfo)
5743 algorithm
5744 ✗ (chars, linfo, headMExp) := matchBinding_base(chars, linfo);
5745 ✗ (chars, linfo) := interleave(chars, linfo);
5746 ✗ (chars, linfo, mexp) := matchBinding_tail(chars, linfo, headMExp);
5747 then (chars, linfo, mexp);
5748
5749 end match;
5750 end matchBinding;
5751 /*
5752 matchBinding_tail(headMExp):
5753 '::' matchBinding:restMExp
5754 => LIST_CONS_MATCH(headMExp, restMExp)
5755 |
5756 _ => headMExp
5757 */
5758 public function matchBinding_tail
5759 input list<String> inChars;
5760 input LineInfo inLineInfo;
5761 input TplAbsyn.MatchingExp inHeadMatchingExp;
5762
5763 output list<String> outChars;
5764 output LineInfo outLineInfo;
5765 output TplAbsyn.MatchingExp outMatchingExp;
5766 algorithm
5767 (outChars, outLineInfo, outMatchingExp) :=
5768 matchcontinue (inChars, inLineInfo, inHeadMatchingExp)
5769 local
5770 list<String> chars;
5771 LineInfo linfo;
5772 TplAbsyn.MatchingExp headMExp, restMExp;
5773
5774 case (":"::":":: chars, linfo, headMExp)
5775 algorithm
5776 ✗ (chars, linfo) := interleave(chars, linfo);
5777 ✗ (chars, linfo, restMExp) := matchBinding(chars, linfo);
5778 ✗ then (chars, linfo, TplAbsyn.LIST_CONS_MATCH(headMExp, restMExp));
5779
5780 else (inChars, inLineInfo, inHeadMatchingExp);
5781
5782 end matchcontinue;
5783 end matchBinding_tail;
5784 /*
5785 matchBinding_base:
5786 'SOME' someBinding_rest:mexp
5787 => SOME_MATCH(mexp)
5788 |
5789 'NONE' takeEmptyBraces
5790 => NONE_MATCH()
5791 |
5792 '(' matchBinding:headMExp tupleOrSingleMatch(headMExp):mexp ')'
5793 => mexp
5794 |
5795 '{' '}'
5796 => LIST_MATCH({})
5797 |
5798 '{' matchBinding:headMExp listMatch_rest:mrest '}
5799 => LIST_MATCH(headMExp :: mrest)
5800 |
5801 stringConstant:strRevList
5802 => STRING_MATCH(stringAppendList(listReverse(strRevList))
5803 |
5804 literalConstant:(str,litType)
5805 => LITERAL_MATCH(str,litType)
5806 |
5807 '_'
5808 => REST_MATCH()
5809 |
5810 pathIdent:pid afterIdentBinding(pid):mexp
5811 => mexp
5812 */
5813 public function matchBinding_base
5814 input list<String> inChars;
5815 input LineInfo inLineInfo;
5816
5817 output list<String> outChars;
5818 output LineInfo outLineInfo;
5819 output TplAbsyn.MatchingExp outMatchingExp;
5820 algorithm
5821 (outChars, outLineInfo, outMatchingExp) :=
5822 matchcontinue (inChars, inLineInfo)
5823 local
5824 list<String> chars, strRevList;
5825 LineInfo linfo;
5826 String str;
5827 TplAbsyn.PathIdent pid;
5828 TplAbsyn.MatchingExp headMExp, mexp;
5829 list<TplAbsyn.MatchingExp> mrest;
5830 TplAbsyn.TypeSignature ts;
5831
5832 case ("S"::"O"::"M"::"E":: chars, linfo)
5833 algorithm
5834 ✗ afterKeyword(chars);
5835 ✗ (chars, linfo) := interleave(chars, linfo);
5836 ✗ (chars, linfo, mexp) := someBinding_rest(chars, linfo);
5837 ✗ then (chars, linfo, TplAbsyn.SOME_MATCH(mexp));
5838
5839 case ("N"::"O"::"N"::"E":: chars, linfo)
5840 algorithm
5841 ✗ afterKeyword(chars);
5842 ✗ (chars, linfo) := interleave(chars, linfo);
5843 ✗ (chars, linfo) := takeEmptyBraces(chars, linfo);
5844 ✗ then (chars, linfo, TplAbsyn.NONE_MATCH());
5845
5846 case ("(":: chars, linfo)
5847 algorithm
5848 ✗ (chars, linfo) := interleave(chars, linfo);
5849 ✗ (chars, linfo, headMExp) := matchBinding(chars, linfo);
5850 ✗ (chars, linfo) := interleave(chars, linfo);
5851 ✗ (chars, linfo, mexp) := tupleOrSingleMatch(chars, linfo, headMExp);
5852 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
5853 ✗ then (chars, linfo, mexp);
5854
5855 case ("{":: chars, linfo)
5856 algorithm
5857 ✗ (chars, linfo) := interleave(chars, linfo);
5858 ✗ "}"::chars := chars;
5859 ✗ then (chars, linfo, TplAbsyn.LIST_MATCH({}));
5860
5861 case ("{":: chars, linfo)
5862 algorithm
5863 ✗ (chars, linfo) := interleave(chars, linfo);
5864 ✗ (chars, linfo, headMExp) := matchBinding(chars, linfo);
5865 ✗ (chars, linfo) := interleave(chars, linfo);
5866 ✗ (chars, linfo, mrest) := listMatch_rest(chars, linfo);
5867 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "}");
5868 ✗ then (chars, linfo, TplAbsyn.LIST_MATCH(headMExp :: mrest));
5869
5870 case ("_":: chars, linfo)
5871 ✗ then (chars, linfo, TplAbsyn.REST_MATCH());
5872
5873 case (chars, linfo)
5874 algorithm
5875 ✗ (chars, linfo, strRevList) := stringConstant(chars, linfo);
5876 ✗ str := stringAppendList(listReverse(strRevList));
5877 ✗ then (chars, linfo, TplAbsyn.STRING_MATCH(str));
5878
5879 case (chars, linfo)
5880 algorithm
5881 ✗ (chars, linfo, str, ts) := literalConstant(chars, linfo);
5882 ✗ then (chars, linfo, TplAbsyn.LITERAL_MATCH(str,ts));
5883
5884 case (chars, linfo)
5885 algorithm
5886 ✗ (chars, linfo, pid) := pathIdent(chars, linfo);
5887 ✗ (chars, linfo) := interleave(chars, linfo);
5888 ✗ (chars, linfo, mexp) := afterIdentBinding(chars, linfo, pid);
5889 then (chars, linfo, mexp);
5890
5891 case (chars, linfo)
5892 algorithm
5893 ✗ linfo := parseError(chars, linfo, "Expected a valid match binding expression at the position.", true);
5894 //true = Flags.isSet(Flags.FAILTRACE); Debug.trace("Parse error - TplParser.matchBinding_base failed .\n");
5895 ✗ then (chars, linfo, TplAbsyn.LITERAL_MATCH("#Error#", TplAbsyn.UNRESOLVED_TYPE("#Error#")));
5896
5897 end matchcontinue;
5898 end matchBinding_base;
5899 /*
5900 someBinding_rest:
5901 '(' '__' ')'
5902 => SOME_MATCH(REST_MATCH())
5903 |
5904 '(' matchBinding:mexp ')'
5905 => SOME_MATCH(mexp)
5906 |
5907 _ => SOME_MATCH(REST_MATCH())
5908 */
5909 public function someBinding_rest
5910 input list<String> inChars;
5911 input LineInfo inLineInfo;
5912
5913 output list<String> outChars;
5914 output LineInfo outLineInfo;
5915 output TplAbsyn.MatchingExp outMatchingExp;
5916 algorithm
5917 (outChars, outLineInfo, outMatchingExp) :=
5918 matchcontinue (inChars, inLineInfo)
5919 local
5920 list<String> chars;
5921 LineInfo linfo;
5922 TplAbsyn.MatchingExp mexp;
5923
5924 case ("(":: chars, linfo)
5925 algorithm
5926 ✗ (chars, linfo) := interleave(chars, linfo);
5927 ✗ "_"::"_":: chars := chars;
5928 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
5929 ✗ then (chars, linfo, TplAbsyn.REST_MATCH());
5930
5931 case ("(":: chars, linfo)
5932 algorithm
5933 ✗ (chars, linfo) := interleave(chars, linfo);
5934 ✗ (chars, linfo, mexp) := matchBinding(chars, linfo);
5935 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
5936 ✗ then (chars, linfo, mexp);
5937
5938 else (inChars, inLineInfo, TplAbsyn.REST_MATCH());
5939
5940 end matchcontinue;
5941 end someBinding_rest;
5942 /*
5943 takeEmptyBraces:
5944 '(' ')'
5945 |
5946 _
5947 */
5948 public function takeEmptyBraces
5949 input list<String> inChars;
5950 input LineInfo inLineInfo;
5951 output list<String> outChars;
5952 output LineInfo outLineInfo;
5953 algorithm
5954 (outChars, outLineInfo) :=
5955 matchcontinue (inChars, inLineInfo)
5956 local
5957 list<String> chars;
5958 LineInfo linfo;
5959
5960 case ("(":: chars, linfo)
5961 algorithm
5962 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
5963 then (chars, linfo);
5964
5965 ✗ else (inChars, inLineInfo);
5966
5967 end matchcontinue;
5968 end takeEmptyBraces;
5969 /*
5970 tupleOrSingleMatch(headMExp):
5971 ',' matchBinding:secMExp listMatch_rest:mrest
5972 => TUPLE_MATCH(headMExp :: secMExp :: mrest)
5973 |
5974 _ => headMExp
5975
5976 */
5977 public function tupleOrSingleMatch
5978 input list<String> inChars;
5979 input LineInfo inLineInfo;
5980 input TplAbsyn.MatchingExp inHeadMatchingExp;
5981
5982 output list<String> outChars;
5983 output LineInfo outLineInfo;
5984 output TplAbsyn.MatchingExp outMatchingExp;
5985 algorithm
5986 (outChars, outLineInfo, outMatchingExp) :=
5987 matchcontinue (inChars, inLineInfo, inHeadMatchingExp)
5988 local
5989 list<String> chars;
5990 LineInfo linfo;
5991 TplAbsyn.MatchingExp headMExp, secMExp;
5992 list<TplAbsyn.MatchingExp> mrest;
5993
5994 case (",":: chars, linfo, headMExp)
5995 algorithm
5996 ✗ (chars, linfo) := interleave(chars, linfo);
5997 ✗ (chars, linfo, secMExp) := matchBinding(chars, linfo);
5998 ✗ (chars, linfo) := interleave(chars, linfo);
5999 ✗ (chars, linfo, mrest) := listMatch_rest(chars, linfo);
6000 ✗ then (chars, linfo, TplAbsyn.TUPLE_MATCH(headMExp :: secMExp :: mrest));
6001
6002 else (inChars, inLineInfo, inHeadMatchingExp);
6003
6004 end matchcontinue;
6005 end tupleOrSingleMatch;
6006 /*
6007 listMatch_rest:
6008 ',' matchBinding:mexp listMatch_rest:mrest
6009 => mexp :: mrest
6010 |
6011 _ => {}
6012
6013 */
6014 public function listMatch_rest
6015 input list<String> inChars;
6016 input LineInfo inLineInfo;
6017
6018 output list<String> outChars;
6019 output LineInfo outLineInfo;
6020 output list<TplAbsyn.MatchingExp> outMatchingExpListRest;
6021 algorithm
6022 (outChars, outLineInfo, outMatchingExpListRest) :=
6023 matchcontinue (inChars, inLineInfo)
6024 local
6025 list<String> chars;
6026 LineInfo linfo;
6027 TplAbsyn.MatchingExp mexp;
6028 list<TplAbsyn.MatchingExp> mrest;
6029
6030 case (",":: chars, linfo)
6031 algorithm
6032 ✗ (chars, linfo) := interleave(chars, linfo);
6033 ✗ (chars, linfo, mexp) := matchBinding(chars, linfo);
6034 ✗ (chars, linfo) := interleave(chars, linfo);
6035 ✗ (chars, linfo, mrest) := listMatch_rest(chars, linfo);
6036 ✗ then (chars, linfo, mexp :: mrest);
6037
6038 else (inChars, inLineInfo, {});
6039
6040 end matchcontinue;
6041 end listMatch_rest;
6042 /*
6043 afterIdentBinding(pid):
6044 '(' ')'
6045 => RECORD_MATCH(pid, {})
6046 |
6047 '(' '__' ')'
6048 => RECORD_MATCH(pid, {}) //TODO: to be RECORD_TYPE_MATCH(pid)
6049 |
6050 '(' fieldBinding:fb fieldBinding_rest:fbs ')'
6051 => RECORD_MATCH(pid, fb::fbs)
6052 |
6053 {pid is PATH_IDENT}
6054 => error "Expected '(' after the dot path."
6055 //RECORD_MATCH(pid, {})
6056 |
6057 {pid is IDENT(id)}
6058 'as' matchBinding:mexp
6059 => BIND_AS_MATCH(id, mexp)
6060 |
6061 {pid is IDENT(id)}
6062 _ => BIND_MATCH(id)
6063 */
6064 public function afterIdentBinding
6065 input list<String> inChars;
6066 input LineInfo inLineInfo;
6067 input TplAbsyn.PathIdent inPathIdent;
6068
6069 output list<String> outChars;
6070 output LineInfo outLineInfo;
6071 output TplAbsyn.MatchingExp outMatchingExp;
6072 algorithm
6073 (outChars, outLineInfo, outMatchingExp) :=
6074 matchcontinue (inChars, inLineInfo, inPathIdent)
6075 local
6076 list<String> chars;
6077 LineInfo linfo;
6078 TplAbsyn.Ident id;
6079 TplAbsyn.PathIdent pid;
6080 TplAbsyn.MatchingExp mexp;
6081 tuple<TplAbsyn.Ident, TplAbsyn.MatchingExp> fb;
6082 list<tuple<TplAbsyn.Ident, TplAbsyn.MatchingExp>> fbs;
6083
6084 case ("(":: chars, linfo, pid)
6085 algorithm
6086 ✗ (chars, linfo) := interleave(chars, linfo);
6087 ✗ ")":: chars := chars;
6088 ✗ then (chars, linfo, TplAbsyn.RECORD_MATCH(pid, {}));
6089
6090 case ("(":: chars, linfo, pid)
6091 algorithm
6092 ✗ (chars, linfo) := interleave(chars, linfo);
6093 ✗ "_"::"_":: chars := chars;
6094 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
6095 ✗ then (chars, linfo, TplAbsyn.RECORD_MATCH(pid, {}));
6096
6097 case ("(":: chars, linfo, pid)
6098 algorithm
6099 ✗ (chars, linfo) := interleave(chars, linfo);
6100 ✗ (chars, linfo, fb) := fieldBinding(chars, linfo);
6101 ✗ (chars, linfo) := interleave(chars, linfo);
6102 ✗ (chars, linfo, fbs) := fieldBinding_rest(chars, linfo);
6103 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, ")");
6104 ✗ then (chars, linfo, TplAbsyn.RECORD_MATCH(pid, fb::fbs));
6105
6106 case (chars, linfo, pid as TplAbsyn.PATH_IDENT(_,_))
6107 algorithm
6108 ✗ linfo := parseError(chars, linfo, "Expected '(' after the dot path.", false);
6109 ✗ then (chars, linfo, TplAbsyn.RECORD_MATCH(pid, {}));
6110
6111 case ("a"::"s":: chars, linfo, TplAbsyn.IDENT(id))
6112 algorithm
6113 ✗ afterKeyword(chars);
6114 ✗ (chars, linfo) := interleave(chars, linfo);
6115 ✗ (chars, linfo, mexp) := matchBinding(chars, linfo);
6116 ✗ then (chars, linfo, TplAbsyn.BIND_AS_MATCH(id, mexp));
6117
6118 case (chars, linfo, TplAbsyn.IDENT(id))
6119 ✗ then (chars, linfo, TplAbsyn.BIND_MATCH(id));
6120
6121 else
6122 algorithm
6123 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("!!! TplParser.afterIdentBinding failed.\n");
6124 ✗ then fail();
6125
6126 end matchcontinue;
6127 end afterIdentBinding;
6128
6129
6130
6131 /*
6132 must not fail
6133 fieldBinding:
6134 identifier:fldId '=' matchBinding:mexp
6135 => (fldId, mexp)
6136 */
6137 public function fieldBinding
6138 input list<String> inChars;
6139 input LineInfo inLineInfo;
6140
6141 output list<String> outChars;
6142 output LineInfo outLineInfo;
6143 output tuple<TplAbsyn.Ident, TplAbsyn.MatchingExp> outFieldBinding;
6144 algorithm
6145 (outChars, outLineInfo, outFieldBinding) :=
6146 matchcontinue (inChars, inLineInfo)
6147 local
6148 list<String> chars;
6149 LineInfo linfo;
6150 TplAbsyn.Ident id;
6151 TplAbsyn.MatchingExp mexp;
6152
6153 case (chars, linfo)
6154 algorithm
6155 ✗ (chars, linfo, id) := identifierNoOpt(chars, linfo);
6156 ✗ (chars, linfo) := interleaveExpectChar(chars, linfo, "=");
6157 ✗ (chars, linfo) := interleave(chars, linfo);
6158 ✗ (chars, linfo, mexp) := matchBinding(chars, linfo);
6159 ✗ then (chars, linfo, (id, mexp));
6160
6161 else
6162 algorithm
6163 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("- !!! TplParser.fieldBinding failed.\n");
6164 ✗ then fail();
6165
6166 end matchcontinue;
6167 end fieldBinding;
6168 /*
6169 fieldBinding_rest:
6170 ',' fieldBinding:fb fieldBinding_rest:fbs
6171 => fb :: fbs
6172 |
6173 _ => {}
6174
6175 */
6176 public function fieldBinding_rest
6177 input list<String> inChars;
6178 input LineInfo inLineInfo;
6179
6180 output list<String> outChars;
6181 output LineInfo outLineInfo;
6182 output list<tuple<TplAbsyn.Ident, TplAbsyn.MatchingExp>> outFieldBindingsRest;
6183 algorithm
6184 (outChars, outLineInfo, outFieldBindingsRest) :=
6185 matchcontinue (inChars, inLineInfo)
6186 local
6187 list<String> chars;
6188 LineInfo linfo;
6189 tuple<TplAbsyn.Ident, TplAbsyn.MatchingExp> fb;
6190 list<tuple<TplAbsyn.Ident, TplAbsyn.MatchingExp>> fbs;
6191
6192 case (",":: chars, linfo)
6193 algorithm
6194 ✗ (chars, linfo) := interleave(chars, linfo);
6195 ✗ (chars, linfo, fb) := fieldBinding(chars, linfo);
6196 ✗ (chars, linfo) := interleave(chars, linfo);
6197 ✗ (chars, linfo, fbs) := fieldBinding_rest(chars, linfo);
6198 ✗ then (chars, linfo, fb :: fbs);
6199
6200 else (inChars, inLineInfo, {});
6201
6202 end matchcontinue;
6203 end fieldBinding_rest;
6204
6205 /*
6206 annotationFooter:
6207 'annotation(...)' => str
6208 |
6209 _ => ""
6210
6211 */
6212 protected function annotationFooter
6213 input list<String> inChars;
6214 input LineInfo inLineInfo;
6215
6216 output list<String> chars;
6217 output LineInfo linfo;
6218 output String footer;
6219 algorithm
6220 (chars,linfo,footer) := match (inChars,inLineInfo)
6221 local
6222 list<String> footerChars;
6223 case ("a"::"n"::"n"::"o"::"t"::"a"::"t"::"i"::"o"::"n"::chars, linfo)
6224 algorithm
6225 ✗ (footerChars,chars) := List.split(inChars,List.position(";", inChars)+1);
6226 ✗ footer := stringAppendList(footerChars);
6227 ✗ then (chars,linfo,footer);
6228 else (inChars,inLineInfo,"annotation(__OpenModelica_generator=\"Susan\");"); // No annotation; put default footer
6229 end match;
6230 end annotationFooter;
6231
6232 annotation(__OpenModelica_Interface="susan");
6233 end TplParser;
6234