Skip to content

Instantly share code, notes, and snippets.

@jakubkulhan
Created May 16, 2010 12:01
Show Gist options
  • Save jakubkulhan/402848 to your computer and use it in GitHub Desktop.
Save jakubkulhan/402848 to your computer and use it in GitHub Desktop.
START = ?{
$this->indent = array();
$this->indentstring = "";
return TRUE;
}
EmpL*
b:(blockarray / blockhash)
EmpL*
!.
-> $b
blockhash = EmpL*
SAMEDENT es:blockhashentry
(EOL
EmpL*
SAMEDENT e:blockhashentry -> { $es = array_merge($es, $e); }
)*
-> $es
blockhashentry = k:key ":" S? EOL
EmpL*
INDENT b:(blockhash / blockarray) OUTDENT -> array($k => $b)
/ k:key S? ":" S? v:value S? -> array($k => $v)
blockarray = EmpL*
SAMEDENT es:blockarrayentry
(EOL
EmpL*
SAMEDENT e:blockarrayentry -> { $es = array_merge($es, $e); }
)*
-> $es
blockarrayentry = "-" S? EOL
EmpL*
INDENT b:(blockhash / blockarray) OUTDENT -> array($b)
/ "-" S? v:value S? -> array($v)
value = booleanvalue
/ nullvalue
/ floatvalue
/ integervalue
/ stringvalue
/ inlinearrayvalue
/ objectvalue
/ literalvalue
booleanvalue = ("true" / "TRUE" / "yes" / "YES") -> TRUE
/ ("false" / "FALSE" / "no" / "NO" ) -> FALSE
nullvalue = ("null" / "NULL") -> NULL
integervalue = minus:"-"?
int:("0" / [1-9][0-9]*)
-> intval($minus . $int)
floatvalue = minus:"-"?
int:("0" / [1-9][0-9]*)
"." prec:[0-9]+
([eE] expsign:[+-]? exp:[0-9]+)?
-> floatval($minus . $int . "." . $prec . "e" . $expsign . $exp)
stringvalue = ["]
s:(!["\\] .
/ "\\" e:["\\] -> $e
/ eschar
)*
["]
-> implode("", $s)
/
[']
s:(!['\\] .
/ "\\" e:['\\] -> $e
/ eschar
)*
[']
-> implode("", $s)
eschar = [\\] e:[nrt] -> { $conv = array("n" => "\n", "r" => "\r", "t" => "\t"); return $conv[$e]; }
/ [\\] "x" f:[0-9a-fA-F] s:[0-9a-fA-F] -> { return chr(hexdec($f . $s)); }
literalvalue = l:(![#"',:=@[\]{}()<>] !EOL .)* -> trim($l)
inlinearrayvalue = ("{" Snl? "}" / "[" Snl? "]") -> array()
/ "{" Snl? es:inlinearrayentries Snl? "}" -> $es
/ "[" Snl? es:inlinearrayentries Snl? "]" -> $es
inlinearrayentries = es:inlinearrayentry ?{
if ($es[0] === NULL) { $es = array($es[1]); }
else { $es = array($es[0] => $es[1]); }
return TRUE;
}
(Snl? "," Snl? e:inlinearrayentry -> {
if ($e[0] === NULL) { $es[] = $e[1]; }
else { $es[$e[0]] = $e[1]; }
})*
-> $es
inlinearrayentry = k:(kk:key S? ("=" ">"? / ":") S? -> { return $kk; })?
v:value
-> array($k, $v)
objectvalue = "@" classname:[a-zA-Z0-9\\]+ S?
"(" Snl? es:inlinearrayentries Snl? ")"
-> array("object", $classname, $es)
key = integervalue
/ stringvalue
/ literalvalue
INDENT = i:[ \t]+ ?{
if (strncmp($this->indentstring, $i, $l = strlen($this->indentstring)) === 0) {
array_push($this->indent, substr($i, $l));
$this->indentstring = implode("", $this->indent);
$this->_p -= strlen($i);
return TRUE;
}
return FALSE;
}
SAMEDENT = i:[ \t]* ?$i === $this->indentstring
OUTDENT = ?{
array_pop($this->indent);
$this->indentstring = implode("", $this->indent);
return TRUE;
}
EOL = "\r\n" / "\n" / "\r"
S = ([ \t] / "#" (!EOL .)*)+
Snl = ([ \t\r\n] / "#" (!EOL.)* EOL)+
EmpL = S? EOL
@jakubkulhan
Copy link
Author

Tenhle parser je dosti pomalejší než ten v distribuci Nette. Hlavní problém vidím v tom, že phpeg neuplatňuje na gramatiku žádné optimalizace a že výsledný parser je scannerless (vstupní řetězec se parsuje znak po znaku kódem v PHP), a jelikož práce s řetězci v PHP není zrovna nejrychlejší...

@dg
Copy link

dg commented May 17, 2010

Hmm, parsování znak po znaku je v PHP šílená brzda.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment