Подобные программы синтаксического анализа: почему один работает, а другой нет? - PullRequest
0 голосов
/ 11 января 2012

Это работает:

<code><?php
  //compare1.php
  //**CLASS AND OBJECT
  class Entry
  {
    private $s_ids;

    public function __construct()
    {
      $this->s_ids      = array();
    }

    public function AddS_id($s_id)
    {
      $this->s_id[] = $s_id;
    }

    public function SetS_ids($s_ids)
    {
      $this->s_ids[] = $s_ids;
    }

    public function GetS_id($i)
    {
      if ($i > count($s_ids))
        throw new Exception('Out of bounds.');
      return $this->s_ids[$i];
    }

    public function GetS_ids()
    {
      return $this->s_ids;
    }
  }


  //EXTRACTION FUNCTION
  function extractS_ids($line)
  {
    $matches;
    preg_match('/^S_id:\s+(.*)\s+$/', $line, $matches);
    return $matches[1];
  }


  //LINE CHECKS
  function isStart($line)
  {
    return preg_match('/^Start.*$/', $line);
  }

  function isS_id($line)
  {
    return preg_match('/^S_id:\s+(.*)$/', $line);
  }

  function isEnd($line)
  {
    return preg_match('/^End.*$/', $line);
  }


  //VARIABLE DECLARATION
  $fName = 'sample1.txt';
  $fh    = fopen($fName, 'r');
  $line;
  $entry;
  $entrys = array();


  //PARSE OPERATION
  if ($fh === FALSE)
    die ('Failed to open file.');

  while (($line = fGets($fh)) !== FALSE)
  {
    if (isStart($line)){
      $entry = new Entry();
    }
    if (isS_id($line)){
      $entry->SetS_ids(extractS_ids($line));
    }
    if (isEnd($line)){
      $entrys[] = $entry;
    }
  }


  //ARRAY RETRIEVAL
  echo "<pre>";
    print_r($entrys);
  echo "
"; fclose ($ ФХ); ?>

С этим примером файла:

Start
S_id:      0611147
S_id:      0651134
End

Start
S_id:      0611125
S_id:      0651125
End

Это не работает:

<code><?php
  //compare2.php
  //CLASS AND OBJECT
  class Entry
    {
      private $titles; 

      public function __construct()
      {
        $this->titles = array();
      }

      public function AddType($title)
      {
        $this->titles[] = $title;
      }

      public function SetTitles($titles)
      {
        $this->titles[] = $titles;
      }

      public function GetTitle($i)
      {
        if ($i > count($titles))
          throw new Exception('Out of bounds.');
        return $this->titles[$i];
      }

      public function GetTitles()
      {
        return $this->titles;
      }
    }

  //EXTRACTION FUNCTION
  function extractTitles($line)
  {
    $matches;
    preg_match('/^<title>(.*)<\/title>.*$/', $line, $matches);
    return $matches[1];
  }

  //LINE CHECK FUNCTION
  function isStart_entry($line)
  {
    return preg_match('/^<title>.*$/', $line);
  }

  function isTitle($line)
  {
    return preg_match('/^<title>.*<\/title>.*$/', $line);
  }

  function isClose_entry($line)
  {
    return preg_match('/^<\/list>.*$/', $line);
  }


  //DECLARATIONS
  $fName = 'sample2.txt';
  $fh    = fopen($fName, 'r');
  $line;
  $entry;
  $entrys = array();


  //PARSE OPERATION
  if ($fh === FALSE)
    die ('Failed to open file.');

  while (($line = fgets($fh)) !== FALSE)
  {
    if (isStart_entry($line)){
      $entry = new Entry();
    }
    if (isTitle($line)){
      $entry->SetTitles(extractTitles($line));
    }
    if (isClose_entry($line)){
      $entrys[] = $entry;
    }
  }

  // Dump the results.
  echo "<pre>";
    print_r($entrys);
  echo "
"; // Закрыть файл. fclose ($ ФХ); ?>

С этим примером файла:

<list>
<title>Coco</title>
<title>Cafe Milk Tea</title>
</list>
<list>
<title>Strong Off</title>
<title>5% Grapefruit</title>
</list>

Логика кажется такой же. Я проверил множественное число, и я проверил функции preg match. Все в compare1.php кажется параллельным compare2.php, но посмотрите на различия в выходных данных:

Output1:

Array
(
    [0] => Entry Object
        (
            [s_ids:Entry:private] => Array
                (
                    [0] => 0611147
                    [1] => 0651134
                )

        )

    [1] => Entry Object
        (
            [s_ids:Entry:private] => Array
                (
                    [0] => 0611125
                    [1] => 0651125
                )

        )

Выход 2:

Array
(
    [0] => Entry Object
        (
            [titles:Entry:private] => Array
                (
                    [0] => Cafe Milk Tea
                )

        )

    [1] => Entry Object
        (
            [titles:Entry:private] => Array
                (
                    [0] => 5% Grapefruit
                )

        )

)


)

Как файлы могут быть практически одинаковыми, и, тем не менее, последние из двух возвращают разные результаты? Разве [0] => 5% Grapefruit не должно быть [0] => Strong off; [1] => 5% Grapefruit? И [0] => Cafe Milk Tea быть [0] => Coco; [1] => Cafe Milk Tea?

1 Ответ

1 голос
/ 11 января 2012

Ваша функция isStart_entry ищет <title> вместо <list>.Это должно быть закодировано так:

function isStart_entry($line)
{
  return preg_match('/^<list>.*$/', $line);
}
...