Skip to content

Instantly share code, notes, and snippets.

@favrik
Created July 24, 2009 04:10
Show Gist options
  • Save favrik/153831 to your computer and use it in GitHub Desktop.
Save favrik/153831 to your computer and use it in GitHub Desktop.
<?php
/*
Note: some parts based on the Spyc YAML parser at http://code.google.com/p/spyc/
*/
class MorpheusParser {
private $Form = array();
/* Pseudo Global Variables shared by several methods */
private $group_cursor = 0;
private $field_name = '';
private $CURRENT_STATE = 'START';
private function getFile($input) {
if (!empty($input) and file_exists($input)) {
return file($input);
}
}
private function isComment ($line) {
if (!$line) {
return false;
}
if ($line[0] == '#') {
return true;
}
return false;
}
private function isBlankLine($line) {
return $line === '';
}
private function parseAttributes($line) {
$result = array();
$attribs = explode(' ', $line);
foreach ($attribs as $attrib) {
$current = explode('=', $attrib);
$result[array_shift($current)] = array_shift($current);
}
return $result;
}
private function addForm($line) {
$params = explode(' ', $line);
$params_number = count($params);
if ($params_number < 2) {
throw new Exception('"form:" directive requires, at least, one line
with two parameters separated by a space.');
}
$this->Form['layout'] = array_shift($params);
$this->Form['method'] = array_shift($params);
if ($params_number === 3) {
$this->Form['action'] = array_shift($params);
}
}
private function addFormAttributes($line) {
if (!$this->isBlankLine($line)) {
$this->Form['attrib'] = $this->parseAttributes($line);
}
}
private function isAttributeLine($line) {
return strpos($line, '=') !== false;
}
private function isFieldStart($line) {
$pos = strpos($line, ':');
if ($pos !== false and $line !== 'group:' and $line !== 'form:') {
return $pos;
}
return false;
}
private function addGroup($line) {
if (empty($line)) {
throw new Exception('"legend" cannot be empty when adding a group.');
}
$this->Form['groups'] = array();
$this->Form['groups'][$this->group_cursor]['legend'] = $line;
$this->Form['groups'][$this->group_cursor]['fields'] = array();
}
private function addGroupAttributes($line) {
$return = $this->isAttributeLine($line);
if ($return) {
$this->Form['groups'][$this->group_cursor]['attrib'] = $this->parseAttributes($line);
}
return $return;
}
private function setFieldName($line) {
$pos = strpos($line, ':');
$name = substr($line, 0, $pos);
$this->Form['groups'][$this->group_cursor]['fields'][$name]['name'] = $name;
$this->field_name = $name;
}
private function addFieldParams($line) {
$params = explode(' ', $line);
$params_number = count($params);
if ($params_number != 2) {
throw new Exception('"field:" directive requires exactly two parameters: TYPE and LABEL.');
}
$this->Form['groups'][$this->group_cursor]['fields'][$this->field_name]['type'] = array_shift($params);
$this->Form['groups'][$this->group_cursor]['fields'][$this->field_name]['label'] = array_shift($params);
}
private function addFieldValidations($line) {
$params = explode(' ', $line);
$validations = array();
foreach ($params as $validation) {
$validations[] = $validation;
}
$this->Form['groups'][$this->group_cursor]['fields'][$this->field_name]['validations'] = $validations;
}
private function addFieldAttributes($line) {
$return = $this->isAttributeLine($line);
if ($return) {
$this->Form['groups'][$this->group_cursor]['fields'][$this->field_name]['attrib'] = $this->parseAttributes($line);
}
return $return;
}
private function automatonStartCheck($line) {
if ($line == 'form:') {
$this->CURRENT_STATE = 'FORM';
} else if ($line == 'group:') {
$this->CURRENT_STATE = 'GROUP';
} else if ($this->isFieldStart($line)) {
$this->setFieldName($line);
$this->CURRENT_STATE = 'FIELD_PARAMS';
}
}
private function automaton($line) {
switch ($this->CURRENT_STATE) {
case 'START':
$this->automatonStartCheck($line);
break;
case 'FORM':
$this->addForm($line);
$this->CURRENT_STATE = 'FORM_ATTRIBS';
break;
case 'FORM_ATTRIBS':
$this->addFormAttributes($line);
$this->CURRENT_STATE = 'START';
break;
case 'GROUP':
$this->addGroup($line);
$this->CURRENT_STATE = 'GROUP_ATTRIBS';
break;
case 'GROUP_ATTRIBS':
if ($this->addGroupAttributes($line)) {
$this->CURRENT_STATE = 'FIELD';
break;
}
case 'FIELD':
$this->setFieldName($line);
$this->CURRENT_STATE = 'FIELD_PARAMS';
break;
case 'FIELD_PARAMS':
$this->addFieldParams($line);
$this->CURRENT_STATE = 'VALIDATIONS';
break;
case 'VALIDATIONS':
$this->addFieldValidations($line);
$this->CURRENT_STATE = 'FIELD_ATTRIBS';
break;
case 'FIELD_ATTRIBS':
if ($this->addFieldAttributes($line)) {
$this->CURRENT_STATE = 'START';
} else {
$this->automatonStartCheck($line);
}
break;
}
}
private function isDataLine($line) {
return !($this->isComment($line) or $this->isBlankLine($line));
}
private function parse($file) {
$lines = $this->getFile($file);
$lines = array_map('trim', $lines);
for ($i = 0; $i < count($lines); $i++) {
if ($this->isDataLine($lines[$i])) {
$this->automaton($lines[$i]);
}
}
return $this->Form;
}
public static function load($file) {
$parser = new MorpheusParser();
return $parser->parse($file);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment