2015-04-28 3 views
1

мне нужно использовать регулярное выражение, чтобы соответствовать шаблону в Scala, и я в настоящее время есть Regex, которыйScala Regex Pattern Matching

InputPattern: scala.util.matching.Regex = put (.*) in (.*) 

Когда я бегу follwing это происходит:

scala> val InputPattern(verb, item, prep, obj) = "put a in b"; 
scala.MatchError: put a in b (of class java.lang.String) 
... 33 elided 

I хотел бы, чтобы он закончил с verb("put"), item("a"), prep("in"), and obj("b") для ввода «положить a в b», а также verb("put"), item(""), prep("in"), and obj("") для ввода «положить в».

Благодаря

+0

Я думаю, вам нужен шаблон с 4 захватывающих группами, например '(M)^(\ S *) \ S * (\ S *?) \ S * (\ S *) \ S * (\ S *?) $'. Взгляните на демонстрационную версию: https://regex101.com/r/mC5eI5/1 –

ответ

1

Это работает для особых случаев:

scala> val InputPattern = "(put) (.*?) ?(in) ?(.*?)".r 
InputPattern: scala.util.matching.Regex = (put) (.*) ?(in) ?(.*) 

scala> val InputPattern(verb, item, prep, obj) = "put a in b" 
verb: String = put 
item: String = a 
prep: String = in 
obj: String = b 

scala> val InputPattern(verb, item, prep, obj) = "put in" 
verb: String = put 
item: String = "" 
prep: String = in 
obj: String = "" 

put и in здесь также учитываются в группах для участия в сопоставлении с образцом. Я также использовал ленивые регулярные выражения (.*?), чтобы сделать как можно меньше, вы можете заменить его (\S*). ? дает вам дополнительное пространство для соответствия «положить» (с одним пробелом между put и in и без пробела в конце).

Но знать об этом:

scala> val InputPattern(verb, item, prep, obj) = "put ainb" 
verb: String = put 
item: String = a 
prep: String = in 
obj: String = b 

scala> val InputPattern(verb, item, prep, obj) = "put aininb" 
verb: String = put 
item: String = a 
prep: String = in 
obj: String = inb 

scala> val InputPattern(verb, item, prep, obj) = "put ain" 
verb: String = put 
item: String = a 
prep: String = in 
obj: String = "" 

Если у вас есть простой интерпретатор команд может быть даже хорошо, в противном случае вы должны соответствовать вашим особым случаям по отдельности.

Для обработки простого (не естественно) языка, вы можете также рассмотреть вопрос о StandardTokenParsers, так как они являются контекстно-свободным (Chomsky type 2):

import scala.util.parsing.combinator.syntactical._ 

val p = new StandardTokenParsers { 
    lexical.reserved ++= List("put", "in") 
    def p = "put" ~ opt(ident) ~ "in" ~ opt(ident) 
} 

scala> p.p(new p.lexical.Scanner("put a in b")) 
warning: there was one feature warning; re-run with -feature for details 
res13 = [1.11] parsed: (((put~Some(a))~in)~Some(b)) 

scala> p.p(new p.lexical.Scanner("put in")) 
warning: there was one feature warning; re-run with -feature for details 
res14 = [1.7] parsed: (((put~None)~in)~None) 
1

Вы можете написать одно регулярное выражение для всех случаев, но я не уверен, что это будет читаемым и ремонтопригодны. Я предпочитаю простой подход:

val pattern1 = "(put) (.*) (in) (.*)".r 
val pattern2 = "(put) (in)".r 
def parse(text: String) = text match { 
    case pattern1(verb, item, prep, obj) => (verb, item, prep, obj); 
    case pattern2(verb, prep) => (verb, "", prep, "") 
} 
scala> parse("put a in b") 
res6: (String, String, String, String) = (put,a,in,b) 

scala> parse("put in") 
res7: (String, String, String, String) = (put,"",in,"") 

И еще одно понятие: надеюсь, вы знаете, что вы делаете! RegEx - это Chomsky Type 3 grammar, а естественный язык намного сложнее. Если вам нужен парсер для естественного языка, вы можете использовать уже имеющееся решение, такое как Stanford NLP parser.

+0

Спасибо! Хотя это и работает, другой ответ лучше работает в моем коде. Спасибо за «лишнее понятие», но это просто для простого присвоения Коллегии со списком заданных команд с переменными. Это мой первый раз, когда я делал Scala, и я просто сталкивался с некоторыми проблемами с моим RegEx. –