@@ -232,7 +232,9 @@ static inline void pop_state(yyscan_t yyscanner);
232
232
233
233
static void startScope(yyscan_t yyscanner,Entry *scope);
234
234
static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot=FALSE);
235
+ static void copyEntry(std::shared_ptr<Entry> dest, const std::shared_ptr<Entry> &src);
235
236
static void resolveModuleProcedures(yyscan_t yyscanner,Entry *current_root);
237
+ static void resolveTypeBoundProcedures(Entry *scope);
236
238
static void truncatePrepass(yyscan_t yyscanner,int index);
237
239
static void pushBuffer(yyscan_t yyscanner,const QCString &buffer);
238
240
static void popBuffer(yyscan_t yyscanner);
@@ -721,7 +723,7 @@ private {
721
723
722
724
<TypedefBodyContains>{ /* Type Bound Procedures */
723
725
^{BS}PROCEDURE{ARGS}? {
724
- yyextra->current->type = QCString(yytext).simplifyWhiteSpace();
726
+ yyextra->current->type = QCString(yytext).simplifyWhiteSpace().lower() ;
725
727
}
726
728
^{BS}final {
727
729
yyextra->current->spec |= Entry::Final;
@@ -733,7 +735,7 @@ private {
733
735
{COMMA} {
734
736
}
735
737
{ATTR_SPEC} {
736
- yyextra->currentModifiers |= QCString(yytext);
738
+ yyextra->currentModifiers |= QCString(yytext).stripWhiteSpace() ;
737
739
}
738
740
{BS}"::"{BS} {
739
741
}
@@ -742,14 +744,46 @@ private {
742
744
yyextra->modifiers[yyextra->current_root][name.lower().str()] |= yyextra->currentModifiers;
743
745
yyextra->current->section = Entry::FUNCTION_SEC;
744
746
yyextra->current->name = name;
747
+ // check for procedure(name)
748
+ if (yyextra->current->type.find('(') != -1)
749
+ {
750
+ yyextra->current->args = extractFromParens(yyextra->current->type).stripWhiteSpace();
751
+ }
752
+ else
753
+ {
754
+ yyextra->current->args = name.lower(); // target procedure name if no => is given
755
+ }
745
756
yyextra->current->fileName = yyextra->fileName;
746
757
yyextra->current->bodyLine = yyextra->lineNr;
747
758
yyextra->current->startLine = yyextra->lineNr;
748
759
addCurrentEntry(yyscanner,true);
749
760
}
750
761
{BS}"=>"[^(\n|\!)]* { /* Specific bindings come after the ID. */
751
- QCString args = yytext;
752
- yyextra->last_entry->args = args.lower();
762
+ QCString tmp = yytext;
763
+ int i = tmp.find("=>");
764
+ if( i != -1 )
765
+ tmp.remove(0, i+2);
766
+ tmp = tmp.simplifyWhiteSpace().lower();
767
+ if( yyextra->last_entry->type == "generic")
768
+ {
769
+ // duplicate entries for each overloaded variant
770
+ // (parse through medhod1,method2, methodN, ...
771
+ //printf("Parsing through %s for generic method %s.\n", tmp.data(), last_entry->name.data());
772
+ int i = tmp.find(",");
773
+ while(i > 0)
774
+ {
775
+ copyEntry(yyextra->current, yyextra->last_entry);
776
+ yyextra->current->name = yyextra->last_entry->name;
777
+ yyextra->current->section = Entry::FUNCTION_SEC;
778
+ yyextra->last_entry->args = tmp.left(i).stripWhiteSpace();
779
+ //printf("Found %s.\n", last_entry->args.data());
780
+ addCurrentEntry(yyscanner,true);
781
+ tmp = tmp.remove(0,i+1).stripWhiteSpace();
782
+ i = tmp.find(",");
783
+ }
784
+ }
785
+ //printf("Target function: %s\n", tmp.data());
786
+ yyextra->last_entry->args = tmp;
753
787
}
754
788
"\n" {
755
789
yyextra->currentModifiers = SymbolModifiers();
@@ -1869,7 +1903,11 @@ static void copyEntry(std::shared_ptr<Entry> dest, const std::shared_ptr<Entry>
1869
1903
dest->args = src->args;
1870
1904
dest->argList = src->argList;
1871
1905
dest->doc = src->doc;
1906
+ dest->docLine = src->docLine;
1907
+ dest->docFile = src->docFile;
1872
1908
dest->brief = src->brief;
1909
+ dest->briefLine= src->briefLine;
1910
+ dest->briefFile= src->briefFile;
1873
1911
}
1874
1912
1875
1913
/** fill empty interface module procedures with info from
@@ -2251,6 +2289,13 @@ static void applyModifiers(Entry *ent, const SymbolModifiers& mdfs)
2251
2289
ent->protection = Public;
2252
2290
else if (mdfs.protection == SymbolModifiers::PRIVATE)
2253
2291
ent->protection = Private;
2292
+
2293
+ if (mdfs.nonoverridable)
2294
+ ent->spec |= Entry::Final;
2295
+ if (mdfs.nopass)
2296
+ ent->stat = TRUE;
2297
+ if (mdfs.deferred)
2298
+ ent->virt = Pure;
2254
2299
}
2255
2300
2256
2301
/*! Starts the new scope in fortran program. Consider using this function when
@@ -2375,7 +2420,7 @@ static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot)
2375
2420
// iterate variables: get and apply yyextra->modifiers
2376
2421
for (const auto &ce : scope->children())
2377
2422
{
2378
- if (ce->section != Entry::VARIABLE_SEC && ce->section != Entry::FUNCTION_SEC && ce->section != Entry::CLASS_SEC && ce->section != Entry::FUNCTION_SEC )
2423
+ if (ce->section != Entry::VARIABLE_SEC && ce->section != Entry::FUNCTION_SEC && ce->section != Entry::CLASS_SEC)
2379
2424
continue;
2380
2425
2381
2426
//cout<<ce->name<<", "<<mdfsMap.contains(ce->name.lower())<<mdfsMap.count()<<endl;
@@ -2395,9 +2440,163 @@ static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot)
2395
2440
// clear all yyextra->modifiers of the scope
2396
2441
yyextra->modifiers.erase(scope);
2397
2442
2443
+ // resolve procedures in types
2444
+ resolveTypeBoundProcedures(scope);
2445
+
2398
2446
return TRUE;
2399
2447
}
2400
2448
2449
+ /*! search for types with type bound procedures (e.g. methods)
2450
+ * and try to resolve their arguments
2451
+ */
2452
+ static void resolveTypeBoundProcedures(Entry *scope)
2453
+ {
2454
+ // map of all subroutines/functions
2455
+ bool procMapCreated = false;
2456
+ std::map<std::string,std::shared_ptr<Entry>> procMap;
2457
+
2458
+ // map of all abstract interfaces
2459
+ bool interfMapCreated = false;
2460
+ std::map<std::string,std::shared_ptr<Entry>> interfMap;
2461
+
2462
+ // iterate over all types
2463
+ for(const auto &ce: scope->children())
2464
+ {
2465
+ if (ce->section != Entry::CLASS_SEC)
2466
+ continue;
2467
+
2468
+ // handle non-"generic" non-"deferred" methods, copying the arguments from the implementation
2469
+ std::map<std::string,std::shared_ptr<Entry>> methodMap;
2470
+ for(auto &ct: ce->children())
2471
+ {
2472
+ if (ct->section != Entry::FUNCTION_SEC)
2473
+ continue;
2474
+
2475
+ if (ct->type=="generic")
2476
+ continue;
2477
+
2478
+ if (ct->virt == Pure)
2479
+ continue;
2480
+
2481
+ // set up the procMap
2482
+ if (!procMapCreated)
2483
+ {
2484
+ for(const auto &cf: scope->children())
2485
+ {
2486
+ if (cf->section == Entry::FUNCTION_SEC)
2487
+ {
2488
+ procMap.insert(std::make_pair(cf->name.str(), cf));
2489
+ }
2490
+ }
2491
+ procMapCreated = true;
2492
+ }
2493
+
2494
+ // found a (non-generic) method
2495
+ QCString implName = ct->args;
2496
+ if( procMap.find(implName.str()) != procMap.end() )
2497
+ {
2498
+ std::shared_ptr<Entry> proc = procMap[implName.str()];
2499
+ ct->args = proc->args;
2500
+ ct->argList = ArgumentList(proc->argList);
2501
+ if (ct->brief.isEmpty())
2502
+ {
2503
+ ct->brief = proc->brief;
2504
+ ct->briefLine = proc->briefLine;
2505
+ ct->briefFile = proc->briefFile;
2506
+ }
2507
+ if (ct->doc.isEmpty())
2508
+ {
2509
+ ct->doc = proc->doc;
2510
+ ct->docLine = proc->docLine;
2511
+ ct->docFile = proc->docFile;
2512
+ }
2513
+ methodMap.insert(std::make_pair(ct->name.str(), ct));
2514
+ }
2515
+ }
2516
+
2517
+ // handle "deferred" methods (pure virtual functions), duplicating with arguments from the target abstract interface
2518
+ for(auto &ct: ce->children())
2519
+ {
2520
+ if (ct->section != Entry::FUNCTION_SEC)
2521
+ continue;
2522
+
2523
+ if (ct->virt != Pure)
2524
+ continue;
2525
+
2526
+ // set up the procMap
2527
+ if (!interfMapCreated)
2528
+ {
2529
+ for(const auto &cf: scope->children())
2530
+ {
2531
+ if (cf->section == Entry::CLASS_SEC && cf->spec & Entry::Interface && cf->type == "abstract")
2532
+ {
2533
+ std::shared_ptr<Entry> ci = cf->children().front();
2534
+ interfMap.insert(std::make_pair(ci->name.str(), ci));
2535
+ }
2536
+ }
2537
+ interfMapCreated = true;
2538
+ }
2539
+
2540
+ // found a (non-generic) method
2541
+ QCString implName = ct->args;
2542
+ if( interfMap.find(implName.str())!= interfMap.end() )
2543
+ {
2544
+ std::shared_ptr<Entry> proc = interfMap[implName.str()];
2545
+ ct->args = proc->args;
2546
+ ct->argList = ArgumentList(proc->argList);
2547
+ if (ct->brief.isEmpty())
2548
+ {
2549
+ ct->brief = proc->brief;
2550
+ ct->briefLine = proc->briefLine;
2551
+ ct->briefFile = proc->briefFile;
2552
+ }
2553
+ if (ct->doc.isEmpty())
2554
+ {
2555
+ ct->doc = proc->doc;
2556
+ ct->docLine = proc->docLine;
2557
+ ct->docFile = proc->docFile;
2558
+ }
2559
+
2560
+ methodMap.insert(std::make_pair(ct->name.str(), ct));
2561
+ }
2562
+ }
2563
+
2564
+ // handle "generic" methods (that is function overloading!), duplicating with arguments from the target method of the type
2565
+ {
2566
+ for(auto &ct: ce->children())
2567
+ {
2568
+ if (ct->section != Entry::FUNCTION_SEC)
2569
+ continue;
2570
+
2571
+ if (ct->type!="generic")
2572
+ continue;
2573
+
2574
+ // found a generic method (already duplicated for each entry by the parser)
2575
+ QCString methodName = ct->args;
2576
+ if( methodMap.find(methodName.str()) != methodMap.end() )
2577
+ {
2578
+ std::shared_ptr<Entry> method = methodMap[methodName.str()];
2579
+ ct->args = method->args;
2580
+ ct->argList = ArgumentList(method->argList);
2581
+ if (ct->brief.isEmpty())
2582
+ {
2583
+ ct->brief = method->brief;
2584
+ ct->briefLine = method->briefLine;
2585
+ ct->briefFile = method->briefFile;
2586
+ }
2587
+ if (ct->doc.isEmpty())
2588
+ {
2589
+ ct->doc = method->doc;
2590
+ ct->docLine = method->docLine;
2591
+ ct->docFile = method->docFile;
2592
+ }
2593
+ }
2594
+ }
2595
+ }
2596
+ }
2597
+ }
2598
+
2599
+
2401
2600
static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
2402
2601
{
2403
2602
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
0 commit comments