1 module tcenal.dsl.generate_parsers; 2 3 import tcenal.parser_combinator.parse_tree_node : ParseTreeNode; 4 import tcenal.parser_combinator.memo : Memo; 5 import tcenal.dsl.lexer : lex; 6 import tcenal.dsl.parsers : rules; 7 8 9 private string generate(ParseTreeNode node, string ruleName = "") 10 { 11 string generated; 12 13 switch (node.ruleName) 14 { 15 case "rules": 16 foreach (i, child; node.children[0].children) 17 { 18 if (i) 19 { 20 generated ~= "\n\n\n"; 21 } 22 23 generated ~= child.generate(); 24 } 25 break; 26 27 case "rule": 28 ruleName = node.children[0].children[0].token.value; 29 generated = "tcenal.parser_combinator.parsing_result.ParsingResult " ~ ruleName ~ "(alias ruleSelector)(tcenal.parser_combinator.token.Token[] input, size_t position, ref tcenal.parser_combinator.memo.Memo memo)\n"; 30 generated ~= "{\nreturn tcenal.parser_combinator.combinators.applyRule!(\n"; 31 generated ~= node.children[0].children[1].generate(ruleName); 32 generated ~= "\n)(input, position, memo);\n}"; 33 break; 34 35 case "choiceExpr": 36 if (node.children[0].children.length == 1) 37 { 38 generated = node.children[0].children[0].generate(ruleName); 39 } 40 else 41 { 42 generated = "tcenal.parser_combinator.combinators.choice!(\n" ~ node.children[0].generate(ruleName) ~ "\n)"; 43 } 44 break; 45 46 case "sequenceExpr": 47 if (node.children[0].children.length == 1) 48 { 49 generated = node.children[0].children[0].generate(ruleName); 50 } 51 else 52 { 53 generated = "tcenal.parser_combinator.combinators.sequence!(\n" ~ node.children[0].generate(ruleName) ~ "\n)"; 54 } 55 break; 56 57 case "prefixExpr": 58 if (node.children[0].ruleName == "#sequence" && node.children[0].children[0].token.type == "") 59 { 60 switch (node.children[0].children[0].token.value) 61 { 62 case "&": 63 generated = "tcenal.parser_combinator.combinators.andPred!(\n" ~ node.children[0].children[1].generate(ruleName) ~ "\n)"; 64 break; 65 66 case "!": 67 generated = "tcenal.parser_combinator.combinators.notPred!(\n" ~ node.children[0].children[1].generate(ruleName) ~ "\n)"; 68 break; 69 70 default: 71 assert (0); 72 } 73 } 74 else 75 { 76 generated = node.children[0].generate(ruleName); 77 } 78 break; 79 80 case "postfixExpr": 81 if (node.children[0].ruleName == "#sequence" && node.children[0].children[1].token.type == "") 82 { 83 switch (node.children[0].children[1].token.value) 84 { 85 case "*": 86 if (node.children[0].children[2].children.length == 1) 87 { 88 generated = "tcenal.parser_combinator.combinators.zeroOrMoreWithSeparator!(\n" ~ node.children[0].children[0].generate(ruleName) ~ ",\n" ~ node.children[0].children[2].children[0].generate(ruleName) ~ "\n)"; 89 } 90 else 91 { 92 generated = "tcenal.parser_combinator.combinators.zeroOrMore!(\n" ~ node.children[0].children[0].generate(ruleName) ~ "\n)"; 93 } 94 95 break; 96 97 case "+": 98 if (node.children[0].children[2].children.length == 1) 99 { 100 generated = "tcenal.parser_combinator.combinators.oneOrMoreWithSeparator!(\n" ~ node.children[0].children[0].generate(ruleName) ~ ",\n)" ~ node.children[0].children[2].children[0].generate(ruleName) ~ "\n)"; 101 } 102 else 103 { 104 generated = "tcenal.parser_combinator.combinators.oneOrMore!(\n" ~ node.children[0].children[0].generate(ruleName) ~ "\n)"; 105 } 106 break; 107 108 case "?": 109 generated = "tcenal.parser_combinator.combinators.option!(\n" ~ node.children[0].children[0].generate(ruleName) ~ "\n)"; 110 break; 111 112 default: 113 assert (0); 114 } 115 } 116 else 117 { 118 generated = node.children[0].generate(ruleName); 119 } 120 break; 121 122 case "primaryExpr": 123 generated = node.children[0].generate(ruleName); 124 break; 125 126 case "ruleName": 127 if (node.children[0].token.value == "super") 128 { 129 generated = "ruleSelector!(\"" ~ ruleName ~ "\", true)"; 130 } 131 else 132 { 133 generated = "ruleSelector!\"" ~ node.children[0].token.value ~ "\""; 134 } 135 break; 136 137 case "tokenValue": 138 generated = "tcenal.parser_combinator.combinators.parseTokenWithValue!\"" ~ node.children[0].token.value ~ "\""; 139 break; 140 141 case "tokenType": 142 generated = "tcenal.parser_combinator.combinators.parseTokenWithType!\"" ~ node.children[0].token.value ~ "\""; 143 break; 144 145 case "#repeat": 146 foreach (i, child; node.children) 147 { 148 if (i) 149 { 150 generated ~= ",\n"; 151 } 152 153 generated ~= child.generate(ruleName); 154 } 155 break; 156 157 default: 158 assert(false, node.toString()); 159 } 160 161 return generated; 162 } 163 164 165 string generateParsers(string src) 166 { 167 enum preamble = q{ 168 static import tcenal.parser_combinator.token; 169 static import tcenal.parser_combinator.memo; 170 static import tcenal.parser_combinator.parsing_result; 171 static import tcenal.parser_combinator.combinators; 172 }; 173 174 Memo memo; 175 176 return preamble ~ src.lex().rules(0, memo).node.generate(); 177 }