開発
2015/1/8
D言語で、構文拡張
mima
D言語の構文を拡張するライブラリ、Tcenalを作り、D言語アドベントカレンダーに書きました。
Swap演算子を追加したい場合、
import parser_combinator.parsing_result : ParsingResult; import parser_combinator.memo : Memo; import parser_combinator.combinators; import tcenal.dparsers : skip; import tcenal.dsl.generate_parsers : generateParsers; mixin (generateParsers(` AssignExpression <- SwapExpression / super; SwapExpression <- ConditionalExpression ":=:" ConditionalExpression; `)); import tcenal.rule_selector : createRuleSelector; import tcenal.dparsers : Module, skip; alias parse = Module!(createRuleSelector!().RuleSelector); import parser_combinator.parse_tree_node : ParseTreeNode; string generateVisitor(ParseTreeNode node) { if (node.ruleName == "SwapExpression") { return "(){" "static import std.algorithm;" "std.algorithm.swap(" ~ node.children[0].children[0].generateVisitor() ~ "," ~ node.children[0].children[2].generateVisitor() ~ ");" "}()"; } else if (node.ruleName.length > 0) { string codeSegment; foreach (child; node.children) { codeSegment ~= child.generateVisitor(); } return codeSegment; } else { return node.value ~ " "; } } string SWAP_OP(string src) { Memo memo; return parse(src, 0, memo).node.generateVisitor(); }
のように記述し、
import swap_op; mixin (SWAP_OP( q{ void bubblesort(T)(T[] array) { foreach (base; 0 .. array.length - 1) { foreach_reverse (i; base .. array.length - 1) { if (array[i] > array[i + 1]) { array[i] :=: array[i + 1]; } } } } void main() { import std.stdio : writeln; int[] array = [3, 1, 4, 1, 5, 9, 2]; array.bubblesort(); writeln(array); } }));
のように使うことが出来ます。
詳しくは以下の記事を参照してください。
Qiita – D言語の構文を拡張する
担当:美馬(アドベントカレンダー用に作るライブラリとしては大きすぎた感じがします)