2013-10-15 1 views
4

У меня есть этот код, который включает в себя SCALA в Parsers класс:Невозможно выбрать правильный комбинатор для синтаксического анализа и борьбы с ним в Scala

trait SomeTrait extends SomeTrait2 { 
    def myParse = { 
    phrase(rep(
      ElemName(Some("http://someUri/"), "someNode1") ~  //compiles well, but fails sometimes at runtime 
      ElemName(Some("http://someUri/"), "someNode2") ^^ 
      { 
       case p1 ~ p2 ⇒ //...... 
      }) ^^ 
      { 
       case p1 ⇒ // .... 
      }) 
    } 
} 

где

case class ElemName(namespace: Option[String], name: String) { 
    // ..... 
} 

Обычно «someNode1» и "someNode2 «оба существуют во входной мыльной строке (которая здесь не указана, но это не имеет значения). Однако иногда либо один из них может существовать или даже ни один из них, и в этом случае он вылетает во время выполнения.

<items> 
    <subItems> 
    <someNode1 val1="123" val2="456" /> 
    <someNode1 val1="123a" val2="456c" /> 
    <someNode1 val1="123b" val2="456d" /> 
    <someNode2 val1="123" val2="456" /> 
    </subItems> 
    <subItems> 
    <someNode2 val1="123cd" val2="456de" /> 
    </subItems> 
    <subItems> 
    </subItems> 
    <subItems> 
    <someNode1 val1="777" val2="888" /> 
    </subItems> 
<items> 

Мне нужно это обработать. Таким образом, я сделал:

trait SomeTrait extends SomeTrait2 { 
    def myParse = { 
    phrase(rep(
     ElemName(Some("http://someUri/"), "someNode1") |   // should work 
     ElemName(Some("http://someUri/"), "someNode2") ^^ 
     { 
     case p1 ~ p2 ⇒ //...... 
     }) ^^ 
     { 
     case p1 ⇒ // .... 
     }) 

     //or, I'm not sure which one to choose 
     //ElemName(Some("http://someUri/"), "someNode1") |||  // should work also 
     //ElemName(Some("http://someUri/"), "someNode2") ^^ 
    } 
} 

, и это должно работать так, как я понимаю. Однако, на данный момент он не компилируется больше, так как он говорит:

constructor cannot be instantiated to expected type; 
[error] found : SomeTrait.this.~[a,b] 
[error] required: ElemName 
[error]   case p1 ~ p2 ⇒ { 
[error]     ^
[error] one error found 

Я считаю, что я должен заменить случай p1 ~ p2 с чем-то другим.

ответ

1

Проблема в том, что | и ||| оба возвращают один токен. В частности:

a | b пытается разобрать, возвращается, если он успешно и пробует разобрать б, если он не a ||| b пытается разобрать и б и использует результат в зависимости от того один разобрать большинство символов. Я не думаю, что любой из них - это то, что вы хотите. И если они есть, вы должны просто использовать p1 не p1 ~ p2. Я думаю, что вы действительно хотите:

phrase(rep(
    ElemName(Some("http://someUri/"), "someNode1").? ~ 
    ElemName(Some("http://someUri/"), "someNode2").? ^^ 
    { 
    case Some(p1) ~ Some(p2) ⇒ //...... 
    case Some(p1) ~ None => //..... 
    case None ~ Some(p2) => //..... 
    })