1 module ctpg.dsl.typed; 2 3 import std.algorithm : count; 4 import std.conv : to; 5 6 import ctpg : parse; 7 import ctpg.parser_kind : ParserKind; 8 9 import ctpg.dsl.typed.node : Node; 10 import ctpg.dsl.typed.parsers : defs; 11 12 import ctpg.dsl.typed.visitors : applySkipLiteral, applyMemoizeSkip, applyMemoizeLiteral, applyMemoizeNonterminal, expandSkip, removeMemoizeDuplicates, removeSkipWithDuplicates, generate; 13 14 import selflinoin : makeCompilationErrorMessage; 15 16 17 string generateParsers(string src, size_t line = __LINE__ , string file = __FILE__) 18 { 19 /+ 20 パスの順番どうしよう? 21 生成オプションの中に「スキップをメモ化」ってのがあるから、生成オプション適応を先にやると、どれがスキップだかわからなくなって困る。 22 SKIPを置き換えるんじゃなくて残して、SKIPの下にスキップパーサを入れるみたいな構造なら、どれがスキップパーサか分かる。 23 それなら、別にapplyMemoizeSkipを先にやる必要はなくなる 24 うーん、単純にスキップをメモ化だけを単独で最初にやっちゃうって方法がいいかな 25 てか、それぞれの生成オプションごとに関数を用意してやるのがいいのかも知れない 26 てか、生成オプションの渡し方とかどうするんですかね・・・ 27 うーん、オプションもDSLの中に書いてもらおうかなぁ・・・ 28 結局、生成オプションごとに関数を作ることにした。オプションはDSL内に書いてもらう 29 古いctpgの実装だと、リテラルはskip!(memoize!(literal))ってなってるから、 30 適応の順番はskip->memoizeになる 31 +/ 32 /+ 33 applySetSkipする前と後のSKIPは別にするべきなのかどうかみたいな話 34 ・別にするべき 35 ・前と後で意味合いが変わる。同じだと紛らわしい 36 ・childrenにスキップパーサを追加する必要がある 37 ・同じにするべき 38 ・前と後で、同時に出ることはないから 39 ・別にすると名前空間が汚れる 40 これは、別の方がいいかも知れない 41 SKIPとSKIP_WITHにした。 42 +/ 43 /+ 44 45 +/ 46 immutable static staticImports = 47 "static import ctpg.is_wrapper;" 48 "static import ctpg.parsers;" 49 "static import ctpg.combinators;" 50 "static import ctpg.caller;" 51 "static import ctpg.input;" 52 "static import ctpg.parse_result;" 53 "static import ctpg.none;"; 54 55 auto parsed = src.parse!(defs, ParserKind!(true, true))(line, file); 56 57 if(parsed.match) 58 { 59 Node code = parsed.value 60 .applySkipLiteral() 61 .applyMemoizeSkip(true) 62 .applyMemoizeLiteral(false) 63 .applyMemoizeNonterminal() 64 .expandSkip() 65 .removeMemoizeDuplicates() 66 .removeSkipWithDuplicates() 67 ; 68 69 string generated = staticImports ~ code.generate(); 70 71 version(ctpgPrintGeneratedCode) 72 { 73 return generated ~ "pragma(msg, \"\n======== " ~ file ~ "(" ~ line.to!string ~ ") =========\n\n\"q{" ~ code.toString() ~ "}\"\n\n=====================\n\n\"q{" ~ generated ~ "});"; 74 } 75 else 76 { 77 return generated; 78 } 79 } 80 else 81 { 82 return "pragma(msg,\"" ~ makeCompilationErrorMessage(parsed.error.msg, file, line + src[0 .. parsed.error.position].count('\n') + 1) ~ "\");static assert(false);"; 83 } 84 } 85 86 mixin template CTPG_DSL_TYPED(string src, size_t line = __LINE__ , string file = __FILE__) 87 { 88 static import ctpg.dsl.typed; 89 mixin(ctpg.dsl.typed.generateParsers(src, line, file)); 90 }