Parse a Comment Line

@param string $line
@param array $lineBreaks
@return Comment
345053
protected function parseCommentLine($line, $lineBreaks)
    {
        $comment = new Comment();
        $comment->setText($line)
                ->setLineBreaks($lineBreaks);

        return $comment;
    }
964998
def comment_lines(lines):
    """"""
    ret = []
    for line in lines:
        ws_prefix, rest, ignore = RE_LINE_SPLITTER_COMMENT.match(line).groups()
        ret.append(ws_prefix + '#' + rest)
    return ''.join(ret)
620968
public function parse($line)
    {
        $elements = [];

        // 1. remove braces
        $line = \str_replace(['{', '}'], '', $line);

        // 2. extract elements
        $elements = $this->extractElements($line);

        // 3. remove quotes
        $iterator = function($element)
        {
            return \str_replace(['\'', '"'], '', $element);
        };

        return \array_map($iterator, $elements);
    }
647176
private function parseFootnote(array $lines, array $value)
    {
        list($space, $note) = $value;
        $index = array_search($note, $this->_footnotes);
        if (false !== $index) {
            $lines[0] = preg_replace("/^\[\^((?:[^\]]|\\]|\\[)+?)\]:/", '', $lines[0]);
            $this->_footnotes[$index] = $lines;
        }
        return '';
    }
1165533
protected function parseDirectiveLine($line, \SplFileObject $file, $lineBreaks)
    {
        $directive = new Directive();

        $args = $this->directiveRegex($line);
        $name = array_shift($args);

        if ($name === null) {
            $lineNum = $file->key();
            throw new SyntaxException($lineNum, $line, "Could not parse the name of the directive");
        }

        $directive->setName($name)
                  ->setArguments($args)
                  ->setLineBreaks($lineBreaks);

        return $directive;
    }
1028686
private function isComment($line)
    {
        // if it's an empty line you might as well skip it
        if (empty($line)) return true;

        $is_comment = false;

        foreach ($this->_comment_character_list as $comment_char) {
            $line = trim($line);
            if (strpos($line, $comment_char) !== false && strpos($line, $comment_char) <= 3) {
                $is_comment = true;
                break;
            }
        }

        return $is_comment;
    }
622283
private function parseQuote(array $lines, $value, $start)
    {
        foreach ($lines as &$line) {
            $line = preg_replace("/^\s*> ?/", '', $line);
        }
        $str = implode("\n", $lines);
        return preg_match("/^\s*$/", $str) ? '' : '<blockquote>' . $this->parse($str, true, $start) . '</blockquote>';
    }
980592
protected function parseInfo($lines) {
    $result = array('videoStreams' => 0, 'audioStreams' => 0);
    foreach ($lines as $line) {
      if (preg_match('/Duration:\s+(\d\d):(\d\d):(\d\d\.\d+)/', $line, $m)) {
        $result['duration'] = $m[1] * 3600 + $m[2] * 60 + $m[3];
      } else if (preg_match('/\s+Stream #(\d)+.*$/', $line, $sm)) {
        if (strpos($line, 'Video:')) {
          $result['videoStreams']++;
          $words = preg_split('/,?\s+/', trim($line));
          for ($i = 0; $i < count($words); $i++) {
            if (preg_match('/(\d+)x(\d+)/', $words[$i], $m)) {
              $result['width'] = $m[1];
              $result['height'] = $m[2];
            }
          }
        } else if (strpos($line, 'Audio:')) {
          $result['audioStreams']++;
        }
      }
    }
    return $result;
  }
857197
private function parseAnnotation($line) {
		// Let's get the annotation text
		preg_match("/^[@]([a-zA-Z][a-zA-Z0-9]*)(.*)/", $line, $values);
		
		$annotationClass = isset($values[1])?$values[1]:null;
		$annotationParams = trim(isset($values[2])?$values[2]:null);
		
		$this->annotationsArrayAsString[$annotationClass][] = $annotationParams;		
	}
154931
protected function parseListLine($line)
    {
        $depth = 0;
        for ($i=0; $i<strlen($line); $i++) {
            $char = $line[$i];

            if ($char == ' ') {
                $depth++;
            } else if ($char == "\t") {
                $depth += 2;
            } else {
                break;
            }
        }

        if (preg_match('/^((\*|\-)|([\d#]+)\.) (.+)$/', trim($line), $match)) {
            return array(
                'prefix' => $line[$i],
                'ordered' => ($line[$i] == '*' || $line[$i] == '-') ? false : true,
                'depth' => $depth,
                'text' => array($match[4])
            );
        }

        return false;
    }
132544
protected function parseTag($line)
    {
        $tagAndValue = preg_split('/\\s/', $line, 2);
        $tag = substr($tagAndValue[0], 1);
        if (count($tagAndValue) > 1) {
            $this->tags[$tag][] = trim($tagAndValue[1]);
        } else {
            $this->tags[$tag] = [];
        }
    }
1055429
public function parse($line)
    {
        if (!preg_match($this->pcreFormat, $line, $matches)) {
            throw new FormatException($line);
        }

        $entry = $this->createEntry();

        foreach (array_filter(array_keys($matches), 'is_string') as $key) {
            if ('time' === $key && true !== $stamp = strtotime($matches[$key])) {
                $entry->stamp = $stamp;
            }

            $entry->{$key} = $matches[$key];
        }

        return $entry;
    }
512855
private function minify($css, $linebreak_pos)
    {
        // strings are safe, now wrestle the comments
        for ($i = 0, $max = count($this->comments); $i < $max; $i++) {

            $token = $this->comments[$i];
            $placeholder = '/' . self::COMMENT . $i . '___/';

            // ! in the first position of the comment means preserve
            // so push to the preserved tokens keeping the !
            if (substr($token, 0, 1) === '!') {
                $this->preserved_tokens[] = $token;
                $token_tring = self::TOKEN . (count($this->preserved_tokens) - 1) . '___';
                $css = preg_replace($placeholder, $token_tring, $css, 1);
                // Preserve new lines for /*! important comments
                $css = preg_replace('/\s*[\n\r\f]+\s*(\/\*'. $token_tring .')/S', self::NL.'$1', $css);
                $css = preg_replace('/('. $token_tring .'\*\/)\s*[\n\r\f]+\s*/S', '$1'.self::NL, $css);
                continue;
            }

            // \ in the last position looks like hack for Mac/IE5
            // shorten that to /*\*/ and the next one to /**/
            if (substr($token, (strlen($token) - 1), 1) === '\\') {
                $this->preserved_tokens[] = '\\';
                $css = preg_replace($placeholder,  self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
                $i = $i + 1; // attn: advancing the loop
                $this->preserved_tokens[] = '';
                $css = preg_replace('/' . self::COMMENT . $i . '___/',  self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
                continue;
            }

            // keep empty comments after child selectors (IE7 hack)
            // e.g. html >/**/ body
            if (strlen($token) === 0) {
                $start_index = $this->index_of($css, $this->str_slice($placeholder, 1, -1));
                if ($start_index > 2) {
                    if (substr($css, $start_index - 3, 1) === '>') {
                        $this->preserved_tokens[] = '';
                        $css = preg_replace($placeholder,  self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
                    }
                }
            }

            // in all other cases kill the comment
            $css = preg_replace('/\/\*' . $this->str_slice($placeholder, 1, -1) . '\*\//', '', $css, 1);
        }


        // Normalize all whitespace strings to single spaces. Easier to work with that way.
        $css = preg_replace('/\s+/', ' ', $css);

        // Shorten & preserve calculations calc(...) since spaces are important
        $css = preg_replace_callback('/calc(\((?:[^\(\)]+|(?1))*\))/i', array($this, 'replace_calc'), $css);

        // Replace positive sign from numbers preceded by : or a white-space before the leading space is removed
        // +1.2em to 1.2em, +.8px to .8px, +2% to 2%
        $css = preg_replace('/((?<!\\\\)\:|\s)\+(\.?\d+)/S', '$1$2', $css);

        // Remove leading zeros from integer and float numbers preceded by : or a white-space
        // 000.6 to .6, -0.8 to -.8, 0050 to 50, -01.05 to -1.05
        $css = preg_replace('/((?<!\\\\)\:|\s)(\-?)0+(\.?\d+)/S', '$1$2$3', $css);

        // Remove trailing zeros from float numbers preceded by : or a white-space
        // -6.0100em to -6.01em, .0100 to .01, 1.200px to 1.2px
        $css = preg_replace('/((?<!\\\\)\:|\s)(\-?)(\d?\.\d+?)0+([^\d])/S', '$1$2$3$4', $css);

        // Remove trailing .0 -> -9.0 to -9
        $css = preg_replace('/((?<!\\\\)\:|\s)(\-?\d+)\.0([^\d])/S', '$1$2$3', $css);

        // Replace 0 length numbers with 0
        $css = preg_replace('/((?<!\\\\)\:|\s)\-?\.?0+([^\d])/S', '${1}0$2', $css);

        // Remove the spaces before the things that should not have spaces before them.
        // But, be careful not to turn "p :link {...}" into "p:link{...}"
        // Swap out any pseudo-class colons with the token, and then swap back.
        $css = preg_replace_callback('/(?:^|\})(?:(?:[^\{\:])+\:)+(?:[^\{]*\{)/', array($this, 'replace_colon'), $css);
        $css = preg_replace('/\s+([\!\{\}\;\:\>\+\(\)\]\~\=,])/', '$1', $css);
        $css = preg_replace('/' . self::CLASSCOLON . '/', ':', $css);

        // retain space for special IE6 cases
        $css = preg_replace('/\:first\-(line|letter)(\{|,)/i', ':first-$1 $2', $css);

        // no space after the end of a preserved comment
        $css = preg_replace('/\*\/ /', '*/', $css);

        // Put the space back in some cases, to support stuff like
        // @media screen and (-webkit-min-device-pixel-ratio:0){
        $css = preg_replace('/\band\(/i', 'and (', $css);

        // Remove the spaces after the things that should not have spaces after them.
        $css = preg_replace('/([\!\{\}\:;\>\+\(\[\~\=,])\s+/S', '$1', $css);

        // remove unnecessary semicolons
        $css = preg_replace('/;+\}/', '}', $css);

        // Fix for issue: #2528146
        // Restore semicolon if the last property is prefixed with a `*` (lte IE7 hack)
        // to avoid issues on Symbian S60 3.x browsers.
        $css = preg_replace('/(\*[a-z0-9\-]+\s*\:[^;\}]+)(\})/', '$1;$2', $css);

        // Replace 0 length units 0(px,em,%) with 0.
        $css = preg_replace('/((?<!\\\\)\:|\s)\-?0(?:em|ex|ch|rem|vw|vh|vm|vmin|cm|mm|in|px|pt|pc|%)/iS', '${1}0', $css);

        // Replace 0 0; or 0 0 0; or 0 0 0 0; with 0.
        $css = preg_replace('/\:0(?: 0){1,3}(;|\})/', ':0$1', $css);

        // Fix for issue: #2528142
        // Replace text-shadow:0; with text-shadow:0 0 0;
        $css = preg_replace_callback(
                   '/(text-shadow\:0)(;|\})/i',
                   function($m) {
                       return strtolower($m[1] . ' 0 0' . $m[2]);
                   },
                   $css
               );

        // Replace background-position:0; with background-position:0 0;
        // same for transform-origin
        $css = preg_replace_callback(
                   '/(background\-position|(?:webkit|moz|o|ms|)\-?transform\-origin)\:0(;|\})/iS',
                   function($m) {
                       return strtolower($m[1] . ':0 0' . $m[2]);
                   },
                   $css
               );

        // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space)
        // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space)
        // This makes it more likely that it'll get further compressed in the next step.
        $css = preg_replace_callback('/rgb\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'rgb_to_hex'), $css);
        $css = preg_replace_callback('/hsl\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'hsl_to_hex'), $css);

        // Shorten colors from #AABBCC to #ABC or short color name.
        $css = $this->compress_hex_colors($css);

        // border: none to border:0, outline: none to outline:0
        $css = preg_replace_callback(
                   '/(border\-?(?:top|right|bottom|left|)|outline)\:none(;|\})/iS',
                   function($m) {
                       return strtolower($m[1] . ':0' . $m[2]);
                   },
                   $css
               );

        // shorter opacity IE filter
        $css = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $css);

        // Remove empty rules.
        $css = preg_replace('/[^\};\{\/]+\{\}/S', '', $css);

        // Some source control tools don't like it when files containing lines longer
        // than, say 8000 characters, are checked in. The linebreak option is used in
        // that case to split long lines after a specific column.
        if ($linebreak_pos !== FALSE && (int) $linebreak_pos >= 0) {
            $linebreak_pos = (int) $linebreak_pos;
            $start_index = $i = 0;
            while ($i < strlen($css)) {
                $i++;
                if ($css[$i - 1] === '}' && $i - $start_index > $linebreak_pos) {
                    $css = $this->str_slice($css, 0, $i) . "\n" . $this->str_slice($css, $i);
                    $start_index = $i;
                }
            }
        }

        // Replace multiple semi-colons in a row by a single one
        // See SF bug #1980989
        $css = preg_replace('/;;+/', ';', $css);

        // Restore new lines for /*! important comments
        $css = preg_replace('/'. self::NL .'/', "\n", $css);

        // restore preserved comments and strings
        for ($i = 0, $max = count($this->preserved_tokens); $i < $max; $i++) {
            $css = preg_replace('/' . self::TOKEN . $i . '___/', $this->preserved_tokens[$i], $css, 1);
        }

        // Trim the final string (for any leading or trailing white spaces)
        return trim($css);
    }
352280
private function parseLine($line)
    {
        if (($pair = $this->generateRulePair($line, array_keys(self::TOP_LEVEL_DIRECTIVES))) !== false) {
            return $this->handler->{self::TOP_LEVEL_DIRECTIVES[$pair[0]]}->add($pair[1]);
        }
1067753
private static function parseOneTemplateLine($line)
    {
        $line = trim($line);

        if (!$line) {
            return [];
        }

        $regex = '#\{\{(.*?)\}\}#';

        preg_match_all($regex, $line, $matches);

        $matched = array_map(function ($v) {
            return trim($v, '\'"{}');
        }, $matches[1]);

        return $matched;
    }
833651
private function parse($docComment) {
		$lines = self::getDocLinesFromComment($docComment);
		
		// First, let's go to the first Annotation.
		// Anything before is the pure comment.
		$annotationLines = array();
		
		$oneAnnotationFound = false;
		// Is the line an annotation? Let's test this with a regexp.
		foreach ($lines as $line) {
			if (preg_match("/^[@][a-zA-Z]/", $line) === 0) {
				if ($oneAnnotationFound == false) {
					$this->comment .= $line."\n";
				}
			} else {
				$this->parseAnnotation($line);
				$oneAnnotationFound = true;
			}
		}
	}
975908
public function parseLines(array $lines)
    {
        $config = new SiteConfig();

        foreach ($lines as $line) {
            $line = trim($line);

            // skip comments, empty lines
            if ('' === $line || '#' === $line[0]) {
                continue;
            }

            // get command
            $command = explode(':', $line, 2);
            // if there's no colon ':', skip this line
            if (2 !== \count($command)) {
                continue;
            }

            $val = trim($command[1]);
            $command = trim($command[0]);
            if ('' === $command || '' === $val) {
                continue;
            }

            // check for commands where we accept multiple statements
            if (\in_array($command, ['title', 'body', 'strip', 'strip_id_or_class', 'strip_image_src', 'single_page_link', 'next_page_link', 'test_url', 'find_string', 'replace_string', 'login_extra_fields', 'native_ad_clue', 'date', 'author', 'strip_attr'], true)) {
                array_push($config->$command, $val);
            // check for single statement commands that evaluate to true or false
            } elseif (\in_array($command, ['tidy', 'prune', 'autodetect_on_failure', 'requires_login', 'skip_json_ld'], true)) {
                $config->$command = ('yes' === $val || 'true' === $val);
            // check for single statement commands stored as strings
            } elseif (\in_array($command, ['parser', 'login_username_field', 'login_password_field', 'not_logged_in_xpath', 'login_uri', 'src_lazy_load_attr'], true)) {
                $config->$command = $val;
            // check for replace_string(find): replace
            } elseif ((')' === substr($command, -1)) && preg_match('!^([a-z0-9_]+)\((.*?)\)$!i', $command, $match) && 'replace_string' === $match[1]) {
                array_push($config->find_string, $match[2]);
                array_push($config->replace_string, $val);
            } elseif ((')' === substr($command, -1)) && preg_match('!^([a-z0-9_]+)\(([a-z0-9_-]+)\)$!i', $command, $match) && 'http_header' === $match[1] && \in_array(strtolower($match[2]), ['user-agent', 'referer', 'cookie', 'accept'], true)) {
                $config->http_header[strtolower(trim($match[2]))] = $val;
            // special treatment for if_page_contains
            } elseif (\in_array($command, ['if_page_contains'], true)) {
                $this->handleIfPageContainsCondition($config, $val);
            }
        }

        return $config;
    }