1 module gamma.parsgen.lalr1.LR1ParserTablesWriter; 2 3 import gamma.grammar.Alternative; 4 import gamma.grammar.Node; 5 import gamma.grammar.Nonterminal; 6 import gamma.grammar.Rule; 7 import gamma.grammar.Symbol; 8 import gamma.grammar.SymbolNode; 9 import gamma.grammar.Terminal; 10 import gamma.parsgen.lalr1.OrderedLR1Tables; 11 import std.algorithm; 12 import std.array; 13 import std.json; 14 import std.stdio; 15 16 /** 17 * Writes an OrderedLR1Tables representation to a given output file. 18 */ 19 public static void write(OrderedLR1Tables parserTables, File output) 20 { 21 JSONValue[string] grammarObject; 22 JSONValue[] nonterminals; 23 24 foreach (nonterminal; parserTables.grammar.nonterminals) 25 nonterminals ~= JSONValue([ 26 "index": JSONValue(nonterminal.index), 27 "repr": JSONValue(nonterminal.toString), 28 ]); 29 grammarObject["nonterminals"] = nonterminals; 30 31 JSONValue[] terminals; 32 33 foreach (terminal; parserTables.grammar.terminals) 34 terminals ~= JSONValue([ 35 "index": JSONValue(terminal.index), 36 "repr": JSONValue(terminal.toString), 37 ]); 38 grammarObject["terminals"] = terminals; 39 40 JSONValue[] rules; 41 size_t altIndex = 0; 42 size_t[Alternative] alt2IndexMap; 43 44 foreach (rule; parserTables.grammar.rules) 45 { 46 JSONValue[string] ruleObject; 47 48 if (rule.alternatives.length == 0) 49 continue; 50 51 ruleObject["lhs"] = (cast(Nonterminal)(cast(Alternative) rule.alternatives[0]).lhs.symbol).index; 52 53 JSONValue[] alternatives; 54 55 foreach (alternative; rule.alternatives) 56 { 57 JSONValue[string] alternativeObject; 58 59 alternativeObject["index"] = altIndex; 60 alt2IndexMap[alternative] = altIndex; 61 ++altIndex; 62 63 JSONValue[] symbols; 64 65 foreach (node; alternative.rhs) 66 { 67 assert(cast(SymbolNode) node); 68 69 auto symbol = (cast(SymbolNode) node).symbol; 70 71 if (cast(Terminal) symbol) 72 symbols ~= JSONValue([ 73 "type": JSONValue("terminal"), 74 "index": JSONValue((cast(Terminal) symbol).index), 75 ]); 76 else if (cast(Nonterminal) symbol) 77 symbols ~= JSONValue([ 78 "type": JSONValue("nonterminal"), 79 "index": JSONValue((cast(Nonterminal) symbol).index) 80 ]); 81 } 82 alternativeObject["rhs"] = symbols; 83 alternatives ~= JSONValue(alternativeObject); 84 } 85 ruleObject["alternatives"] = alternatives; 86 rules ~= JSONValue(ruleObject); 87 } 88 grammarObject["rules"] = rules; 89 grammarObject["startSymbol"] = ["index": parserTables.grammar.startSymbol.index]; 90 91 JSONValue[] states; 92 93 foreach (state; 0 .. parserTables.stateCount) 94 { 95 JSONValue[string] stateObject; 96 97 stateObject["index"] = state; 98 99 JSONValue[] actions; 100 101 foreach (action; parserTables.getSortedParserActionRow(state)) 102 { 103 JSONValue[string] actionObject; 104 105 actionObject["on"] = action.lookahead.index; 106 if (cast(OrderedLR1Tables.Shift) action) 107 { 108 actionObject["type"] = "shift"; 109 actionObject["to"] = (cast(OrderedLR1Tables.Shift) action).state; 110 } 111 else if (cast(OrderedLR1Tables.Reduce) action) 112 { 113 OrderedLR1Tables.Reduce ra = cast(OrderedLR1Tables.Reduce) action; 114 115 actionObject["type"] = "reduce"; 116 actionObject["ruleAlt"] = alt2IndexMap[ra.alternative]; 117 } 118 else if (cast(OrderedLR1Tables.Halt) action) 119 { 120 actionObject["type"] = "halt"; 121 } 122 if (action.isContinuationAction) 123 actionObject["continues"] = true; 124 actions ~= JSONValue(actionObject); 125 } 126 stateObject["actions"] = actions; 127 128 JSONValue[] transitions; 129 130 foreach (g; parserTables.getSortedGotoRow(state)) 131 transitions ~= JSONValue([ 132 "on": JSONValue(g.lhs.index), 133 "to": JSONValue(g.state), 134 ]); 135 stateObject["transitions"] = transitions; 136 states ~= JSONValue(stateObject); 137 } 138 139 JSONValue value = [ 140 "grammar": JSONValue(grammarObject), 141 "states": JSONValue(states), 142 ]; 143 144 output.writeln(value.toPrettyString); 145 }