2011-02-03 4 views
2

Я пишу парсер для интерфейса командной строки внешнего инструмента, и я использую библиотеку компиляторов Scala. В качестве части этого мне нужно проанализировать стандартную дату формата EEE MMM d HH: mm: ss yyyy Z.Проанализируйте дату из CharSequence со стандартными шаблонами ...

Компараторы анализатора Scala являются «потоковыми» и работают с CharSequence вместо Strings. Это затрудняет использование java.text.DateTimeFormat или DateTimeFormat от JodaTime, поскольку они оба работают со строками.

На данный момент я должен написать свой собственный регулярный анализатор, подобный этому, чтобы проанализировать дату, но я бы скорее включил работу, которая была выполнена с JodaTime, в мой синтаксический анализатор. Я действительно не хочу изобретать велосипед. Я смотрел исходный код JodaTime, и я не совсем уверен, почему он должен работать со строками, а не только с CharSequences. Я пропустил какой-то аспект?

ответ

0

Это мое решение прямо сейчас:

я раздвоенный Joda времени и сделал небольшие изменения для того, чтобы работать на CharSequence с вместо String с. Это здесь https://github.com/hedefalk/joda-time/commit/ef3bdafd89b334fb052ce0dd192613683b3486a4

Тогда я мог бы написать DateParser так:

trait DateParsers extends RegexParsers { 
    def dateTime(pattern: String): Parser[DateTime] = new Parser[DateTime] { 
    val dateFormat = DateTimeFormat.forPattern(pattern); 

    def jodaParse(text: CharSequence, offset: Int) = { 
     val mutableDateTime = new MutableDateTime 
     val newPos = dateFormat.parseInto(mutableDateTime, text, offset) 
     (mutableDateTime.toDateTime, newPos) 
    } 

    def apply(in: Input) = { 
     val source = in.source 
     val offset = in.offset 
     val start = handleWhiteSpace(source, offset) 
     val (dateTime, endPos) = jodaParse(source, start) 
     if (endPos >= 0) 
     Success(dateTime, in.drop(endPos - offset)) 
     else 
     Failure("Failed to parse date", in.drop(start - offset)) 
    } 
    } 
} 

Тогда я могу использовать эту особенность, чтобы иметь правила производства, как:

private[this] def dateRow = "date:" ~> dateTime("EEE MMM d HH:mm:ss yyyy Z") 

ли я изнурение это? Я действительно устал прямо сейчас ...

+0

А я вижу. Таким образом, вы хотите, чтобы lexer regex datetime продвигался, как только появился следующий байт из сети. Кажется, что нет другого способа сделать это, кроме как fork joda-time, и переписать его совпадение, чтобы использовать регулярное выражение или еще лучше, создайте собственную библиотеку анализа данных datetime на основе потоков/regex и поделитесь с нами. Я все еще верю, что ваш ответ здесь - путь. –

+0

Да, я еще не нашел другую библиотеку анализа времени и времени, основанную на потоках. Плюс joda-time - это одноразовая дата api для использования в любом случае, не так ли? Я отправил по электронной почте Стивена Колеборна об этом, и он согласился, что он должен разбирать CharSequence, но может быть проблемы с обратной совместимостью, чтобы он ничего не мог обещать. Худший случай, я должен буду поддерживать свою вилку :) –

+0

Или нет. Я бы не сказал, что joda-time - это все решения для всех ваших потребностей в датах. Я столкнулся с ситуациями, когда шаблон joda-time просто не мог выразить формат, который мне нужен, и мне пришлось вернуться к SimpleDateFormat (ISO 8601 и RFC 3339 имеют множество вариаций). –

1

Got it, now. Хорошо, есть более простое решение, чем форкировка. Здесь:

trait DateParsers extends RegexParsers { 
    def dateTime(pattern: String): Parser[DateTime] = new Parser[DateTime] { 
    val dateFormat = DateTimeFormat.forPattern(pattern); 

    def jodaParse(text: CharSequence, offset: Int) = { 
     val mutableDateTime = new MutableDateTime 
     val maxInput = text.source.subSequence(offset, dateFormat.estimateParsedLength + offset).toString 
     val newPos = dateFormat.parseInto(mutableDateTime, maxInput, 0) 
     (mutableDateTime.toDateTime, newPos + offset) 
    } 

    def apply(in: Input) = { 
     val source = in.source 
     val offset = in.offset 
     val start = handleWhiteSpace(source, offset) 
     val (dateTime, endPos) = jodaParse(source, start) 
     if (endPos >= 0) 
     Success(dateTime, in.drop(endPos - offset)) 
     else 
     Failure("Failed to parse date", in.drop(start - offset)) 
    } 
    } 
} 
+0

Извините, конечно! Но вход по-прежнему «Reader [Elem]» с 'source'-method возвращает' CharSequence'. Я не вижу, как я мог бы использовать это, чтобы передать String во внешнюю синтаксическую структуру. Для меня это кажется невозможным, поскольку комбинаторы работают над потоками. В основном вы не знаете, сколько символов имеет строка даты, и, следовательно, нужен парсер даты, который также работает в потоках, и возвращает информацию о том, сколько из потока, которое оно потребляло. –

+0

Я имею в виду входной итоговый объединенный синтаксический анализатор. Полученный результат анализатора, который я пытаюсь написать, должен быть датой. –

+0

@hedefalk Это 'scala.util.parsing.input.Reader', который вы можете подклассом, независимо от того, что вам нужно. Например, вы можете использовать лексер для возврата токенов, а затем обрабатывать токены. Пожалуйста, напишите какой-то код того, что вы пытаетесь сделать, потому что это не ясно. –

0

Я не уверен, что вы просите. Вы спрашиваете, почему RegexParser.parse() параметр in принимает CharSequence? Если да, есть еще один перегруженный RegexParser.parse(), который берет Reader, который вы можете написать простую функцию преобразования следующим образом:

def stringToReader(str: String): Reader = new StringReader(str) 

Как формат даты, я считаю, это прекрасно, чтобы определить его как знак в анализатор.

Надеюсь, это поможет.

+0

Возможно, мой собственный ответ немного уточнил мой вопрос ...? То, что я пытаюсь достичь, - это синтаксический анализатор, который может использоваться в правилах производства других парсеров и который создает дату. Мой собственный ответ показывает это, но мне пришлось внести изменения в joda-время, чтобы он принял 'CharSequence'. –

+0

Мой вопрос не совсем о компиляторах синтаксического анализатора Scala, но если существует какой-либо установленный способ синтаксического анализа дат из таких шаблонов, как «EE MMM d HH: mm: ss yyyy Z», который работает с потоками символов, поэтому я могу использовать его изнутри комбинатор-анализатор. –

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

  • Нет связанных вопросов^_^