1 module epsilon.analyzer; 2 3 import EAG = epsilon.eag; 4 import Earley = epsilon.earley; 5 import epsilon.lexer : Lexer, Token; 6 import io : Input, Position; 7 import log; 8 import runtime; 9 import std.bitmanip : BitArray; 10 import std.conv : to; 11 12 const nil = EAG.nil; 13 int ErrorCounter; 14 bool NameNotified; 15 16 Lexer lexer; 17 18 void Error(Position Pos, string ErrMsg) @safe 19 { 20 import std.exception : enforce; 21 22 ++ErrorCounter; 23 24 enforce(ErrorCounter <= 25, 25 "Too many errors!"); 26 27 error!"%s\n%s"(ErrMsg, Pos); 28 } 29 30 /** 31 * Specification: 32 * (MetaRule | HyperRule) {MetaRule | HyperRule} . 33 */ 34 void Specification() 35 { 36 /** 37 * MetaRule: 38 * ident "=" MetaExpr ".". 39 */ 40 void MetaRule(int Id, bool IsToken) 41 { 42 const MNont = EAG.FindMNont(Id); 43 44 /** 45 * MetaExpr: 46 * MetaTerm {"|" MetaTerm}. 47 */ 48 void MetaExpr() 49 { 50 /** 51 * MetaTerm: 52 * {ident | string}. 53 */ 54 void MetaTerm() 55 { 56 while (true) 57 { 58 if (lexer.front == Token.name) 59 { 60 EAG.AppMemb(EAG.FindMNont(lexer.value.to!int)); 61 lexer.popFront; 62 if (lexer.front == Token.number) 63 { 64 Error(lexer.position, "number is not allowed here"); 65 lexer.popFront; 66 } 67 } 68 else if (lexer.front == Token.string_) 69 { 70 EAG.AppMemb(-EAG.FindMTerm(lexer.value.to!int)); 71 lexer.popFront; 72 } 73 else 74 { 75 EAG.AppMemb(EAG.nil); 76 break; 77 } 78 } 79 } 80 81 while (true) 82 { 83 const Rhs = EAG.NextMemb; 84 85 MetaTerm; 86 EAG.AppMemb(EAG.NewMAlt(MNont, Rhs)); 87 if (lexer.front == '|') 88 lexer.popFront; 89 else 90 break; 91 } 92 } 93 94 EAG.MNont[MNont].IsToken = EAG.MNont[MNont].IsToken || IsToken; 95 if (lexer.front == '=') 96 lexer.popFront; 97 else 98 Error(lexer.position, "'=' expected"); 99 MetaExpr; 100 if (lexer.front == '.') 101 lexer.popFront; 102 else 103 Error(lexer.position, "'.' expected"); 104 } 105 106 void SetBaseName() 107 { 108 EAG.StartSym = EAG.firstHNont; 109 EAG.BaseName = EAG.symbolTable.symbol(EAG.HNont[EAG.StartSym].Id); 110 } 111 112 /** 113 * HyperRule: 114 * ident [FormalParams] ":" HyperExpr ".". 115 */ 116 void HyperRule(int Id, bool IsToken) 117 { 118 void Distribute(int Sym, EAG.Alt A, int Sig, EAG.ParamsDesc Formal) 119 { 120 void CopyParams(ref int s, ref int d) 121 { 122 int Affixform; 123 int P = s; 124 125 d = EAG.NextParam; 126 while (EAG.ParamBuf[P].Affixform != nil) 127 { 128 Earley.CopyAffixform(EAG.ParamBuf[P].Affixform, Affixform); 129 EAG.AppParam(Affixform, EAG.ParamBuf[P].Pos); 130 ++P; 131 } 132 EAG.AppParam(nil, EAG.ParamBuf[P].Pos); 133 } 134 135 EAG.HNont[Sym].Sig = Sig; 136 A.Formal.Pos = Formal.Pos; 137 A.Formal.Params = Formal.Params; 138 A = A.Next; 139 while (A !is null) 140 { 141 A.Formal.Pos = Formal.Pos; 142 CopyParams(Formal.Params, A.Formal.Params); 143 A = A.Next; 144 } 145 } 146 147 /** 148 * FormalParams: 149 * "<" ("+" | "-") Affixform ":" ident {"," ("+" | "-") Affixform ":" ident} ">". 150 * ActualParams: 151 * "<" Affixform {"," Affixform} ">". 152 */ 153 void Params(ref EAG.ParamsDesc Actual, ref EAG.ParamsDesc Formal) 154 { 155 /** 156 * Affixform: 157 * {string | ["!"] ident [number]}. 158 */ 159 void Affixform(ref int Sym) 160 { 161 int Cnt = 0; 162 163 while (true) 164 { 165 short Uneq; 166 int Num; 167 Position Pos = lexer.position; 168 169 if (lexer.front == Token.string_) 170 { 171 Sym = -EAG.FindMTerm(lexer.value.to!int); 172 Num = 0; 173 lexer.popFront; 174 ++Cnt; 175 } 176 else if (lexer.front == '!' || lexer.front == Token.name) 177 { 178 if (lexer.front == '!') 179 { 180 Uneq = -1; 181 lexer.popFront; 182 } 183 else 184 { 185 Uneq = 1; 186 } 187 if (lexer.front == Token.name) 188 { 189 Sym = EAG.FindMNont(lexer.value.to!int); 190 lexer.popFront; 191 if (lexer.front == Token.number) 192 { 193 Num = Uneq * (lexer.value.to!int + 2); 194 lexer.popFront; 195 } 196 else 197 { 198 Num = Uneq; 199 } 200 ++Cnt; 201 } 202 else 203 { 204 Error(lexer.position, "Metanonterminal expected"); 205 } 206 } 207 else 208 { 209 Earley.EndAffixform(Pos); 210 break; 211 } 212 Earley.AppMSym(Sym, Num, Pos); 213 } 214 if (Cnt != 1) 215 Sym = -1; 216 } 217 218 EAG.ParamsDesc P; 219 220 P.Params = EAG.empty; 221 P.Pos = lexer.position; 222 Actual = P; 223 Formal = P; 224 if (lexer.front == '<') 225 { 226 lexer.popFront; 227 228 bool isFormal = lexer.front == '+' || lexer.front == '-'; 229 230 P.Params = EAG.NextParam; 231 while (true) 232 { 233 char Dir; 234 int Sym; 235 236 if (lexer.front == '+' || lexer.front == '-') 237 { 238 if (!isFormal) 239 Error(lexer.position, "'+' or '-' not allowed in actual params"); 240 Dir = lexer.front.to!char; 241 lexer.popFront; 242 } 243 else 244 { 245 if (isFormal) 246 Error(lexer.position, "'+' or '-' expected"); 247 } 248 EAG.AppParam(Earley.StartAffixform(), lexer.position); 249 Affixform(Sym); 250 if (isFormal) 251 { 252 if (Sym < 0 || lexer.front == ':') 253 { 254 if (lexer.front == ':') 255 lexer.popFront; 256 else 257 Error(lexer.position, "':' expected"); 258 if (lexer.front == Token.name) 259 { 260 EAG.AppDom(Dir, EAG.FindMNont(lexer.value.to!int)); 261 lexer.popFront; 262 } 263 else 264 { 265 Error(lexer.position, "Metanonterminal expected"); 266 } 267 if (lexer.front == Token.number) 268 { 269 Error(lexer.position, "number is not allowed here"); 270 lexer.popFront; 271 } 272 } 273 else 274 { 275 EAG.AppDom(Dir, Sym); 276 } 277 } 278 while (lexer.front != ',' && lexer.front != '>' && lexer.front != Token.end) 279 { 280 Error(lexer.position, "symbol not allowed"); 281 lexer.popFront; 282 } 283 if (lexer.front == ',') 284 lexer.popFront; 285 else 286 break; 287 } 288 EAG.AppParam(EAG.nil, lexer.position); 289 if (lexer.front == '>') 290 lexer.popFront; 291 else 292 Error(lexer.position, "'>' expected"); 293 if (isFormal) 294 Formal.Params = P.Params; 295 else 296 Actual.Params = P.Params; 297 } 298 } 299 300 /** 301 * HyperExpr: 302 * [FormalParams] HyperTerm [ActualParams] {"|" [FormalParams] HyperTerm [ActualParams]}. 303 */ 304 void HyperExpr(int HNont, int Id, char Left, ref EAG.Alt HExpr, Position AltPos) 305 { 306 /** 307 * HyperTerm: 308 * { ident [ActualParams] 309 * | string 310 * | [ActualParams] ( "(" HyperExpr ")" 311 * | "[" HyperExpr "]" [FormalParams] 312 * | "{" HyperExpr "}" [FormalParams] ) 313 * } . 314 */ 315 void HyperTerm(ref EAG.ParamsDesc Actual, ref EAG.Factor First, ref EAG.Factor Last) 316 { 317 int HNont; 318 EAG.Alt HExpr; 319 EAG.ParamsDesc Formal; 320 char Left; 321 Position Pos; 322 323 First = null; 324 Last = null; 325 while (true) 326 { 327 if (lexer.front == Token.name) 328 { 329 if (Actual.Params != EAG.empty) 330 { 331 Error(Actual.Pos, "actual params not allowed here"); 332 Actual.Params = EAG.empty; 333 } 334 HNont = EAG.FindHNont(lexer.value.to!int); 335 Pos = lexer.position; 336 lexer.popFront; 337 if (lexer.front == Token.number) 338 { 339 Error(lexer.position, "number is not allowed here!"); 340 lexer.popFront; 341 } 342 Params(Actual, Formal); 343 if (Formal.Params != EAG.empty) 344 Error(Formal.Pos, "formal params not allowed here"); 345 EAG.NewNont(Last, HNont, Actual, Pos); 346 Actual.Params = EAG.empty; 347 } 348 else if (lexer.front == Token.string_) 349 { 350 if (Actual.Params != EAG.empty) 351 { 352 Error(Actual.Pos, "actual params not allowed here"); 353 Actual.Params = EAG.empty; 354 } 355 EAG.NewTerm(Last, EAG.FindHTerm(lexer.value.to!int), lexer.position); 356 lexer.popFront; 357 } 358 else 359 { 360 if (Actual.Params == EAG.empty) 361 { 362 Params(Actual, Formal); 363 if (Formal.Params != EAG.empty) 364 Error(Formal.Pos, "formal params not allowed here"); 365 } 366 if (lexer.front == '(' || lexer.front == '[' || lexer.front == '{') 367 { 368 Pos = lexer.position; 369 HNont = EAG.NewAnonymNont(Id); 370 EAG.NewNont(Last, HNont, Actual, Pos); 371 Actual.Params = EAG.empty; 372 if (lexer.front == '(') 373 { 374 lexer.popFront; 375 HyperExpr(HNont, Id, '(', HExpr, Pos); 376 if (lexer.front == ')') 377 lexer.popFront; 378 else 379 Error(lexer.position, "')' expected"); 380 EAG.NewGrp(HNont, HExpr); 381 } 382 else 383 { 384 Left = lexer.front.to!char; 385 lexer.popFront; 386 HyperExpr(HNont, Id, Left, HExpr, Pos); 387 Pos = lexer.position; 388 if (Left == '{') 389 { 390 if (lexer.front == '}') 391 lexer.popFront; 392 else 393 Error(lexer.position, "'}' expected"); 394 } 395 else 396 { 397 if (lexer.front == ']') 398 lexer.popFront; 399 else 400 Error(lexer.position, "']' expected"); 401 } 402 Params(Actual, Formal); 403 if (!EAG.SigOK(HNont)) 404 Error(Formal.Pos, "formal params differ"); 405 if (Left == '{') 406 EAG.NewRep(HNont, HExpr, Formal, Pos); 407 else 408 EAG.NewOpt(HNont, HExpr, Formal, Pos); 409 } 410 } 411 else 412 { 413 return; 414 } 415 } 416 if (First is null) 417 First = Last; 418 } 419 } 420 421 EAG.Alt Last = null; 422 423 HExpr = null; 424 while (true) 425 { 426 EAG.ParamsDesc Actual; 427 EAG.ParamsDesc Formal; 428 EAG.ParamsDesc Formal1; 429 EAG.Factor FirstF; 430 EAG.Factor LastF; 431 432 Params(Actual, Formal); 433 if (!EAG.SigOK(HNont)) 434 Error(Formal.Pos, "formal params differ"); 435 HyperTerm(Actual, FirstF, LastF); 436 if (Left == '{' && Actual.Params == EAG.empty) 437 { 438 Params(Actual, Formal1); 439 if (Formal1.Params != EAG.empty) 440 Error(Formal1.Pos, "formal params not allowed here"); 441 } 442 else if (Left != '{' && Actual.Params != EAG.empty) 443 { 444 Error(Actual.Pos, "actual params not allowed here"); 445 Actual.Params = EAG.empty; 446 } 447 EAG.NewAlt(Last, HNont, Formal, Actual, FirstF, LastF, AltPos); 448 if (HExpr is null) 449 HExpr = Last; 450 if (lexer.front == '|') 451 { 452 AltPos = lexer.position; 453 lexer.popFront; 454 } 455 else 456 { 457 break; 458 } 459 } 460 } 461 462 int HNont = EAG.FindHNont(Id); 463 int Sig; 464 EAG.Alt HExpr; 465 466 if (!NameNotified && HNont == EAG.firstHNont && ErrorCounter == 0 && lexer.ok) 467 { 468 NameNotified = true; 469 SetBaseName; 470 info!"Analysing %s"(EAG.BaseName); 471 } 472 EAG.HNont[HNont].IsToken = EAG.HNont[HNont].IsToken || IsToken; 473 474 EAG.ParamsDesc Actual; 475 EAG.ParamsDesc Formal; 476 477 Params(Actual, Formal); 478 if (Actual.Params != EAG.empty) 479 Error(Actual.Pos, "actual params not allowed here"); 480 if (Formal.Params != EAG.empty && EAG.SigOK(HNont)) 481 { 482 Sig = EAG.HNont[HNont].Sig; 483 EAG.HNont[HNont].Sig = EAG.empty; 484 } 485 486 Position AltPos; 487 488 if (lexer.front == ':') 489 { 490 AltPos = lexer.position; 491 lexer.popFront; 492 } 493 else 494 { 495 Error(lexer.position, "':' expected"); 496 } 497 HyperExpr(HNont, Id, '(', HExpr, AltPos); 498 if (Formal.Params != EAG.empty) 499 Distribute(HNont, HExpr, Sig, Formal); 500 EAG.NewGrp(HNont, HExpr); 501 if (lexer.front == '.') 502 lexer.popFront; 503 else 504 Error(lexer.position, "'.' expected"); 505 } 506 507 do 508 { 509 int Id; 510 bool IsToken = false; 511 512 if (lexer.front == Token.name) 513 { 514 Id = lexer.value.to!int; 515 lexer.popFront; 516 } 517 else 518 { 519 Error(lexer.position, "identifier of rule expected"); 520 } 521 if (lexer.front == Token.number) 522 { 523 Error(lexer.position, "number is not allowed here"); 524 lexer.popFront; 525 } 526 if (lexer.front == '*') 527 { 528 IsToken = true; 529 lexer.popFront; 530 } 531 if (lexer.front == '=') 532 MetaRule(Id, IsToken); 533 else 534 HyperRule(Id, IsToken); 535 if (lexer.front != Token.name && lexer.front != Token.end) 536 { 537 Error(lexer.position, "not allowed symbol"); 538 do 539 lexer.popFront; 540 while (lexer.front != '.' && lexer.front != Token.end); 541 if (lexer.front != Token.end) 542 lexer.popFront; 543 Error(lexer.position, " restart point"); 544 } 545 } 546 while (lexer.front != Token.end); 547 ErrorCounter += lexer.ok ? 0 : 1; 548 } 549 550 void CheckSemantics() 551 { 552 void Shrink(int Sym) 553 { 554 if (EAG.HNont[Sym].Id >= 0 && cast(EAG.Grp) EAG.HNont[Sym].Def) 555 { 556 EAG.Alt A = (cast(EAG.Grp) EAG.HNont[Sym].Def).Sub; 557 558 if (A.Formal.Params == EAG.empty && A.Next is null && A.Sub !is null && cast(EAG.Nont) A.Sub) 559 { 560 EAG.Nont F = cast(EAG.Nont) A.Sub; 561 562 if (EAG.HNont[F.Sym].anonymous && F.Actual.Params == EAG.empty && F.Next is null) 563 { 564 EAG.HNont[Sym].Def = EAG.HNont[F.Sym].Def; 565 EAG.HNont[F.Sym].Def = null; 566 EAG.HNont[Sym].Sig = EAG.HNont[F.Sym].Sig; 567 A = EAG.HNont[Sym].Def.Sub; 568 do 569 { 570 A.Up = Sym; 571 A = A.Next; 572 } 573 while (A !is null); 574 } 575 } 576 } 577 } 578 579 void Traverse(int Sym) 580 { 581 void CheckParamList(int Dom, EAG.ParamsDesc Par, bool Lhs) 582 { 583 import std.math : abs; 584 585 int P = Par.Params; 586 587 while (EAG.DomBuf[Dom] != nil && EAG.ParamBuf[P].Affixform != nil) 588 { 589 EAG.ParamBuf[P].isDef = Lhs && EAG.DomBuf[Dom] < 0 || !Lhs && EAG.DomBuf[Dom] > 0; 590 Earley.Parse(abs(EAG.DomBuf[Dom]), EAG.ParamBuf[P].Affixform, 591 EAG.ParamBuf[P].Affixform, EAG.ParamBuf[P].isDef); 592 if (EAG.ParamBuf[P].Affixform == EAG.nil) 593 ++ErrorCounter; 594 ++Dom; 595 ++P; 596 } 597 if (EAG.DomBuf[Dom] != EAG.ParamBuf[P].Affixform) 598 { 599 Error(Par.Pos, "number of affixforms differs from signature"); 600 } 601 } 602 603 void CheckActual(EAG.Nont F) 604 { 605 if (EAG.WellMatched(EAG.HNont[F.Sym].Sig, EAG.empty) 606 && F.Actual.Params != EAG.empty 607 && F.Next !is null 608 && cast(EAG.Nont) F.Next 609 && (cast(EAG.Nont) F.Next).Actual.Params == EAG.empty 610 && EAG.HNont[(cast(EAG.Nont) F.Next).Sym].anonymous) 611 { 612 (cast(EAG.Nont)F.Next).Actual = F.Actual; 613 F.Actual.Params = EAG.empty; 614 } 615 } 616 617 void CheckRep(EAG.Alt A) 618 { 619 if (A.Last !is null) 620 if (auto F = cast(EAG.Nont) A.Last) 621 { 622 if (EAG.WellMatched(EAG.HNont[F.Sym].Sig, EAG.empty) 623 && F.Actual.Params != EAG.empty 624 && A.Actual.Params == EAG.empty) 625 { 626 A.Actual = F.Actual; 627 F.Actual.Params = EAG.empty; 628 } 629 } 630 } 631 632 EAG.Rule Node = EAG.HNont[Sym].Def; 633 const Sig = EAG.HNont[Sym].Sig; 634 635 if (Node !is null) 636 { 637 if (auto rep = cast(EAG.Rep) Node) 638 { 639 EAG.Scope = EAG.NextVar; 640 rep.Scope.Beg = EAG.NextVar; 641 CheckParamList(Sig, rep.Formal, true); 642 rep.Scope.End = EAG.NextVar; 643 } 644 else if (auto opt = cast(EAG.Opt) Node) 645 { 646 EAG.Scope = EAG.NextVar; 647 opt.Scope.Beg = EAG.NextVar; 648 CheckParamList(Sig, opt.Formal, true); 649 opt.Scope.End = EAG.NextVar; 650 } 651 652 EAG.Alt A = Node.Sub; 653 654 do 655 { 656 EAG.Scope = EAG.NextVar; 657 A.Scope.Beg = EAG.NextVar; 658 CheckParamList(Sig, A.Formal, true); 659 if (cast(EAG.Rep) Node) 660 { 661 CheckRep(A); 662 CheckParamList(Sig, A.Actual, false); 663 } 664 665 EAG.Factor F = A.Sub; 666 667 while (F !is null) 668 { 669 if (auto nont = cast(EAG.Nont) F) 670 { 671 CheckActual(nont); 672 CheckParamList(EAG.HNont[nont.Sym].Sig, nont.Actual, false); 673 } 674 F = F.Next; 675 } 676 A.Scope.End = EAG.NextVar; 677 A = A.Next; 678 } 679 while (A !is null); 680 } 681 } 682 683 EAG.All = BitArray(); 684 EAG.All.length = EAG.NextHNont + 1; 685 if (EAG.firstHNont == EAG.NextHNont) 686 { 687 ++ErrorCounter; 688 error!"EAG needs at least one hyper-rule"; 689 } 690 for (int Sym = EAG.firstHNont; Sym < EAG.NextHNont; ++Sym) 691 { 692 if (EAG.HNont[Sym].Def is null) 693 { 694 if (EAG.HNont[Sym].Id >= 0) 695 { 696 ++ErrorCounter; 697 error!"hyper-nonterminal %s undefined"(EAG.symbolTable.symbol(EAG.HNont[Sym].Id)); 698 } 699 } 700 else 701 { 702 EAG.All[Sym] = true; 703 Shrink(Sym); 704 } 705 } 706 for (int Sym = EAG.firstMNont; Sym < EAG.NextMNont; ++Sym) 707 { 708 if (EAG.MNont[Sym].MRule == nil) 709 { 710 ++ErrorCounter; 711 error!"meta-nonterminal %s undefined"(EAG.symbolTable.symbol(EAG.MNont[Sym].Id)); 712 } 713 } 714 if (ErrorCounter == 0) 715 { 716 for (int Sym = EAG.firstHNont; Sym < EAG.NextHNont; ++Sym) 717 Traverse(Sym); 718 for (int n = EAG.firstVar; n < EAG.NextVar; ++n) 719 { 720 if (EAG.Var[n].Num < 0 && EAG.Var[n].Neg == EAG.nil) 721 Error(EAG.Var[n].Pos, "! operator not allowed"); 722 if (!EAG.Var[n].Def) 723 { 724 import std.format : format; 725 726 Error(EAG.Var[n].Pos, format!"variable %s never on defining position"(EAG.VarRepr(n))); 727 } 728 } 729 if (EAG.DomBuf[EAG.HNont[EAG.StartSym].Sig] == EAG.nil 730 || EAG.DomBuf[EAG.HNont[EAG.StartSym].Sig] < 0 731 || EAG.DomBuf[EAG.HNont[EAG.StartSym].Sig + 1] != EAG.nil) 732 { 733 ++ErrorCounter; 734 error!"start symbol %s must have exactly one synthesized attribute"( 735 EAG.symbolTable.symbol(EAG.HNont[EAG.StartSym].Id)); 736 } 737 if (EAG.firstMNont == EAG.NextMNont) 738 { 739 ++ErrorCounter; 740 error!"EAG needs at least one meta-rule"; 741 } 742 } 743 } 744 745 void ComputeEAGSets() 746 { 747 struct EdgeRecord 748 { 749 EAG.Alt Dest; 750 int Next; 751 } 752 753 EdgeRecord[] Edge; 754 int NextEdge; 755 int[] Deg; 756 int[] Stack; 757 int Top; 758 BitArray Prod; 759 760 void ComputeReach(int Sym) 761 { 762 EAG.Alt A = EAG.HNont[Sym].Def.Sub; 763 764 EAG.Reach[Sym] = true; 765 do 766 { 767 for (EAG.Factor F = A.Sub; F !is null; F = F.Next) 768 if (auto nont = cast(EAG.Nont) F) 769 if (!EAG.Reach[nont.Sym]) 770 ComputeReach(nont.Sym); 771 A = A.Next; 772 } 773 while (A !is null); 774 } 775 776 void NewEdge(int From, EAG.Alt To) 777 { 778 Edge[NextEdge].Dest = To; 779 Edge[NextEdge].Next = Edge[From].Next; 780 Edge[From].Next = NextEdge; 781 ++NextEdge; 782 } 783 784 void TestDeg(EAG.Alt A) 785 { 786 if (Deg[A.Ind] == 0) 787 { 788 if (!Prod[A.Up]) 789 { 790 Prod[A.Up] = true; 791 Stack[Top] = A.Up; 792 ++Top; 793 } 794 } 795 } 796 797 void Prune() 798 { 799 int E; 800 EAG.Alt A; 801 while (Top > 0) 802 { 803 --Top; 804 E = Edge[Stack[Top]].Next; 805 while (E != nil) 806 { 807 A = Edge[E].Dest; 808 --Deg[A.Ind]; 809 TestDeg(A); 810 E = Edge[E].Next; 811 } 812 } 813 } 814 815 long Warnings = 0; 816 817 EAG.Reach = BitArray(); 818 EAG.Reach.length = EAG.NextHNont + 1; 819 820 ComputeReach(EAG.StartSym); 821 for (int Sym = EAG.firstHNont; Sym < EAG.NextHNont; ++Sym) 822 if (EAG.HNont[Sym].Def !is null && !EAG.Reach[Sym] && EAG.HNont[Sym].Id >= 0) 823 ++Warnings; 824 Deg = new int[EAG.NextHAlt]; 825 Stack = new int[EAG.NextHNont]; 826 Top = 0; 827 Edge = new EdgeRecord[EAG.NextHNont + EAG.NONont + 1]; 828 NextEdge = EAG.NextHNont; 829 for (int Sym = EAG.firstHNont; Sym < EAG.NextHNont; ++Sym) 830 Edge[Sym].Next = nil; 831 EAG.Null = BitArray(); 832 EAG.Null.length = EAG.NextHNont + 1; 833 Prod = BitArray(); 834 Prod.length = EAG.NextHNont + 1; 835 for (int Sym = EAG.firstHNont; Sym < EAG.NextHNont; ++Sym) 836 { 837 if (EAG.HNont[Sym].Def !is null) 838 { 839 if (cast(EAG.Opt) EAG.HNont[Sym].Def || cast(EAG.Rep) EAG.HNont[Sym].Def) 840 { 841 Prod[Sym] = true; 842 Stack[Top] = Sym; 843 ++Top; 844 } 845 846 EAG.Alt A = EAG.HNont[Sym].Def.Sub; 847 848 do 849 { 850 bool TermFound = false; 851 852 Deg[A.Ind] = 0; 853 for (EAG.Factor F = A.Sub; F !is null; F = F.Next) 854 { 855 if (cast(EAG.Term) F) 856 { 857 TermFound = true; 858 } 859 else if (auto nont = cast(EAG.Nont) F) 860 { 861 ++Deg[A.Ind]; 862 NewEdge(nont.Sym, A); 863 } 864 } 865 if (TermFound) 866 Deg[A.Ind] += int.min; 867 else 868 TestDeg(A); 869 A = A.Next; 870 } 871 while (A !is null); 872 } 873 } 874 Prune; 875 EAG.Null = Prod.dup; 876 for (int Sym = EAG.firstHNont; Sym < EAG.NextHNont; ++Sym) 877 { 878 if (EAG.HNont[Sym].Def !is null) 879 { 880 EAG.Alt A = EAG.HNont[Sym].Def.Sub; 881 882 do 883 { 884 if (Deg[A.Ind] < 0) 885 { 886 Deg[A.Ind] -= int.min; 887 TestDeg(A); 888 } 889 A = A.Next; 890 } 891 while (A !is null); 892 } 893 } 894 Prune; 895 EAG.Prod = Prod; 896 Warnings += (EAG.All & ~EAG.Prod).count; 897 if (Warnings > 0) 898 warn!"%s warnings"(Warnings); 899 } 900 901 void Analyse(Input input) 902 { 903 EAG.Init; 904 lexer = Lexer(input, EAG.symbolTable); 905 Earley.Init; 906 ErrorCounter = 0; 907 NameNotified = false; 908 Specification; 909 if (ErrorCounter == 0) 910 { 911 CheckSemantics; 912 Earley.Finit; 913 } 914 if (ErrorCounter == 0) 915 { 916 ComputeEAGSets; 917 } 918 if (ErrorCounter == 0) 919 { 920 EAG.History |= EAG.analysed; 921 info!"%s grammar is valid"(EAG.BaseName); 922 } 923 else 924 { 925 EAG.History &= ~EAG.analysed; 926 if (NameNotified) 927 info!"errors in %s"(EAG.BaseName); 928 else 929 info!"errors"; 930 } 931 } 932 933 void Warnings() 934 in (EAG.Performed(EAG.analysed)) 935 { 936 const Unreach = EAG.All - EAG.Reach; 937 const Unprod = EAG.All - EAG.Prod; 938 const NoWarnings = Unreach.bitsSet.empty && Unprod.bitsSet.empty; 939 940 if (NoWarnings) 941 { 942 info!"Analyser: no warnings on %s's hyper-nonterminals"(EAG.BaseName); 943 return; 944 } 945 warn!"Analyser warnings on %s's hyper-nonterminals:"(EAG.BaseName); 946 for (int Sym = EAG.firstHNont; Sym < EAG.NextHNont; ++Sym) 947 { 948 if (Unreach[Sym] && EAG.HNont[Sym].Id >= 0) 949 warn!"%s unreachable"(EAG.HNontRepr(Sym)); 950 if (Unprod[Sym]) 951 { 952 if (EAG.HNont[Sym].anonymous) 953 warn!"anonymous nonterminal in %s unproductive"(EAG.NamedHNontRepr(Sym)); 954 else 955 warn!"%s unproductive"(EAG.HNontRepr(Sym)); 956 } 957 } 958 }