public static function validate_regex($regex, $element)
 {
     if (is_string($regex) && @get_class($element) == CRAYON_ELEMENT_CLASS) {
         // If the (?alt) tag has been used, insert the file into the regex
         $file = self::regex_match('#\\(\\?alt:(.+?)\\)#', $regex);
         if (count($file) == 2) {
             // Element 0 has full match, 1 has captured groups
             for ($i = 0; $i < count($file[1]); $i++) {
                 $file_lines = CrayonUtil::lines(dirname($element->path()) . crayon_s() . $file[1][$i], 'rcwh');
                 if ($file_lines !== FALSE) {
                     $file_lines = implode('|', $file_lines);
                     // If any spaces exist, treat them as whitespace
                     $file_lines = preg_replace('#[ \\t]+#msi', '\\s+', $file_lines);
                     $regex = str_replace($file[0][$i], "(?:{$file_lines})", $regex);
                 } else {
                     CrayonLog::syslog("Parsing of '{$element->path()}' failed, an (?alt) tag failed for the element '{$element->name()}'");
                     return FALSE;
                 }
             }
         }
         // If the (?default:element) function is used, replace the regex with the default, if exists
         $def = self::regex_match('#\\(\\?default(?:\\:(\\w+))?\\)#', $regex);
         if (count($def) == 2) {
             // Load default language
             $default = CrayonResources::langs()->get(CrayonLangs::DEFAULT_LANG);
             // If default has not been loaded, we can't use it, skip the element
             if (!$default) {
                 CrayonLog::syslog("Could not use default regex in the element '{$element->name()}' in '{$element->path()}'");
                 return FALSE;
             }
             for ($i = 0; $i < count($def[1]); $i++) {
                 // If an element has been provided
                 $element_name = !empty($def[1][$i]) ? $def[1][$i] : $element->name();
                 if (($default_element = $default->element($element_name)) != FALSE) {
                     $regex = str_replace($def[0][$i], '(?:' . $default_element->regex() . ')', $regex);
                 } else {
                     CrayonLog::syslog("The language at '{$element->path()}' referred to the Default Language regex for element '{$element->name()}', which did not exist.");
                     return FALSE;
                 }
             }
         }
         // If the (?html) tag is used, escape characters in html (<, > and &)
         $html = self::regex_match('#\\(\\?html:(.+?)\\)#', $regex);
         if (count($html) == 2) {
             for ($i = 0; $i < count($html[1]); $i++) {
                 $regex = str_replace($html[0][$i], htmlentities($html[1][$i]), $regex);
             }
         }
         // Ensure all parenthesis are atomic to avoid conflicting with element matches
         $regex = CrayonUtil::esc_atomic($regex);
         // Escape #, this is our delimiter
         $regex = CrayonUtil::esc_hash($regex);
         // Test if regex is valid
         if (@preg_match("#{$regex}#", '') === FALSE) {
             CrayonLog::syslog("The regex for the element '{$element->name()}' in '{$element->path()}' is not valid.");
             return FALSE;
         }
         return $regex;
     } else {
         return '';
     }
 }
 private function load_attr_file($path)
 {
     if (($lines = CrayonUtil::lines($path, 'lwc')) !== FALSE) {
         $attributes = array();
         // key = language id, value = array of attr
         foreach ($lines as $line) {
             preg_match('#^[\\t ]*([^\\r\\n\\t ]+)[\\t ]+([^\\r\\n]+)#', $line, $matches);
             if (count($matches) == 3 && ($lang = $this->get($matches[1]))) {
                 // If the langauges of the attribute exists, return it in an array
                 // TODO merge instead of replace key?
                 $attributes[$matches[1]] = explode(' ', $matches[2]);
             }
         }
         return $attributes;
     } else {
         CrayonLog::syslog('Could not load attr file: ' . $path);
         return FALSE;
     }
 }