回答編集履歴

2

別解 scala-paser-combinators 紹介 (2019-02-07)

2019/02/07 09:19

投稿

退会済みユーザー
test CHANGED
@@ -109,3 +109,113 @@
109
109
  ```
110
110
 
111
111
  ヒントをもとに考えてみましょう。必要なら新しい質問をしてください。
112
+
113
+
114
+
115
+ ### 別解 scala-paser-combinators 紹介 (2019-02-07)
116
+
117
+
118
+
119
+ **パーサーコンビネーター**
120
+
121
+ Scalaのパーサーコンビネーターを使って問題を解いてみました。
122
+
123
+ 『Scala スケーラブルプログラミング 第3版』インプレス - 第33章 パーサー・コンビネーター
124
+
125
+
126
+
127
+ 質問の関数をEBNFで記述しました。
128
+
129
+
130
+
131
+ ```EBNF
132
+
133
+ function ::= functionHeader argList
134
+
135
+ argList ::= argLiteral args
136
+
137
+ args ::= argLiteral [args]
138
+
139
+ functionHeader ::= (“A” | .. | “Z”)
140
+
141
+ argLiteral ::= ( “(“ smallAlpha smallAlpha “)” | smallAlpha )
142
+
143
+ smallAlpha ::= (“a” | .. | “z”)
144
+
145
+ ```
146
+
147
+
148
+
149
+ 記述したEBNFをもとに、scala.util.parsing.combinator.RegexParsersを使って、パーサーを作成します。^^に続けてパース後に実行する動作を記述します。動作は関数の第二引数を削除して、それ以外の引数を表示する処理になります。
150
+
151
+
152
+
153
+ ```Scala
154
+
155
+ import scala.util.parsing.combinator._
156
+
157
+ class FunctionParserEval extends RegexParsers {
158
+
159
+
160
+
161
+ def expr: Parser[String] = function ^^ {_.mkString}
162
+
163
+ def function: Parser[List[String]] = functionHeader~argList ^^ { case _ ~ b => b.head :: b.drop(2) }
164
+
165
+ def argList: Parser[List[String]] = argLiteral~args ^^ { case a ~ b => a::b }
166
+
167
+ def args: Parser[List[String]] = argLiteral~opt( args ) ^^ {
168
+
169
+ case a ~ None => a :: Nil
170
+
171
+ case a ~ Some(b) => a :: b
172
+
173
+ }
174
+
175
+ def argLiteral: Parser[String] = "(\([a-z]{2}\)|[a-z])".r
176
+
177
+ def functionHeader: Parser[String] = "[A-Z]".r
178
+
179
+
180
+
181
+ def parse(str:String) = parseAll(expr,str)
182
+
183
+ }
184
+
185
+ ```
186
+
187
+
188
+
189
+ パーサーに関数文字列を入力して評価し、結果を表示します。第二引数を削除した引数が表示されます。
190
+
191
+
192
+
193
+ ```Scala
194
+
195
+ val parserEval = new FunctionParserEval
196
+
197
+ println(parserEval.parse("Aabcd"))
198
+
199
+ println(parserEval.parse("A(xy)(yz)(za)"))
200
+
201
+ ```
202
+
203
+
204
+
205
+ **build.sbt**
206
+
207
+ パーサーコンビネーターは、最新のScala基本パッケージに同梱されていないので、sbt環境にダウンロードします。
208
+
209
+
210
+
211
+ ```sbt
212
+
213
+ "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.1"
214
+
215
+ ```
216
+
217
+
218
+
219
+ **参考**
220
+
221
+ https://github.com/scala/scala-parser-combinators

1

ヒントを追加

2019/02/07 09:19

投稿

退会済みユーザー
test CHANGED
@@ -79,3 +79,33 @@
79
79
  このような形式で質問して下されば、余計な質疑応答がなくなります。
80
80
 
81
81
  実現のところに具体的なソースコードやエラーメッセージが書けるようになるとなお良いです。
82
+
83
+
84
+
85
+ ### ヒント
86
+
87
+ slice()を使わず、正規表現を使うことをすすめます。
88
+
89
+
90
+
91
+ ヒント:引数を取り出してListに格納する。
92
+
93
+ ```Scala
94
+
95
+ "(\([a-z]{2}\)|[a-z])".r.findAllIn("Abcd").toList
96
+
97
+ "(\([a-z]{2}\)|[a-z])".r.findAllIn("A(xy)(yz)(za)").toList
98
+
99
+ ```
100
+
101
+
102
+
103
+ ヒント:listの2番目の要素を削除する。リストに格納する型は無関係です。
104
+
105
+ ```Scala
106
+
107
+ def drop2nd[T](list:List[T]):List[T] = if (list.isEmpty) list else list.head :: list.drop(2)
108
+
109
+ ```
110
+
111
+ ヒントをもとに考えてみましょう。必要なら新しい質問をしてください。