Last active
August 31, 2017 18:46
-
-
Save haskellcamargo/8d73d4c7a19f45daa614 to your computer and use it in GitHub Desktop.
Frankenstein - TypeScript Preprocessor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function parse($file) | |
{ | |
$result_stack = []; | |
$tokens = token_get_all("<?php " . file_get_contents($file)); | |
for ($i = 0, $l = sizeof($tokens); $i < $l; $i++) { | |
// T_OPEN | |
if (is_open($tokens[$i])) { | |
// Expect whitespace | |
if (token_at(T_WHITESPACE, ++$i, $tokens)) { | |
// Expect simple string | |
if (token_at(T_CONSTANT_ENCAPSED_STRING, ++$i, $tokens)) { | |
$reference = codegen_open(token_val($tokens[$i])); | |
// Expect semicolon | |
if (token_at(";", ++$i, $tokens)) { | |
$result_stack[] = $reference; | |
} else { | |
throw new Exception("Expecting semicolon in `open`."); | |
} | |
} else { | |
throw new Exception("Excepting filename in `open`."); | |
} | |
} else { | |
throw new Exception("Expecting whitespace after `open`."); | |
} | |
// T_LAMBDA | |
} elseif (is_lambda($tokens[$i])) { | |
$result_stack[] = codegen_lambda(); | |
// T_LET | |
} elseif (is_let($tokens[$i])) { | |
$result_stack[] = codegen_let(); | |
// T_THIS | |
} elseif (is_this($tokens[$i])) { | |
$result_stack[] = codegen_this(); | |
// T_TYPESIG | |
} elseif (is_typesig($tokens[$i])) { | |
$result_stack[] = codegen_typesig(); | |
} else { | |
$result_stack[] = $tokens[$i]; | |
} | |
} | |
echo translate_to_source($result_stack); | |
} | |
parse($argv[1]); | |
function codegen_typesig() | |
{ | |
return make_token(":"); | |
} | |
function codegen_this() | |
{ | |
return make_token("this."); | |
} | |
function codegen_let() | |
{ | |
return make_token("var"); | |
} | |
function codegen_lambda() | |
{ | |
return make_token("() =>"); | |
} | |
function codegen_open($filename) | |
{ | |
return make_token("/// <reference path={$filename} />", | |
T_CONSTANT_ENCAPSED_STRING); | |
} | |
function token_at($token, $pos, &$stack) | |
{ | |
return is_string($stack[$pos]) | |
? $stack[$pos] === $token | |
: $stack[$pos][0] === $token; | |
} | |
function is_typesig($combinator) | |
{ | |
return $combinator[0] === T_PAAMAYIM_NEKUDOTAYIM && $combinator[1] === "::"; | |
} | |
function is_this($combinator) | |
{ | |
return $combinator === "@"; | |
} | |
function is_open($combinator) | |
{ | |
return $combinator[0] === T_STRING && $combinator[1] === "open"; | |
} | |
function is_let($combinator) | |
{ | |
return $combinator[0] === T_STRING && $combinator[1] === "let"; | |
} | |
function is_lambda($combinator) | |
{ | |
return $combinator[0] === T_STRING && $combinator[1] === "λ"; | |
} | |
function make_token($value, $key = null) | |
{ | |
return isset($key) | |
? [$key, $value, 1] | |
: $value; // Literal | |
} | |
function token_val($token) | |
{ | |
return is_string($token) | |
? $token | |
: $token[1]; | |
} | |
function translate_to_source($stack) | |
{ | |
$source = []; | |
for ($i = 1, $l = sizeof($stack); $i < $l; $i++) { | |
if (is_string($stack[$i])) { | |
$source[] = $stack[$i]; | |
} else { | |
$source[] = $stack[$i][1]; | |
} | |
} | |
return implode("", $source); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment