2015-06-17 4 views
0

Я пишу парсер, используя StandardTokenParsers в Scala. Необходимо создать парсер регулярных выражений для анализа пути. Я тестировал регулярное выражение, отлично работает, но отправляя его в функцию для его анализа, программа дает ошибку, которую я не могу понять! часть кода, который связан с этим анализатором выглядит следующим образом:Как решить ошибку, связанную с созданием парсера из регулярного выражения?

class InfixToPostfix extends StandardTokenParsers { 
import scala.util.matching.Regex 
import lexical.StringLit 
//parsing the path 
def regexStringLit(r: Regex): Parser[String] = 
acceptMatch("string literal matching regex " + r,{ case StringLit(s) if r.unapplySeq(s).isDefined => s }) 
// Regex for path 
val pathIdent ="""/hdfs://[\d.]+:\d+/[\w/]+/\w+([.+]\w+)+""".r 
def pathIdente: Parser[String] =regexStringLit(pathIdent) 

lexical.delimiters ++= List("+","-","*","/", "^","(",")",",") 
def value :Parser[Expr] = numericLit ^^ { s => Number(s) } 
def variable:Parser[Expr] = pathIdente ^^ { s => Variable(s) } 
def parens:Parser[Expr] = "(" ~> expr <~ ")" 

def argument:Parser[Expr] = expr <~ (","?) 
def func:Parser[Expr] = (pathIdente ~ "(" ~ (argument+) ~ ")" ^^ { case f ~ _ ~ e ~ _ => Function(f, e) }) 
//and the rest of the code .... 

Этот анализатор будет анализировать арифметические операции. Я использую арг (0), чтобы отправить свой вклад в программу, которая: «/hdfs://111.33.55.2:8888/folder1/p.a3d+1»

и я получаю следующее сообщение об ошибке:

[1.1] failure: string literal matching regex /hdfs://([\d\.]+):(\d+)/([\w/]+/(\w+\.\w+)) expected 

/hdfs://111.33.55.2:8888/folder1/p.a3d 
^ 

Не удалось выяснить, как его решить!

FYI: Часть для «+1» будет обрабатываться парсером в коде, поэтому часть «pathIdent» предназначена только для пути, и это часть, вызывающая проблемы. Это также хорошо:

"""/hdfs://\d+(\.\d+){3}:\d+(/(\w+([.+]\w+)*))+""".r 

он отлично работает за пределами кода проверки его: regexpal.com , но все же ошибка при использовании его в программе.

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

+0

Я думаю, он говорит, что вход не соответствует этому регулярному выражению. Каков был вклад? – sln

+0

например: "/hdfs://111.33.55.2:8888/folder1/p.a3d+1", но я прокомментировал остальную часть кода, кроме части пути, и попробовал его только с "/hdfs://111.33. 55.2: 8888/folder1/p.a3d "он по-прежнему дает ту же ошибку – Rubbic

+0

Где это'/hdfs: // ([\ d \.] +): (\ D +)/([\ w /] +/(\ w + \. \ w +)) 'от? Я вижу только код '/ hdfs: // [\ d.] +: \ D +/[\ w /] +/\ w + ([. +] \ W +) +' кода. – sln

ответ

1

Невозможность совпадения будет заключаться в том, что сопряжение является жадным. Это обычная проблема с регулярным выражением (и, следовательно, лексическим анализом) на нескольких языках.

Жадное совпадение улавливает вас в конце выражения.

Вы ([\w/]+/(\w+\.\w+)), но это не соответствует, потому что словоp соответствует по \w представленным входному тексту folder1/p поглощен поштучно ([\w/]+. Он останавливается на период .. Поэтому нет слова перед точкой, чтобы разрешить (\w+\.\w+).

Вам нужно переосмыслить свое регулярное выражение и сделать каждый фрагмент пути завершенным на солидасе /, а не сделать его частью набора.

Вы видите?

Чтобы сделать эту работу, Вы должны выразить следующим образом:

"""/hdfs://[\d.]+:\d+/(\w/)+\w+([.+]\w+)+""".r 

Где я заменил [\w/]+/ на (\w/)+. Это теперь указывает порядок слов и косых черт и оставляет слово, не имеющее аналогов для следующего шаблона.

+0

Ага! Я вижу, что вы говорите! Итак, вы хотите решить это, я должен отделить имя файла, содержащее точку? – Rubbic

+0

Я тоже пробовал это "" "/hdfs://\d+(\.\d+){3}:\d+(/(\w+([.+]\w+)*))+" "". r, но не работает – Rubbic

+0

Я также изменил свое регулярное выражение только: "" "/ hdfs: //" "" и отправил "/ hdfs: //" в качестве ввода в программу и получил ту же ошибку! – Rubbic

Смежные вопросы