回答編集履歴

2

練習問題

2015/05/21 23:38

投稿

takotakot
takotakot

スコア1111

test CHANGED
@@ -99,3 +99,53 @@
99
99
 
100
100
 
101
101
  これで、動くんじゃないかな…。
102
+
103
+
104
+
105
+
106
+
107
+ ```lang-
108
+
109
+ A
110
+
111
+ {if $v1}
112
+
113
+ B
114
+
115
+ {if $v2}
116
+
117
+ C
118
+
119
+ {if $v3}
120
+
121
+ D
122
+
123
+ {if $v4}
124
+
125
+ E
126
+
127
+ {/if}
128
+
129
+ D
130
+
131
+ {/if}
132
+
133
+ C
134
+
135
+ {/if}
136
+
137
+ B
138
+
139
+ {/if}
140
+
141
+ A
142
+
143
+ ```
144
+
145
+ 上記で、2つのA, B, C, D が「出力されるかどうか」は必ず一致しているのが理解できるでしょうか。それを担保するのが stack への push と pop です。
146
+
147
+
148
+
149
+ $v1=TRUE, $v2 未定義, $v3=FALSE, $v4=TRUE の状態で、各A, B, C, D は出力されるかどうか、考えてみて下さい。さらに、A, B, C, D で stack 及び内部状態がどうなっているか、考えて下さい。
150
+
151
+ 答え…いりますか?

1

詳細に

2015/05/21 23:38

投稿

takotakot
takotakot

スコア1111

test CHANGED
@@ -1,3 +1,101 @@
1
1
  プッシュダウン・オートマトン...でだめでしょうか。
2
2
 
3
3
  詳しく必要であれば、詳しく書きます。
4
+
5
+
6
+
7
+ 変数定義ファイル(例2) での "{/if $date}" は "{/lf}" の書き間違いと解釈して、コメントします。
8
+
9
+
10
+
11
+ 私ならどう実装するか、簡単に書きますね。Java はしばらく触っていないので、用語が間違っていたら教えて下さい。
12
+
13
+ まず、変数定義ファイルからデータを読みます。`variables_map Map<String, boolean>` を用意しておきます。
14
+
15
+ 出力用に、StringWriter を1つ確保しておきます。その後で、処理用の関数を一つ呼びます。
16
+
17
+
18
+
19
+ 関数は、出力有無を覚えておくためにスタック一つ `state_stack`、`int state`、文字列インデックス `int index`、一時的な文字列 `String var_str` を持ちます。state の初期値は 1 とします。
20
+
21
+ 0 が FALSE、1 が TRUE、2 が「FALSE かつ、変数がない状態」、3 が「TRUE かつ、変数がない状態」に対応しているとします。
22
+
23
+
24
+
25
+ まず、関数内では、"{if " または "{/if}" という文字列を探します。読んでいる位置を new_index とします。String.indexOf(String str, int fromIndex) を使えばよいですね。もし、state が TRUEであれば、この間の文字列は全部出力として有効なので、substring で切り出して、StringWriter に書き出します。FALSE なら、読み捨てます。
26
+
27
+
28
+
29
+ 続いて、"{if " か "{/if}" かによって、処理を変えます。
30
+
31
+
32
+
33
+ ### "{if " であったら
34
+
35
+ 続いて、"$***}" が来るはずなので、そこまで読んでおきましょう。`var_str` に代入します。スタックに現在の `state` を積みます。それ以外の場合は「たまたま "{if " という文字列が来た」と解釈するか、「文法エラー」かどちらかです。適当に決めて下さい。
36
+
37
+
38
+
39
+ #### "{if " で変数が存在する
40
+
41
+ `variables_map.containKey(var_str)` が TRUE の時は、普通のときです。
42
+
43
+
44
+
45
+ state が TRUE(1, 3) の場合、続いて、variables_map を使って
46
+
47
+ `state = variables_map.get(var_str) ? 1 : 0;`
48
+
49
+ とします。要するに、変数が TRUE なら 1にします。内側も出力するからです。
50
+
51
+
52
+
53
+ state が FALSE(2, 4) の場合、内側は出力しないと思うので、
54
+
55
+ `state = 2;`
56
+
57
+ とします。
58
+
59
+
60
+
61
+ "}" の終わりまで読んで終了です。
62
+
63
+
64
+
65
+ ### "{if " で変数が存在しない
66
+
67
+ `variables_map.containKey(var_str)` が FALSE の時は、残ります。
68
+
69
+ state が TRUE(1, 3) の場合
70
+
71
+ "{if $***}" を出力し、 `state = 3;` とします。仮置きの状態です。
72
+
73
+
74
+
75
+ `state` が FALSE(0, 2) の場合
76
+
77
+ 出力せずに、`state = 2;` とします。
78
+
79
+
80
+
81
+ "}" の終わりまで読んで終了です。
82
+
83
+
84
+
85
+
86
+
87
+ ### "{/if}" であったら
88
+
89
+ `state` の値が TRUE(1) か FALSE(0, 2) の場合、読み捨てます。
90
+
91
+ `state` の値が 3 の場合、{/if} を出力します。
92
+
93
+ `state = state_stack.pop();`
94
+
95
+ で、更新します。`state_stack` が空の場合は異常です。
96
+
97
+
98
+
99
+
100
+
101
+ これで、動くんじゃないかな…。