2013-12-13 2 views
0

Его первый раз, используя комбинаторы парсера scala. У меня такая ситуация, когда у меня есть список «типов», и они могут распространять другие типы или нет. Если это так, я просто создаю карту между типом и его родительским типом. Если нет, просто сопоставьте тип с «объектом». (Типы просто струнные имена)Комбинировщик Parser Дополнительные детали

Они написаны так:

type1 type2 type3 - parentType 

или

type0a type0b 

в этом случае они будут неявно быть - object

Я пытался реализовать его в следующим образом, но не компилируя его. Он говорит, что для него требуется Option [~ List [String, String], и он нашел ~ [a, b]. Его также говорит, что он не может найти имена значений в первом для понимания, когда на самом деле его указано в шаблоне case. Немного смущает теперь то, что на самом деле происходит.

def type_list = ((name+) ~ ("-" ~> parent_type)?) ^^ { 
    case names ~ parent_type => for (name <- names) yield name -> parent_type 
    case names => for (name <- names) yield name -> "object" 
} 

def name = """[a-zA-Z\d]+""".r 

На самом деле я просто хочу, чтобы это вернуть Map[String, String], если parent_type отсутствует он должен по умолчанию «объект». Как лучше подойти к этому?

ответ

3

Здесь есть несколько вещей.

Во-первых, приоритет ~ и? означает, что вместо объединения (name +), который является Parser [List [String]] с ("-" ~> parent_type)? который является Parser [Option [String]], вы фактически обертываете все это? и поэтому получить Parser [Option [~ [List [String], String]], если это имеет смысл.

Простейшим решением является использование дополнительного набора кронштейнов.

Итак, вы хотите начать с:

def type_list = ((name+) ~ (("-" ~> parent_type)?)) 

Тогда в функции отображения, что будет вы будете получать это ~ [Список [String], опция [String]] со списком имен и необязательный параметр parent_type. С точки зрения соответствия шаблону вы всегда получаете имя ~ parent_type, где последним является опция [String]. Так что в основном ваш второй шаблон недействителен.

Таким образом, вы можете либо сделать это:

def type_list = ((name+) ~ (("-" ~> parent_type)?)) ^^ { 
    case names ~ Some(parent_type) => for (name <- names) yield name -> parent_type 
    case names ~ None => for (name <- names) yield name -> "object" 
} 

Или вы могли бы упростить это:

def type_list = ((name+) ~ (("-" ~> parent_type)?)) ^^ { 
    case names ~ parent_type => for (name <- names) yield name -> parent_type.getOrElse("object) 
} 
+0

Спасибо ... Эти монады до сих пор удается поставить меня из колеи. Спасибо за простую версию. – jbx