Независимо от того, хотите вы реализовать правильный синтаксический анализатор или нет, вы должны по крайней мере создать структуры данных, которые могут точно представлять ваши команды.
Вот одно предложение:
sealed trait Dimension {
def translate(implicit t: Map[Symbol, String]) =
t(Symbol(toString.toLowerCase))
}
case object W extends Dimension
case object H extends Dimension
case object L extends Dimension
case object R extends Dimension
case object T extends Dimension
case object B extends Dimension
object Dimension {
def all = List(W, H, L, R, T, B)
}
sealed trait CommandModifier {
def translate(implicit t: Map[Symbol, String]): String
}
case object Unmodified extends CommandModifier {
def translate(implicit t: Map[Symbol, String]) = ""
}
case class Multiplied(factor: Int) extends CommandModifier {
def translate(implicit t: Map[Symbol, String]) = t('m) + " " + factor
}
case class Command(dim: Dimension, mod: CommandModifier) {
def translate(implicit t: Map[Symbol, String]) =
dim.translate + " " + mod.translate
}
ACommand
- это правильный класс падежа, который имеет размер и модификатор в качестве члена.CommandModifier
моделируются как отдельная запечатанная черта.Dimension
s (ширина, высота и т. Д.) - это просто перечисление.Короткие строки магического значения "w"
, "h"
были заменены символами 'w
, 'h
и т. Д.
Теперь вы можете реализовать экстрактор Untranslation
, который извлекает всю команду за один раз.и, следовательно, не требует никаких дополнительных параметров:
object Untranslation {
def unapply(s: String)(implicit t: Map[Symbol, String]): Option[Command] = {
val sParts = s.split(" ").toList
for (dim <- Dimension.all) {
val a: List[String] = dim.translate.split(" ").toList
val b: List[String] = t('m).split(" ").toList
val ab: List[String] = a ++ b
sParts match {
case `a` => return Some(Command(dim, Unmodified))
case `ab` :+ value => return Some(Command(dim, Multiplied(value.toInt)))
// + some more cases
case _ => None
}
}
None
}
}
Небольшой пример.Вот как вы можете анализировать и записывать команды на английском и немецком языках.Во-первых, два словаря, которые отображают формальные символы в фактические слова на естественном языке:
val En = Map(
'w -> "width",
'h -> "height",
'l -> "left",
'r -> "right",
't -> "top",
'b -> "bottom",
'm -> "multiplied by"
)
val De = Map(
'w -> "Breite",
'h -> "Höhe",
'l -> "links",
'r -> "rechts",
't -> "oben",
'b -> "unten",
'm -> "mal"
)
Используя En
-директион, вы можете теперь сопоставлять команды на английском языке:
for (example <- List(
"width multiplied by 2",
"top",
"height multiplied by 42"
)) {
println("-" * 60)
implicit val lang = En
example match {
case Untranslation(v) => {
println(v)
println(v.translate(En))
println(v.translate(De))
}
case _ => println("invalid command")
}
}
Вот что соответствует, и как оно переводится на английский и немецкий:
------------------------------------------------------------
Command(W,Multiplied(2))
width multiplied by 2
Breite mal 2
------------------------------------------------------------
Command(T,Unmodified)
top
oben
------------------------------------------------------------
Command(H,Multiplied(42))
height multiplied by 42
Höhe mal 42
То же самое работает наоборот, с немецкого на английский:
for (example <- List(
"Breite mal 2",
"oben",
"Höhe mal 42"
)) {
println("-" * 60)
implicit val lang = De
example match {
case Untranslation(v) => {
println(v)
println(v.translate(En))
println(v.translate(De))
}
case _ => println("invalid command")
}
}
Вывод:
------------------------------------------------------------
Command(W,Multiplied(2))
width multiplied by 2
Breite mal 2
------------------------------------------------------------
Command(T,Unmodified)
top
oben
------------------------------------------------------------
Command(H,Multiplied(42))
height multiplied by 42
Höhe mal 42
Обратите внимание, что весь подход с разделением строк и сопоставлением с образцом является чрезвычайно хрупким и не масштабируется вообще.Если вы хотите сделать это правильно, вы должны написать правильный синтаксический анализатор (либо с помощью генератора синтаксических анализаторов, либо с помощью библиотеки комбинатора синтаксического анализатора).