SequenceMatcher.scala 2.57 KB
Newer Older
1
2
3
//
// Copyright (C) 2017 Jens Korinth, TU Darmstadt
//
4
// This file is part of Tapasco (TPC).
5
//
6
// Tapasco is free software: you can redistribute it and/or modify
7
8
9
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
10
// // Tapasco is distributed in the hope that it will be useful,
11
12
13
14
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
16
// along with Tapasco.  If not, see <http://www.gnu.org/licenses/>.
17
18
19
20
21
22
//
/**
 * @file     SequenceMatcher.scala
 * @brief    Multi-line stateful regex matcher for text file parsing.
 * @authors  J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de)
 **/
23
package de.tu_darmstadt.cs.esa.tapasco.util
24
25
26
27
28
import  scala.util.matching._
import  scala.util.matching.Regex.Match

/** Text matching class that matches incoming line-wise text to a sequence of regular
    expressions. Helper to match multi-line stuff in text files. **/
29
private[tapasco] class SequenceMatcher[T](ors : Regex*)(implicit mustMatchEveryLine: Boolean = false,
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    cons: Seq[Match] => T = identity[Seq[Match]] _) {
  private val or: Seq[Regex] = ors.toSeq
  private var rs: Seq[Regex] = ors.toSeq
  private var ms: Seq[Match] = Seq()
  def matched: Boolean = rs.isEmpty
  def matches: Seq[Match] = ms
  def result: Option[T] = if (matched) Some(cons(matches)) else None
  def update(line: String): Boolean = {
    if (rs.isEmpty) { true }
    else {
      val m = rs.head.findFirstMatchIn(line)
      if (m.isEmpty) {
        if (mustMatchEveryLine) rs = or
        false
      } else {
        ms = ms :+ m.get
        rs = rs.tail
        rs.isEmpty
      }
    }
  }
}
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

/** Repeats a [[SequenceMatcher]] to generate a Seq[T]. */
private[tapasco] class RepSeqMatcher[T](ors: Regex*)(implicit mustMatchEveryLine: Boolean = false,
    cons: Seq[Match] => T = identity[Seq[Match]] _) {
  private var matcher = new SequenceMatcher(ors:_*)(mustMatchEveryLine, cons)
  private val _result = new scala.collection.mutable.ArrayBuffer[T]()
  def update(line: String): Boolean = {
    matcher.update(line)
    if (matcher.matched) {
      _result += matcher.result.get
      matcher = new SequenceMatcher(ors:_*)(mustMatchEveryLine, cons)
    }
    matcher.matched
  }
  def result: Option[Seq[T]] = if (_result.isEmpty) None else Some(_result.toSeq)
  def matched: Boolean = _result.nonEmpty
}