PageRenderTime 29ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/sablecc-3.2/src/org/sablecc/sablecc/Grammar.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 687 lines | 512 code | 119 blank | 56 comment | 68 complexity | e5cd317fafdc5f9c6ae2f571b77065bf MD5 | raw file
  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2. * This file is part of SableCC. *
  3. * See the file "LICENSE" for copyright information and the *
  4. * terms and conditions for copying, distribution and *
  5. * modification of SableCC. *
  6. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  7. package org.sablecc.sablecc;
  8. import java.util.Vector;
  9. import java.util.*;
  10. public final class Grammar
  11. {
  12. private static TreeMap fastLr0Closure = new TreeMap();
  13. private static TreeMap fastLr1Closure = new TreeMap();
  14. static int startSymbol;
  15. static int startProduction;
  16. static int eof ;
  17. static int dummy ;
  18. static int[][][] action_;
  19. static int[][] goto_;
  20. static
  21. {
  22. reinit();
  23. }
  24. private Grammar()
  25. {}
  26. public static int addTerminal(String name, String errorName)
  27. {
  28. return new Symbol(name, errorName, true).index;
  29. }
  30. public static int addNonterminal(String name)
  31. {
  32. return new Symbol(name, null, false).index;
  33. }
  34. public static int addProduction(String nonterminal, String name)
  35. {
  36. Symbol symbol = Symbol.symbol(nonterminal);
  37. if(symbol.terminal)
  38. {
  39. throw new IllegalArgumentException("The symbol " + nonterminal +
  40. " is a terminal.");
  41. }
  42. return new Production(symbol.index, name).index;
  43. }
  44. public static void addSymbolToProduction(String symbol, int production)
  45. {
  46. Production.production(production).addSymbol(Symbol.symbol(symbol));
  47. }
  48. public static void reinit()
  49. {
  50. fastLr0Closure = new TreeMap();
  51. fastLr1Closure = new TreeMap();
  52. startSymbol = 0;
  53. startProduction = -1;
  54. eof = -1;
  55. dummy = -1;
  56. action_ = null;
  57. goto_ = null;
  58. }
  59. public static void computeLALR() throws ConflictException
  60. {
  61. // Add EOF to terminals
  62. eof = addTerminal("EOF", "EOF");
  63. // Add dummy to terminals
  64. dummy = addTerminal("#", null);
  65. // Add the production S'->S
  66. startSymbol = addNonterminal("Start");
  67. Production start = new Production(startSymbol, "Start");
  68. start.addSymbol(Symbol.symbol(0, false));
  69. startProduction = start.index;
  70. computeFirst();
  71. LR0ItemSet set
  72. = new LR0ItemSet();
  73. set.set(new LR0Item(startProduction, 0));
  74. LR1Collection collection = new LR1Collection(set
  75. );
  76. LR0ItemSet[] sets = collection.collection.sets();
  77. Symbol[] terminals = Symbol.terminals();
  78. Symbol[] nonterminals = Symbol.nonterminals();
  79. action_ = new int[sets.length][terminals.length - 1][];
  80. goto_ = new int[sets.length][nonterminals.length - 1];
  81. Set listOfConflictualProds = new HashSet();
  82. StringBuffer conflictMessage = new StringBuffer();
  83. for(int i = 0; i < sets.length; i++)
  84. {
  85. System.out.print(".");
  86. LR1ItemSet state = new LR1ItemSet();
  87. {
  88. LR0Item[] items = sets[i].items();
  89. for(int j = 0; j < items.length; j++)
  90. {
  91. Symbol[] lookaheads = ((SymbolSet) collection.lookaheads[i].
  92. get
  93. (items[j])).getSymbols();
  94. for(int k = 0; k < lookaheads.length; k++)
  95. {
  96. state.set(new LR1Item(items[j], lookaheads[k].index));
  97. }
  98. }
  99. }
  100. state = CLOSURE(state);
  101. LR1Item[] items = state.items();
  102. for(int j = 0; j < terminals.length; j++)
  103. {
  104. Integer destination = collection.collection.GOTO(i, terminals[j]);
  105. if(destination != null)
  106. {
  107. //Shift action is taken
  108. action_[i][j] = new int[] {0, destination.intValue()};
  109. }
  110. for(int k = 0; k < items.length; k++)
  111. {
  112. Production production = Production.
  113. production(items[k].lr0Item.production);
  114. //A conflict occurs only if one is on the end of an alternative
  115. try
  116. {
  117. production.rightside(items[k].lr0Item.position);
  118. }
  119. catch(Exception e)
  120. {
  121. if(production.leftside != startSymbol)
  122. {
  123. if(items[k].terminal == terminals[j].index)
  124. {
  125. int[] action = action_[i][j];
  126. if(action != null)
  127. {
  128. /* The current alternative is conflictual (reduce in a XXX/reduce conflict) */
  129. listOfConflictualProds.add(Symbol.symbol(production.leftside, false).toString());
  130. /* */
  131. switch(action[0])
  132. {
  133. case 0:
  134. conflictMessage.append(
  135. "\n\nshift/reduce conflict in state [stack:" +
  136. collection.collection.names.elementAt(i) + "*] on " +
  137. terminals[j] + " in " + state.toString(terminals[j]));
  138. /* nothing else to do */
  139. break;
  140. case 1:
  141. conflictMessage.append(
  142. "\n\nreduce/reduce conflict in state [stack:" +
  143. collection.collection.names.elementAt(i) + "*] on " +
  144. terminals[j] + " in " + state.toString(terminals[j]));
  145. listOfConflictualProds.add(Symbol.symbol(Production.production(action[1]).leftside, false).toString());
  146. break;
  147. case 2:
  148. conflictMessage.append(
  149. "\n\nreduce/accept conflict in state [stack:" +
  150. collection.collection.names.elementAt(i) + "*] on " +
  151. terminals[j] + " in " + state.toString(terminals[j]));
  152. listOfConflictualProds.add(Symbol.symbol(Production.production(action[1]).leftside, false).toString());
  153. break;
  154. }
  155. }
  156. else
  157. {
  158. //it's a reduction action
  159. action_[i][j] = new int[] {1,
  160. items[k].lr0Item.production};
  161. }
  162. }
  163. }
  164. else
  165. {
  166. if(terminals[j].index == eof)
  167. {
  168. int[] action = action_[i][j];
  169. if(action != null)
  170. {
  171. /* The current alternative is conflictual (accept in a XXX/accept conflict) */
  172. listOfConflictualProds.add(Symbol.symbol(production.leftside, false).toString());
  173. /* */
  174. switch(action[0])
  175. {
  176. case 0:
  177. conflictMessage.append(
  178. "shift/accept conflict in state [stack:" +
  179. collection.collection.names.elementAt(i) + "*] on " +
  180. terminals[j] + " in " + state);
  181. /* nothing else to do */
  182. break;
  183. case 1:
  184. conflictMessage.append(
  185. "reduce/accept conflict in state [stack:" +
  186. collection.collection.names.elementAt(i) + "*] on " +
  187. terminals[j] + " in " + state);
  188. listOfConflictualProds.add(Symbol.symbol(Production.production(action[1]).leftside, false).toString());
  189. break;
  190. }
  191. }
  192. else
  193. {
  194. //accept action is taken
  195. action_[i][j] = new int[] {2};
  196. }
  197. }
  198. }
  199. }//End of catch
  200. }
  201. }
  202. if (listOfConflictualProds.size() > 0)
  203. {
  204. throw new ConflictException(listOfConflictualProds, conflictMessage.toString());
  205. }
  206. for(int j = 0; j < nonterminals.length - 1; j++)
  207. {
  208. Integer destination = collection.collection.GOTO(i, nonterminals[j]);
  209. if(destination != null)
  210. {
  211. goto_[i][j] = destination.intValue();
  212. }
  213. else
  214. {
  215. goto_[i][j] = -1;
  216. }
  217. }
  218. }
  219. System.out.println();
  220. }
  221. static SymbolSet[] FIRST_Terminal;
  222. static SymbolSet[] FIRST_Nonterminal;
  223. static void computeFirst()
  224. {
  225. // Get terminals, nonterminals and productions
  226. Symbol[] terminals = Symbol.terminals();
  227. Symbol[] nonterminals = Symbol.nonterminals();
  228. Production[] productions = Production.productions();
  229. // Initialize FIRST(X) to {}
  230. FIRST_Terminal = new SymbolSet[terminals.length];
  231. for(int i = 0; i < terminals.length; i++)
  232. {
  233. FIRST_Terminal[i] = new SymbolSet();
  234. }
  235. FIRST_Nonterminal = new SymbolSet[nonterminals.length];
  236. for(int i = 0; i < nonterminals.length; i++)
  237. {
  238. FIRST_Nonterminal[i] = new SymbolSet();
  239. }
  240. // if X is terminal, then FIRST(X) is {X}
  241. for(int i = 0; i < terminals.length; i++)
  242. {
  243. FIRST_Terminal[i].setTerminal(terminals[i].index);
  244. }
  245. // if X -> empty is a production, then add empty to FIRST(X)
  246. for(int i = 0; i < productions.length; i++)
  247. {
  248. if(productions[i].rightside().length == 0)
  249. {
  250. FIRST_Nonterminal[productions[i].leftside].
  251. setEmpty();
  252. }
  253. }
  254. // if X is nonterminal and X -> Y(1) Y(2) ... Y(k) is a production,
  255. // then place t in FIRST(X) if for some i, t is in FIRST(Y(i)), and
  256. // empty is in all of FIRST(Y(1)), ... , FIRST(Y(i-1)).
  257. boolean changed;
  258. do
  259. {
  260. changed = false;
  261. for(int i = 0; i < productions.length; i++)
  262. {
  263. SymbolSet before =
  264. (SymbolSet) FIRST_Nonterminal[productions[i].leftside].clone();
  265. FIRST_Nonterminal[productions[i].leftside].
  266. or(FIRST(productions[i].rightside()));
  267. if(!before.equals(FIRST_Nonterminal[productions[i].leftside]))
  268. {
  269. changed = true;
  270. }
  271. }
  272. }
  273. while(changed);
  274. }
  275. static SymbolSet FIRST(Symbol[] symbols)
  276. {
  277. return FIRST(symbols, 0, symbols.length);
  278. }
  279. static SymbolSet FIRST(Symbol[] symbols, int begin)
  280. {
  281. return FIRST(symbols, begin, symbols.length);
  282. }
  283. static SymbolSet FIRST(Symbol[] symbols, int begin, int end)
  284. {
  285. SymbolSet result = new SymbolSet();
  286. boolean previousContainsEmpty = true;
  287. for(int i = begin; i < end; i++)
  288. {
  289. if(!previousContainsEmpty)
  290. {
  291. break;
  292. }
  293. if(symbols[i].terminal)
  294. {
  295. result.or(FIRST_Terminal[symbols[i].index]);
  296. previousContainsEmpty = FIRST_Terminal[symbols[i].index].getEmpty();
  297. }
  298. else
  299. {
  300. result.or(FIRST_Nonterminal[symbols[i].index]);
  301. previousContainsEmpty = FIRST_Nonterminal[symbols[i].index].getEmpty();
  302. }
  303. }
  304. if(previousContainsEmpty)
  305. {
  306. result.setEmpty();
  307. }
  308. else
  309. {
  310. result.clearEmpty();
  311. }
  312. return result;
  313. }
  314. static SymbolSet[] FOLLOW;
  315. static void computeFollow()
  316. {
  317. // Get terminals, nonterminals and productions
  318. Symbol[] terminals = Symbol.terminals();
  319. Symbol[] nonterminals = Symbol.nonterminals();
  320. Production[] productions = Production.productions();
  321. // Initialize FOLLOW(A) to {}
  322. FOLLOW = new SymbolSet[nonterminals.length];
  323. for(int i = 0; i < nonterminals.length; i++)
  324. {
  325. FOLLOW[i] = new SymbolSet();
  326. }
  327. // Place eof in FOLLOW(S) where S is the start symbol.
  328. FOLLOW[startSymbol].setTerminal(eof);
  329. // If there is a production A->xBy, then everything in FIRST(y) except
  330. // for empty is placed in FOLLOW(B).
  331. for(int i = 0; i < productions.length; i++)
  332. {
  333. Symbol[] rightside = productions[i].rightside();
  334. for(int j = 0; j < rightside.length; j++)
  335. {
  336. if(!rightside[j].terminal)
  337. {
  338. SymbolSet set
  339. = FIRST(rightside, j + 1);
  340. set.clearEmpty();
  341. FOLLOW[rightside[j].index].or(set
  342. );
  343. }
  344. }
  345. }
  346. // If there is a production A->xB, or a production A->xBy where FIRST(y)
  347. // contains empty, then everything in FOLLOW(A) is in FOLLOW(B).
  348. boolean changed;
  349. do
  350. {
  351. changed = false;
  352. for(int i = 0; i < productions.length; i++)
  353. {
  354. Symbol[] rightside = productions[i].rightside();
  355. for(int j = 0; j < rightside.length; j++)
  356. {
  357. if(!rightside[j].terminal)
  358. {
  359. SymbolSet before =
  360. (SymbolSet) FOLLOW[rightside[j].index].clone();
  361. if(FIRST(rightside, j + 1).getEmpty())
  362. {
  363. FOLLOW[rightside[j].index].
  364. or(FOLLOW[productions[i].leftside]);
  365. }
  366. if(!before.equals(FOLLOW[rightside[j].index]))
  367. {
  368. changed = true;
  369. }
  370. }
  371. }
  372. }
  373. }
  374. while(changed);
  375. }
  376. static SymbolSet FOLLOW(int nonterminal)
  377. {
  378. return FOLLOW[nonterminal];
  379. }
  380. static LR0ItemSet CLOSURE(LR0Item item)
  381. {
  382. LR0ItemSet result = (LR0ItemSet) fastLr0Closure.get(item);
  383. if(result != null)
  384. {
  385. return result;
  386. }
  387. result = new LR0ItemSet();
  388. result.set(item);
  389. LR0ItemSet newItems = result;
  390. boolean modified;
  391. do
  392. {
  393. modified = false;
  394. LR0Item[] items = newItems.items();
  395. newItems = new LR0ItemSet();
  396. for(int i = 0; i < items.length; i++)
  397. {
  398. Production production = Production.production(items[i].production);
  399. Symbol[] rightside = production.rightside();
  400. if(items[i].position < rightside.length)
  401. {
  402. Symbol symbol = rightside[items[i].position];
  403. if(!symbol.terminal)
  404. {
  405. Production[] alternatives =
  406. Production.alternatives(symbol.index);
  407. for(int j = 0; j < alternatives.length; j++)
  408. {
  409. LR0Item newItem = new LR0Item(alternatives[j].index, 0);
  410. if(!result.get(newItem))
  411. {
  412. result.set(newItem);
  413. newItems.set(newItem);
  414. modified = true;
  415. }
  416. }
  417. }
  418. }
  419. }
  420. }
  421. while(modified);
  422. fastLr0Closure.put(item, result);
  423. return result;
  424. }
  425. // private static final SplayTreeMap fastLr0SetClosure = new SplayTreeMap();
  426. static LR0ItemSet CLOSURE(LR0ItemSet set
  427. )
  428. {
  429. LR0ItemSet result =
  430. /*
  431. (LR0ItemSet) fastLr0SetClosure.get(set);
  432. if(result != null)
  433. {
  434. return result;
  435. }
  436. result =*/
  437. new LR0ItemSet();
  438. LR0Item[] setItems = set.items();
  439. for(int i = 0; i < setItems.length; i++)
  440. {
  441. LR0Item[] items = CLOSURE(setItems[i]).items();
  442. for(int j = 0; j < items.length; j++)
  443. {
  444. result.set(items[j]);
  445. }
  446. }
  447. // fastLr0SetClosure.put(set, result);
  448. return result;
  449. }
  450. static LR1ItemSet CLOSURE(LR1Item item)
  451. {
  452. LR1ItemSet result = (LR1ItemSet) fastLr1Closure.get(item);
  453. if(result != null)
  454. {
  455. return result;
  456. }
  457. result = new LR1ItemSet();
  458. result.set(item);
  459. LR1ItemSet newItems = result;
  460. boolean modified;
  461. do
  462. {
  463. modified = false;
  464. LR1Item[] items = newItems.items();
  465. newItems = new LR1ItemSet();
  466. for(int i = 0; i < items.length; i++)
  467. {
  468. Production production = Production.production(items[i].lr0Item.production);
  469. Symbol[] rightside = production.rightside();
  470. if(items[i].lr0Item.position < rightside.length)
  471. {
  472. Symbol symbol = rightside[items[i].lr0Item.position];
  473. if(!symbol.terminal)
  474. {
  475. Vector tailVector = new Vector(0);
  476. for(int k = items[i].lr0Item.position + 1; k < rightside.length; k++)
  477. {
  478. tailVector.addElement(rightside[k]);
  479. }
  480. tailVector.addElement(Symbol.symbol(items[i].terminal, true));
  481. Symbol[] tail = new Symbol[tailVector.size()];
  482. tailVector.copyInto(tail);
  483. Symbol[] symbols = FIRST(tail).getSymbols();
  484. Production[] alternatives =
  485. Production.alternatives(symbol.index);
  486. for(int k = 0; k < symbols.length; k++)
  487. {
  488. if(symbols[k].terminal)
  489. {
  490. for(int j = 0; j < alternatives.length; j++)
  491. {
  492. LR1Item newItem = new LR1Item(
  493. new LR0Item(alternatives[j].index, 0),
  494. symbols[k].index);
  495. if(!result.get(newItem))
  496. {
  497. result.set(newItem);
  498. newItems.set(newItem);
  499. modified = true;
  500. }
  501. }
  502. }
  503. }
  504. }
  505. }
  506. }
  507. }
  508. while(modified);
  509. fastLr1Closure.put(item, result);
  510. return result;
  511. }
  512. // private static final SplayTreeMap fastLr1SetClosure = new SplayTreeMap();
  513. static LR1ItemSet CLOSURE(LR1ItemSet set
  514. )
  515. {
  516. LR1ItemSet result =
  517. /*
  518. (LR1ItemSet) fastLr1SetClosure.get(set);
  519. if(result != null)
  520. {
  521. return result;
  522. }
  523. result =*/
  524. new LR1ItemSet();
  525. LR1Item[] setItems = set.items();
  526. for(int i = 0; i < setItems.length; i++)
  527. {
  528. LR1Item[] items = CLOSURE(new LR1Item(setItems[i].lr0Item, dummy)).items();
  529. for(int j = 0; j < items.length; j++)
  530. {
  531. result.set(new LR1Item(items[j].lr0Item,
  532. items[j].terminal == dummy ? setItems[i].terminal : items[j].terminal));
  533. }
  534. }
  535. // fastLr1SetClosure.put(set, result);
  536. return result;
  537. }
  538. static LR0ItemSet GOTO(LR0ItemSet set
  539. , Symbol symbol)
  540. {
  541. LR0ItemSet initialset = set
  542. ;
  543. set
  544. = CLOSURE(set
  545. );
  546. LR0ItemSet result = new LR0ItemSet();
  547. // return all items A->xS.y such that A->x.Sy is in set. (S=symbol)
  548. LR0Item[] items = set.items();
  549. for(int i = 0; i < items.length; i++)
  550. {
  551. Production production = Production.production(items[i].production);
  552. Symbol[] rightside = production.rightside();
  553. if(items[i].position < rightside.length)
  554. {
  555. if(symbol.equals(rightside[items[i].position]))
  556. {
  557. result.set(new LR0Item(items[i].production,
  558. items[i].position + 1));
  559. }
  560. }
  561. }
  562. return result;
  563. }
  564. }