teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

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

2019/02/07 09:19

投稿

退会済みユーザー
answer CHANGED
@@ -53,4 +53,59 @@
53
53
  ```Scala
54
54
  def drop2nd[T](list:List[T]):List[T] = if (list.isEmpty) list else list.head :: list.drop(2)
55
55
  ```
56
- ヒントをもとに考えてみましょう。必要なら新しい質問をしてください。
56
+ ヒントをもとに考えてみましょう。必要なら新しい質問をしてください。
57
+
58
+ ### 別解 scala-paser-combinators 紹介 (2019-02-07)
59
+
60
+ **パーサーコンビネーター**
61
+ Scalaのパーサーコンビネーターを使って問題を解いてみました。
62
+ 『Scala スケーラブルプログラミング 第3版』インプレス - 第33章 パーサー・コンビネーター
63
+
64
+ 質問の関数をEBNFで記述しました。
65
+
66
+ ```EBNF
67
+ function ::= functionHeader argList
68
+ argList ::= argLiteral args
69
+ args ::= argLiteral [args]
70
+ functionHeader ::= (“A” | .. | “Z”)
71
+ argLiteral ::= ( “(“ smallAlpha smallAlpha “)” | smallAlpha )
72
+ smallAlpha ::= (“a” | .. | “z”)
73
+ ```
74
+
75
+ 記述したEBNFをもとに、scala.util.parsing.combinator.RegexParsersを使って、パーサーを作成します。^^に続けてパース後に実行する動作を記述します。動作は関数の第二引数を削除して、それ以外の引数を表示する処理になります。
76
+
77
+ ```Scala
78
+ import scala.util.parsing.combinator._
79
+ class FunctionParserEval extends RegexParsers {
80
+
81
+ def expr: Parser[String] = function ^^ {_.mkString}
82
+ def function: Parser[List[String]] = functionHeader~argList ^^ { case _ ~ b => b.head :: b.drop(2) }
83
+ def argList: Parser[List[String]] = argLiteral~args ^^ { case a ~ b => a::b }
84
+ def args: Parser[List[String]] = argLiteral~opt( args ) ^^ {
85
+ case a ~ None => a :: Nil
86
+ case a ~ Some(b) => a :: b
87
+ }
88
+ def argLiteral: Parser[String] = "(\([a-z]{2}\)|[a-z])".r
89
+ def functionHeader: Parser[String] = "[A-Z]".r
90
+
91
+ def parse(str:String) = parseAll(expr,str)
92
+ }
93
+ ```
94
+
95
+ パーサーに関数文字列を入力して評価し、結果を表示します。第二引数を削除した引数が表示されます。
96
+
97
+ ```Scala
98
+ val parserEval = new FunctionParserEval
99
+ println(parserEval.parse("Aabcd"))
100
+ println(parserEval.parse("A(xy)(yz)(za)"))
101
+ ```
102
+
103
+ **build.sbt**
104
+ パーサーコンビネーターは、最新のScala基本パッケージに同梱されていないので、sbt環境にダウンロードします。
105
+
106
+ ```sbt
107
+ "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.1"
108
+ ```
109
+
110
+ **参考**
111
+ https://github.com/scala/scala-parser-combinators

1

ヒントを追加

2019/02/07 09:19

投稿

退会済みユーザー
answer CHANGED
@@ -38,4 +38,19 @@
38
38
  以上
39
39
 
40
40
  このような形式で質問して下されば、余計な質疑応答がなくなります。
41
- 実現のところに具体的なソースコードやエラーメッセージが書けるようになるとなお良いです。
41
+ 実現のところに具体的なソースコードやエラーメッセージが書けるようになるとなお良いです。
42
+
43
+ ### ヒント
44
+ slice()を使わず、正規表現を使うことをすすめます。
45
+
46
+ ヒント:引数を取り出してListに格納する。
47
+ ```Scala
48
+ "(\([a-z]{2}\)|[a-z])".r.findAllIn("Abcd").toList
49
+ "(\([a-z]{2}\)|[a-z])".r.findAllIn("A(xy)(yz)(za)").toList
50
+ ```
51
+
52
+ ヒント:listの2番目の要素を削除する。リストに格納する型は無関係です。
53
+ ```Scala
54
+ def drop2nd[T](list:List[T]):List[T] = if (list.isEmpty) list else list.head :: list.drop(2)
55
+ ```
56
+ ヒントをもとに考えてみましょう。必要なら新しい質問をしてください。