You are here

class PARSEENTRIES in Bibliography Module 7.3

Same name and namespace in other branches
  1. 5 bibtexParse/PARSEENTRIES.php \PARSEENTRIES
  2. 6.2 modules/bibtexParse/PARSEENTRIES.php \PARSEENTRIES
  3. 6 bibtexParse/PARSEENTRIES.php \PARSEENTRIES
  4. 7 modules/bibtexParse/PARSEENTRIES.php \PARSEENTRIES
  5. 7.2 modules/bibtexParse/PARSEENTRIES.php \PARSEENTRIES

Hierarchy

Expanded class hierarchy of PARSEENTRIES

File

plugins/biblio_style/bibtex/PARSEENTRIES.php, line 132

View source
class PARSEENTRIES {

  /**
   * @return unknown_type
   */
  function PARSEENTRIES() {
    $this->transtab_latex_unicode = $this
      ->get_transtab_latex_unicode();
    $this->preamble = $this->strings = $this->undefinedStrings = $this->entries = array();
    $this->count = 0;
    $this->fieldExtract = TRUE;
    $this->removeDelimit = TRUE;
    $this->expandMacro = FALSE;
    $this->parseFile = TRUE;
    $this->outsideEntry = TRUE;
    $this->translate_latex = TRUE;
  }

  // Open bib file

  /**
   * @param $file
   * @return none
   */
  function openBib($file) {
    if (!is_file($file)) {
      die;
    }
    ini_set('auto_detect_line_endings', true);
    $this->fid = fopen($file, 'r');
    $this->parseFile = TRUE;
  }

  // Load a bibtex string to parse it
  function loadBibtexString($bibtex_string) {
    if (is_string($bibtex_string)) {

      //$bibtex_string = $this->searchReplaceText($this->transtab_latex_unicode, $bibtex_string, FALSE);
      $this->bibtexString = explode("\n", $bibtex_string);
    }
    else {
      $this->bibtexString = $bibtex_string;
    }
    $this->parseFile = FALSE;
    $this->currentLine = 0;
  }
  function searchReplaceText($searchReplaceActionsArray, $sourceString, $includesSearchPatternDelimiters = FALSE) {
    $searchStrings = array_keys($searchReplaceActionsArray);
    if (!$includesSearchPatternDelimiters) {
      foreach ($searchStrings as $key => $value) {
        $searchStrings[$key] = "/" . $value . "/";

        // add search pattern delimiters
      }
    }
    $replaceStrings = array_values($searchReplaceActionsArray);

    // apply the search & replace actions defined in '$searchReplaceActionsArray' to the text passed in '$sourceString':
    return preg_replace($searchStrings, $replaceStrings, $sourceString);
  }

  // Set strings macro
  function loadStringMacro($macro_array) {
    $this->userStrings = $macro_array;
  }

  // Close bib file
  function closeBib() {
    fclose($this->fid);
  }

  // Get a non-empty line from the bib file or from the bibtexString
  function getLine() {
    if ($this->parseFile) {
      if (!feof($this->fid)) {
        do {
          $line = trim(fgets($this->fid));
        } while (!feof($this->fid) && !$line);
        return $line;
      }
      return FALSE;
    }
    else {
      do {
        $line = array_shift($this->bibtexString);
        $line = trim($line);
        $this->currentLine++;
      } while ($this->bibtexString && !$line);
      return $line;
    }
  }

  // Extract value part of @string field enclosed by double-quotes or braces.
  // The string may be expanded with previously-defined strings
  function extractStringValue($string) {

    // $string contains a end delimiter, remove it
    $string = trim(substr($string, 0, strlen($string) - 1));

    // remove delimiters and expand
    $string = $this
      ->removeDelimitersAndExpand($string);
    return $string;
  }

  // Extract a field
  function fieldSplit($seg) {

    // echo "**** ";print_r($seg);echo "<BR>";
    // handle fields like another-field = {}
    $array = preg_split("/,\\s*([-_.:,a-zA-Z0-9]+)\\s*={1}\\s*/U", $seg, PREG_SPLIT_DELIM_CAPTURE);

    // echo "**** ";print_r($array);echo "<BR>";

    //$array = preg_split("/,\s*(\w+)\s*={1}\s*/U", $seg, PREG_SPLIT_DELIM_CAPTURE);
    if (!array_key_exists(1, $array)) {
      return array(
        $array[0],
        FALSE,
      );
    }
    return array(
      $array[0],
      $array[1],
    );
  }

  // Extract and format fields
  function reduceFields($oldString) {

    // 03/05/2005 G. Gardey. Do not remove all occurences, juste one
    // * correctly parse an entry ended by: somefield = {aValue}}
    $lg = strlen($oldString);
    if ($oldString[$lg - 1] == "}" || $oldString[$lg - 1] == ")" || $oldString[$lg - 1] == ",") {
      $oldString = substr($oldString, 0, $lg - 1);
    }

    // $oldString = rtrim($oldString, "}),");
    $split = preg_split("/=/", $oldString, 2);
    $string = $split[1];
    while ($string) {
      list($entry, $string) = $this
        ->fieldSplit($string);
      $values[] = $entry;
    }
    foreach ($values as $value) {
      $pos = strpos($oldString, $value);
      $oldString = substr_replace($oldString, '', $pos, strlen($value));
    }
    $rev = strrev(trim($oldString));
    if ($rev[0] != ',') {
      $oldString .= ',';
    }
    $keys = preg_split("/=,/", $oldString);

    // 22/08/2004 - Mark Grimshaw
    // I have absolutely no idea why this array_pop is required but it is.  Seems to always be
    // an empty key at the end after the split which causes problems if not removed.
    array_pop($keys);
    foreach ($keys as $key) {
      $value = trim(array_shift($values));
      $rev = strrev($value);

      // remove any dangling ',' left on final field of entry
      if ($rev[0] == ',') {
        $value = rtrim($value, ",");
      }
      if (!$value) {
        continue;
      }

      // 21/08/2004 G.Gardey -> expand macro
      // Don't remove delimiters now needs to know if the value is a string macro
      // $this->entries[$this->count][strtolower(trim($key))] = trim($this->removeDelimiters(trim($value)));
      $key = strtolower(trim($key));
      $value = trim($value);
      $this->entries[$this->count][$key] = $value;
    }

    // echo "**** ";print_r($this->entries[$this->count]);echo "<BR>";
  }

  // Start splitting a bibtex entry into component fields.
  // Store the entry type and citation.
  function fullSplit($entry) {
    $matches = preg_split("/@(.*)[{(](.*),/U", $entry, 2, PREG_SPLIT_DELIM_CAPTURE);
    $this->entries[$this->count]['bibtexEntryType'] = strtolower(trim($matches[1]));

    // sometimes a bibtex entry will have no citation key
    if (preg_match("/=/", $matches[2])) {

      // this is a field
      $matches = preg_split("/@(.*)\\s*[{(](.*)/U", $entry, 2, PREG_SPLIT_DELIM_CAPTURE);
    }

    // print_r($matches); print "<P>";
    $this->entries[$this->count]['bibtexCitation'] = $matches[2];
    $this
      ->reduceFields($matches[3]);
  }

  // Grab a complete bibtex entry
  function parseEntry($entry) {
    set_time_limit(30);

    // reset the script timer to avoid timeouts
    $entry = $this->translate_latex ? $this
      ->searchReplaceText($this->transtab_latex_unicode, $entry, FALSE) : $entry;
    $count = 0;
    $lastLine = FALSE;
    if (preg_match("/@(.*)([{(])/U", preg_quote($entry), $matches)) {
      if (!array_key_exists(1, $matches)) {
        return $lastLine;
      }
      if (preg_match("/string/i", trim($matches[1]))) {
        $this->strings[] = $entry;
      }
      else {
        if (preg_match("/preamble/i", trim($matches[1]))) {
          $this->preamble[] = $entry;
        }
        else {
          if (preg_match("/comment/i", $matches[1])) {
          }
          else {
            if ($this->fieldExtract) {
              $this
                ->fullSplit($entry);
            }
            else {
              $this->entries[$this->count] = $entry;
            }
            $this->count++;
          }
        }
      }
      return $lastLine;
    }
  }

  // Remove delimiters from a string
  function removeDelimiters($string) {
    if ($string && $string[0] == "\"") {
      $string = substr($string, 1);
      $string = substr($string, 0, -1);
    }
    else {
      if ($string && $string[0] == "{") {
        if (strlen($string) > 0 && $string[strlen($string) - 1] == "}") {
          $string = substr($string, 1);
          $string = substr($string, 0, -1);
        }
      }
      else {
        if (!is_numeric($string) && !array_key_exists($string, $this->strings) && array_search($string, $this->undefinedStrings) === FALSE) {
          $this->undefinedStrings[] = $string;

          // Undefined string that is not a year etc.
          return '';
        }
      }
    }
    return $string;
  }

  // This function works like explode('#',$val) but has to take into account whether
  // the character # is part of a string (i.e., is enclosed into "..." or {...} )
  // or defines a string concatenation as in @string{ "x # x" # ss # {xx{x}x} }
  function explodeString($val) {
    $openquote = $bracelevel = $i = $j = 0;
    while ($i < strlen($val)) {
      if ($val[$i] == '"') {
        $openquote = !$openquote;
      }
      elseif ($val[$i] == '{') {
        $bracelevel++;
      }
      elseif ($val[$i] == '}') {
        $bracelevel--;
      }
      elseif ($val[$i] == '#' && !$openquote && !$bracelevel) {
        $strings[] = substr($val, $j, $i - $j);
        $j = $i + 1;
      }
      $i++;
    }
    $strings[] = substr($val, $j);
    return $strings;
  }

  // This function receives a string and a closing delimiter '}' or ')'
  // and looks for the position of the closing delimiter taking into
  // account the following Bibtex rules:
  //  * Inside the braces, there can arbitrarily nested pairs of braces,
  //    but braces must also be balanced inside quotes!
  //  * Inside quotes, to place the " character it is not sufficient
  //    to simply escape with \": Quotes must be placed inside braces.
  function closingDelimiter($val, $delimitEnd) {

    //  echo "####>$delimitEnd $val<BR>";
    $openquote = $bracelevel = $i = $j = 0;
    while ($i < strlen($val)) {

      // a '"' found at brace level 0 defines a value such as "ss{\"o}ss"
      if ($val[$i] == '"' && !$bracelevel) {
        $openquote = !$openquote;
      }
      elseif ($val[$i] == '{') {
        $bracelevel++;
      }
      elseif ($val[$i] == '}') {
        $bracelevel--;
      }
      if ($val[$i] == $delimitEnd && !$openquote && !$bracelevel) {
        return $i;
      }
      $i++;
    }

    // echo "--> $bracelevel, $openquote";
    return 0;
  }

  // Remove enclosures around entry field values.  Additionally, expand macros if flag set.
  function removeDelimitersAndExpand($string, $inpreamble = FALSE) {

    // only expand the macro if flag set, if strings defined and not in preamble
    if (!$this->expandMacro || empty($this->strings) || $inpreamble) {
      $string = $this
        ->removeDelimiters($string);
    }
    else {
      $stringlist = $this
        ->explodeString($string);
      $string = "";
      foreach ($stringlist as $str) {

        // trim the string since usually # is enclosed by spaces
        $str = trim($str);

        // replace the string if macro is already defined
        // strtolower is used since macros are case insensitive
        if (isset($this->strings[strtolower($str)])) {
          $string .= $this->strings[strtolower($str)];
        }
        else {
          $string .= $this
            ->removeDelimiters(trim($str));
        }
      }
    }
    return $string;
  }

  // This function extract entries taking into account how comments are defined in BibTeX.
  // BibTeX splits the file in two areas: inside an entry and outside an entry, the delimitation
  // being indicated by the presence of a @ sign. When this character is met, BibTex expects to
  // find an entry. Before that sign, and after an entry, everything is considered a comment!
  function extractEntries() {
    $inside = $possibleEntryStart = FALSE;
    $entry = "";
    while ($line = $this
      ->getLine()) {
      if ($possibleEntryStart) {
        $line = $possibleEntryStart . $line;
      }
      if (!$inside && strchr($line, "@")) {

        // throw all characters before the '@'
        $line = strstr($line, '@');
        if (!strchr($line, "{") && !strchr($line, "(")) {
          $possibleEntryStart = $line;
        }
        elseif (preg_match("/@.*([{(])/U", preg_quote($line), $matches)) {
          $inside = TRUE;
          if ($matches[1] == '{') {
            $delimitEnd = '}';
          }
          else {
            $delimitEnd = ')';
          }
          $possibleEntryStart = FALSE;
        }
      }
      if ($inside) {
        $entry .= " " . $line;
        if ($j = $this
          ->closingDelimiter($entry, $delimitEnd)) {

          // all characters after the delimiter are thrown but the remaining
          // characters must be kept since they may start the next entry !!!
          $lastLine = substr($entry, $j + 1);
          $entry = substr($entry, 0, $j + 1);

          // Strip excess whitespaces from the entry
          $entry = preg_replace('/\\s\\s+/', ' ', $entry);
          $this
            ->parseEntry($entry);
          $entry = strchr($lastLine, "@");
          if ($entry) {
            $inside = TRUE;
          }
          else {
            $inside = FALSE;
          }
        }
      }
    }
  }

  // Return arrays of entries etc. to the calling process.
  function returnArrays() {

    //   global $transtab_latex_unicode; // defined in 'transtab_latex_unicode.inc.php'
    foreach ($this->preamble as $value) {
      preg_match("/.*?[{(](.*)/", $value, $matches);
      $preamble = substr($matches[1], 0, -1);
      $preambles['bibtexPreamble'] = trim($this
        ->removeDelimitersAndExpand(trim($preamble), TRUE));
    }
    if (isset($preambles)) {
      $this->preamble = $preambles;
    }
    if ($this->fieldExtract) {

      // Next lines must take into account strings defined by previously-defined strings
      $strings = $this->strings;

      // $this->strings is initialized with strings provided by user if they exists
      // it is supposed that there are no substitutions to be made in the user strings, i.e., no #
      $this->strings = isset($this->userStrings) ? $this->userStrings : array();
      foreach ($strings as $value) {

        // changed 21/08/2004 G. Gardey
        // 23/08/2004 Mark G. account for comments on same line as @string - count delimiters in string value
        $value = trim($value);
        $matches = preg_split("/@\\s*string\\s*([{(])/i", $value, 2, PREG_SPLIT_DELIM_CAPTURE);
        $delimit = $matches[1];
        $matches = preg_split("/=/", $matches[2], 2, PREG_SPLIT_DELIM_CAPTURE);

        // macros are case insensitive
        $this->strings[strtolower(trim($matches[0]))] = $this
          ->extractStringValue($matches[1]);
      }
    }

    // changed 21/08/2004 G. Gardey
    // 22/08/2004 Mark Grimshaw - stopped useless looping.
    // removeDelimit and expandMacro have NO effect if !$this->fieldExtract
    if ($this->removeDelimit || $this->expandMacro && $this->fieldExtract) {
      for ($i = 0; $i < count($this->entries); $i++) {
        foreach ($this->entries[$i] as $key => $value) {

          // 02/05/2005 G. Gardey don't expand macro for bibtexCitation
          // and bibtexEntryType
          if ($key != 'bibtexCitation' && $key != 'bibtexEntryType') {
            $this->entries[$i][$key] = trim($this
              ->removeDelimitersAndExpand($this->entries[$i][$key]));
          }
        }
      }
    }

    // EZ: Remove this to be able to use the same instance for parsing several files,
    // e.g., parsing a entry file with its associated abbreviation file
    //    if (empty($this->preamble))
    //      $this->preamble = FALSE;
    //    if (empty($this->strings))
    //      $this->strings = FALSE;
    //    if (empty($this->entries))
    //      $this->entries = FALSE;
    return array(
      $this->preamble,
      $this->strings,
      $this->entries,
      $this->undefinedStrings,
    );
  }
  function &getEntries() {
    if ($this->removeDelimit || $this->expandMacro && $this->fieldExtract) {
      for ($i = 0; $i < count($this->entries); $i++) {
        foreach ($this->entries[$i] as $key => $value) {

          // 02/05/2005 G. Gardey don't expand macro for bibtexCitation
          // and bibtexEntryType
          if ($key != 'bibtexCitation' && $key != 'bibtexEntryType') {
            $this->entries[$i][$key] = trim($this
              ->removeDelimitersAndExpand($this->entries[$i][$key]));
          }
        }
      }
    }
    return $this->entries;
  }

  // Copyright:  Matthias Steffens
  //             This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
  //             Please see the GNU General Public License for more details.
  // File:       ./includes/transtab_latex_unicode.inc.php
  // Created:    10-Aug-06, 23:55
  // Modified:   13-Aug-06, 16:16
  // This is a translation table for best-effort conversion from LaTeX to Unicode entities. It contains a comprehensive list of substitution strings for LaTeX characters,
  // which are used with the 'T1' font encoding. Uses commands from the 'textcomp' package. Unicode characters that can't be matched uniquely are commented out.
  // Adopted from 'transtab' by Markus Kuhn
  // (transtab.utf v1.8 2000-10-12 11:01:28+01 mgk25 Exp); see <http://www.cl.cam.ac.uk/~mgk25/unicode.html> for more info about Unicode and transtab.
  public function get_transtab_latex_unicode() {
    return array(
      '\\$\\\\#\\$' => "#",
      "\\\\%" => "%",
      "\\\\&" => "&",
      "(?<!\\\\)~" => " ",
      "\\{\\\\textexclamdown\\}" => "¡",
      "\\{\\\\textcent\\}" => "¢",
      "\\{\\\\textsterling\\}" => "£",
      "\\{\\\\textyen\\}" => "¥",
      "\\{\\\\textbrokenbar\\}" => "¦",
      "\\{\\\\textsection\\}" => "§",
      "\\{\\\\textasciidieresis\\}" => "¨",
      "\\{\\\\textcopyright\\}" => "©",
      "\\{\\\\textordfeminine\\}" => "ª",
      "\\{\\\\guillemotleft\\}" => "«",
      "\\{\\\\textlnot\\}" => "¬",
      "\\{\\\\textregistered\\}" => "®",
      "\\{\\\\textasciimacron\\}" => "¯",
      "\\{\\\\textdegree\\}" => "°",
      "\\{\\\\textpm\\}" => "±",
      "\\{\\\\texttwosuperior\\}" => "²",
      "\\{\\\\textthreesuperior\\}" => "³",
      "\\{\\\\textasciiacute\\}" => "´",
      "\\{\\\\textmu\\}" => "µ",
      "\\{\\\\textparagraph\\}" => "¶",
      "\\{\\\\textperiodcentered\\}" => "·",
      "\\{\\\\c\\\\ \\}" => "¸",
      "\\{\\\\textonesuperior\\}" => "¹",
      "\\{\\\\textordmasculine\\}" => "º",
      "\\{\\\\guillemotright\\}" => "»",
      "\\{\\\\textonequarter\\}" => "¼",
      "\\{\\\\textonehalf\\}" => "½",
      "\\{\\\\textthreequarters\\}" => "¾",
      "\\{\\\\textquestiondown\\}" => "¿",
      "\\{?\\\\`\\{?A\\}?\\}?" => "À",
      "\\{?\\\\'\\{?A\\}?\\}?" => "Á",
      "\\{?\\\\\\^\\{?A\\}?\\}?" => "Â",
      "\\{?\\\\~\\{?A\\}?\\}?" => "Ã",
      "\\{?\\\\\"\\{?A\\}?\\}?" => "Ä",
      "\\{?\\\\r\\s\\{?A\\}?\\}?" => "Å",
      "\\{?\\\\AE\\}?" => "Æ",
      "\\{?\\\\c\\sC\\}?" => "Ç",
      "\\{?\\\\`\\{?E\\}?\\}?" => "È",
      "\\{?\\\\'\\{?E\\}?\\}?" => "É",
      "\\{?\\\\\\^\\{?E\\}?\\}?" => "Ê",
      "\\{?\\\\\"\\{?E\\}?\\}?" => "Ë",
      "\\{?\\\\`\\{?I\\}?\\}?" => "Ì",
      "\\{?\\\\'\\{?I\\}?\\}?" => "Í",
      "\\{?\\\\\\^\\{?I\\}?\\}?" => "Î",
      "\\{?\\\\\"\\{?I\\}?\\}?" => "Ï",
      "\\{?\\\\DH\\}?" => "Ð",
      "\\{?\\\\~\\{?N\\}?\\}?" => "Ñ",
      "\\{?\\\\`\\{?O\\}?\\}?" => "Ò",
      "\\{?\\\\'\\{?O\\}?\\}?" => "Ó",
      "\\{?\\\\\\^\\{?O\\}?\\}?" => "Ô",
      "\\{?\\\\~\\{?O\\}?\\}?" => "Õ",
      "\\{?\\\\\"\\{?O\\}?\\}?" => "Ö",
      "\\{?\\\\texttimes\\}?" => "×",
      "\\{?\\\\O\\}?" => "Ø",
      "\\{?\\\\`\\{?U\\}?\\}?" => "Ù",
      "\\{?\\\\'\\{?U\\}?\\}?" => "Ú",
      "\\{?\\\\\\^\\{?U\\}?\\}?" => "Û",
      "\\{?\\\\\"\\{?U\\}?\\}?" => "Ü",
      "\\{?\\\\'\\{?Y\\}?\\}?" => "Ý",
      "\\{?\\\\TH\\}?" => "Þ",
      "\\{?\\\\ss\\{?\\}?\\}?" => "ß",
      "\\{?\\\\`\\{?a\\}?\\}?" => "à",
      "\\{?\\\\'\\{?a\\}?\\}?" => "á",
      "\\{?\\\\\\^\\{?a\\}?\\}?" => "â",
      "\\{?\\\\~\\{?a\\}?\\}?" => "ã",
      "\\{?\\\\\"\\{?a\\}?\\}?" => "ä",
      "\\{?\\\\r\\s\\{?a\\}?\\}?" => "å",
      "\\{?\\\\ae\\}?" => "æ",
      "\\{?\\\\c\\{?c\\}?\\}?" => "ç",
      "\\{?\\\\`\\{?e\\}?\\}?" => "è",
      "\\{?\\\\'\\{?e\\}?\\}?" => "é",
      "\\{?\\\\\\^\\{?e\\}?\\}?" => "ê",
      "\\{?\\\\\"\\s?\\{?e\\}?\\}?" => "ë",
      "\\{?\\\\`\\{?i\\}?\\}?" => "ì",
      "\\{?\\\\'\\{?i\\}?\\}?" => "í",
      "\\{?\\\\\\^\\{?i\\}?\\}?" => "î",
      "\\{?\\\\\"\\{?i\\}?\\}?" => "ï",
      "\\{?\\\\dh\\}?" => "ð",
      "\\{?\\\\~\\{?n\\}?\\}?" => "ñ",
      "\\{?\\\\`\\{?o\\}?\\}?" => "ò",
      "\\{?\\\\'\\{?o\\}?\\}?" => "ó",
      "\\{?\\\\\\^\\{?o\\}?\\}?" => "ô",
      "\\{?\\\\~\\{?o\\}?\\}?" => "õ",
      "\\{?\\\\\"\\{?o\\}?\\}?" => "ö",
      "\\{?\\\\textdiv\\}?" => "÷",
      "\\{?\\\\o\\}?" => "ø",
      "\\{?\\\\`\\{?u\\}?\\}?" => "ù",
      "\\{?\\\\'\\{?u\\}?\\}?" => "ú",
      "\\{?\\\\\\^\\{?u\\}?\\}?" => "û",
      "\\{?\\\\\"\\{?u\\}?\\}?" => "ü",
      "\\{?\\\\'\\{?y\\}?\\}?" => "ý",
      "\\{?\\\\th\\}?" => "þ",
      "\\{?\\\\\"\\{?y\\}?\\}?" => "ÿ",
      "\\{?\\\\u\\{?A\\}?\\}?" => "Ă",
      "\\{?\\\\u\\{?a\\}?\\}?" => "ă",
      //  "\\{?\\\\k\\{?A\\}?||}?" => "Ą",
      "\\{?\\\\k\\{?a\\}?\\}?" => "ą",
      "\\{?\\\\'\\{?C\\}?\\}?" => "Ć",
      "\\{?\\\\'\\{?c\\}?\\}?" => "ć",
      "\\{?\\\\v\\{?C\\}?\\}?" => "Č",
      "\\{?\\\\v\\{?c\\}?\\}?" => "č",
      "\\{?\\\\v\\{?c\\}?\\}?" => "č",
      "\\{?\\\\v\\{?D\\}?\\}?" => "Ď",
      "\\{?\\\\v\\{?d\\}?\\}?" => "ď",
      "\\{?\\\\DJ\\}?" => "Đ",
      "\\{?\\\\dj\\}?" => "đ",
      "\\{?\\\\k\\{?E\\}?\\}?" => "Ę",
      "\\{?\\\\k\\{?e\\}?\\}?" => "ę",
      "\\{?\\\\v\\{?E\\}?\\}?" => "Ě",
      "\\{?\\\\v\\{?e\\}?\\}?" => "ě",
      "\\{?\\\\u\\s?\\{?e\\}?\\}?" => "ĕ",
      "\\{?\\\\u\\{?G\\}?\\}?" => "Ğ",
      "\\{?\\\\u\\{?g\\}?\\}?" => "ğ",
      "\\{?\\\\.\\{?g\\}?\\}?" => "ġ",
      "\\{?\\\\.\\{?I\\}?\\}?" => "İ",
      "\\{?\\\\i\\}?" => "ı",
      "\\{?\\\\'\\{?L\\}?\\}?" => "Ĺ",
      //  "\\{?\\\\'\\{?l\\}?||}?" => "ĺ",
      "\\{?\\\\v\\{?L\\}?\\}?" => "Ľ",
      "\\{?\\\\v\\{?l\\}?\\}?" => "ľ",
      "\\{?\\\\L\\}?" => "Ł",
      "\\{?\\\\l\\}?" => "ł",
      "\\{?\\\\'\\{?N\\}?\\}?" => "Ń",
      "\\{?\\\\'\\{?n\\}?\\}?" => "ń",
      "\\{?\\\\v\\{?N\\}?\\}?" => "Ň",
      "\\{?\\\\v\\{?n\\}?\\}?" => "ň",
      "\\{?\\\\NG\\}?" => "Ŋ",
      "\\{?\\\\ng\\}?" => "ŋ",
      "\\{?\\\\H\\{?O\\}?\\}?" => "Ő",
      "\\{?\\\\H\\{?o\\}?\\}?" => "ő",
      "\\{?\\\\OE\\}?" => "Œ",
      "\\{?\\\\oe\\}?" => "œ",
      "\\{?\\\\'\\{?R\\}?\\}?" => "Ŕ",
      "\\{?\\\\'\\{?r\\}?\\}?" => "ŕ",
      "\\{?\\\\v\\{?R\\}?\\}?" => "Ř",
      "\\{?\\\\v\\{?r\\}?\\}?" => "ř",
      "\\{?\\\\'\\{?S\\}?\\}?" => "Ś",
      "\\{?\\\\'\\{?s\\}?\\}?" => "ś",
      "\\{?\\\\c\\{?S\\}?\\}?" => "Ş",
      "\\{?\\\\c\\{?s\\}?\\}?" => "ş",
      "\\{?\\\\v\\{?S\\}?\\}?" => "Š",
      "\\{?\\\\v\\{?s\\}?\\}?" => "š",
      "\\{?\\\\c\\{?T\\}?\\}?" => "Ţ",
      "\\{?\\\\c\\{?t\\}?\\}?" => "ţ",
      "\\{?\\\\v\\{?T\\}?\\}?" => "Ť",
      "\\{?\\\\v\\{?t\\}?\\}?" => "ť",
      "\\{?\\\\r\\{?U\\}?\\}?" => "Ů",
      "\\{?\\\\r\\{?u\\}?\\}?" => "ů",
      "\\{?\\\\H\\{?U\\}?\\}?" => "Ű",
      "\\{?\\\\H\\{?u\\}?\\}?" => "ű",
      "\\{?\\\\\"\\{?Y\\}?\\}?" => "Ÿ",
      "\\{?\\\\'\\{?Z\\}?\\}?" => "Ź",
      "\\{?\\\\'\\{?z\\}?\\}?" => "ź",
      "\\{?\\\\.\\{?Z\\}?\\}?" => "Ż",
      "\\{?\\\\.\\{?z\\}?\\}?" => "ż",
      "\\{?\\\\v\\{?Z\\}?\\}?" => "Ž",
      "\\{?\\\\v\\{?z\\}?\\}?" => "ž",
      "\\{?\\\\textflorin\\}?" => "ƒ",
      "\\{?\\\\textasciicircum\\}?" => "ˆ",
      "\\{?\\\\textacutedbl\\}?" => "˝",
      "\\{?\\\\textendash\\}?|--" => "–",
      "\\{?\\\\textemdash\\}?|---" => "—",
      "\\{?\\\\textbardbl\\}?" => "‖",
      "\\{?\\\\textunderscore\\}?" => "‗",
      "\\{?\\\\textquoteleft\\}?" => "‘",
      "\\{?\\\\textquoteright\\}?" => "’",
      "\\{?\\\\quotesinglbase\\}?" => "‚",
      "\\{?\\\\textquotedblleft\\}?" => "“",
      "\\{?\\\\textquotedblright\\}?" => "”",
      "\\{?\\\\quotedblbase\\}?" => "„",
      "\\{?\\\\textdagger\\}?" => "†",
      "\\{?\\\\textdaggerdbl\\}?" => "‡",
      "\\{?\\\\textbullet\\}?" => "•",
      "\\{?\\\\textellipsis\\}?" => "…",
      "\\{?\\\\textperthousand\\}?" => "‰",
      "\\{?\\\\guilsinglleft\\}?" => "‹",
      "\\{?\\\\guilsinglright\\}?" => "›",
      "\\{?\\\\textfractionsolidus\\}?" => "⁄",
      '\\$\\^\\{0\\}\\$' => "⁰",
      '\\$\\^\\{4\\}\\$' => "⁴",
      '\\$\\^\\{5\\}\\$' => "⁵",
      '\\$\\^\\{6\\}\\$' => "⁶",
      '\\$\\^\\{7\\}\\$' => "⁷",
      '\\$\\^\\{8\\}\\$' => "⁸",
      '\\$\\^\\{9\\}\\$' => "⁹",
      '\\$\\^\\{+\\}\\$' => "⁺",
      '\\$\\^\\{-\\}\\$' => "⁻",
      '\\$\\^\\{=\\}\\$' => "⁼",
      '\\$\\^\\{n\\}\\$' => "ⁿ",
      '\\$_\\{0\\}\\$' => "₀",
      '\\$_\\{1\\}\\$' => "₁",
      '\\$_\\{2\\}\\$' => "₂",
      '\\$_\\{3\\}\\$' => "₃",
      '\\$_\\{4\\}\\$' => "₄",
      '\\$_\\{5\\}\\$' => "₅",
      '\\$_\\{6\\}\\$' => "₆",
      '\\$_\\{7\\}\\$' => "₇",
      '\\$_\\{8\\}\\$' => "₈",
      '\\$_\\{9\\}\\$' => "₉",
      '\\$_\\{+\\}\\$' => "₊",
      '\\$_\\{-\\}\\$' => "₋",
      '\\$_\\{=\\}\\$' => "₌",
      "\\{?\\\\texteuro\\}?" => "€",
      "\\{?\\\\textcelsius\\}?" => "℃",
      "\\{?\\\\textnumero\\}?" => "№",
      "\\{?\\\\textcircledP\\}?" => "℗",
      "\\{?\\\\textservicemark\\}?" => "℠",
      "\\{?\\\\texttrademark\\}?" => "™",
      "\\{?\\\\textohm\\}?" => "Ω",
      "\\{?\\\\textestimated\\}?" => "℮",
      "\\{?\\\\textleftarrow\\}?" => "←",
      "\\{?\\\\textuparrow\\}?" => "↑",
      "\\{?\\\\textrightarrow\\}?" => "→",
      "\\{?\\\\textdownarrow\\}?" => "↓",
      '\\$\\\\infty\\$' => "∞",
      "\\{?\\\\textlangle\\}?" => "〈",
      "\\{?\\\\textrangle\\}?" => "〉",
      "\\{?\\\\textvisiblespace\\}?" => "␣",
      "\\{?\\\\textopenbullet\\}?" => "◦",
      "\\{?\\\\Delta\\}?" => "Δ",
      "\\{?\\\\iota\\}?" => "ι",
      "\\{?\\\\omicron\\}?" => "ο",
      "\\{?\\\\mu\\}?" => "μ",
      "\\{?\\\\eta\\}?" => "η",
      "\\{?\\\\delta\\}?" => "δ",
      "\\{?\\\\varsigma\\}?" => "ς",
      "\\{?\\\\Sigma\\}?" => "Σ",
      "\\{?\\\\pi\\}?" => "π",
      "\\{?\\\\nu\\}?" => "ν",
      "\\{?\\\\epsilon\\}?" => "ε",
      "\\{?\\\\lambda\\}?" => "λ",
      "\\{?\\\\=\\{?o\\}?\\}?" => "ō",
    );
  }

}

Members