public Combination Successor() { if (this.data[0] == this.n - this.k) return null; Combination ans = new Combination(this.n, this.k); long i; for (i = 0; i < this.k; ++i) ans.data[i] = this.data[i]; for (i = this.k - 1; i > 0 && ans.data[i] == this.n - this.k + i; --i) ; ++ans.data[i]; for (long j = i; j < this.k - 1; ++j) ans.data[j + 1] = ans.data[j] + 1; return ans; }
// unroll文はmacro扱い。 public SyntaxTree UnrollStatement() { var tree = CreateSyntaxTree(Syntax.Unroll); // 一応、構文解析をする。 var treeNew = CreateSyntaxTree(Syntax.Macro); // 実際は、変換後のソースを保持する。 tree.Append(Token); // "unroll" var token = Token; switch(token) { case Token.CASE: { /* unroll case { case 1: AAA case 2: BBB case 4: CCC } */ tree.Append(Token.CASE); // "case" tree.Append(Token.LBRACE); // "{" var caselist = new List<SyntaxTree>(); while (Token == Token.CASE || Token == Token.DEFAULT) { var t = CaseStatement(); tree.Append(t); caselist.Add(t); } tree.Append(Token.RBRACE); // "}" // このあとMacroに変換してそれを返す // caselistのなかですべての順列組み合わせ int n = caselist.Count; for (int i = 1; i <= n; ++i) { var c = new Combination(n, i); var m = Combination.Choose(n, i); for (int j = 0; j < m; ++j) { var e = c.Element(j); // これですべての順列組み合わせが得られた。 treeNew.Append(Token.CASE, "case"); for (int k = 0; k < e.data.Length; ++k) { if (k != 0) treeNew.Append(Token.PLUS, "+"); // case 1: case 2: みたいになっていないことを仮定しているので // まあここは決め打ちでいいや treeNew.Append(Token.IDENT, caselist[(int) e.data[k]].elms[0].elms[1].ToString()); } treeNew.Append(Token.COLON, ":"); for (int k = 0; k < e.data.Length; ++k) { treeNew.Append(Token.IDENT, caselist[(int) e.data[k]].elms[1].ToString()); } treeNew.Append(Token.BREAK, "break"); treeNew.Append(Token.SEMICOLON, ";"); } } return treeNew; } case Token.FOREACH: { // unroll foreach ident in range_parameters StatementSequence tree.Append(Token); // "foreach" tree.Append(Token.IDENT); tree.Append(Token.IN); tree.Append(RangeParameters()); tree.Append(StatementSequence()); // 解析が終わったので並べ替えて出力する。 var ss = tree.elms[5].ToString(); var target = tree.elms[2].ToString(); foreach (var t0 in RangeParameters2Enumerator(tree.elms[4])) { var ss_string = ss.Replace(target, t0); treeNew.Append(Token.SOMETHING, ss_string); } return treeNew; } default: // それ以外のなんかのunroll throw new UnrollerException("使えないunroll"); } }