Simple interpreter code in PHP.
- Compatible with php 5 and later
- Build your own simple language (words and functions)
- Plugins system
- Begin with a few examples: basic and logo plugins
- More plugins and repository coming soon and based on Cody (template system...)
This software is distributed under the GPLv3 licence. Please read LICENSE for information on the software availability and distribution.
Just copy or sync this repository. Two ways to load Cody class and his plugins:
1- Load the config.php file
require_once("config.php");
In the config file you can change libray path if you want:
define("C_PATH_LIB", "path_of_cody_class_and_plugins_files");
2- Place php files where you want, but put these 2 lines of code:
require_once("mypath/cl_cody.php");
define('C_CODY_DIR_PLUGINS', "path_of_plugins_files"); // optional, directory "plugin" by default
Here are 3 examples using Cody with different languages (plugins in this repository):
1- Basic plugin
require_once('config.php');
$code = '
print "Table of Square, Sin<br>"
let $num = rnd(2,10)
print $num, "values<br>"
for $i=1 to $num gosub "calc" next
end
label calc
print $i, "-->", $i*$i, "-->", sin($i)
return
'
$cody = new cl_cody();
$cody->plugin_install('basic,math');
$cody->cy_interpret($code);
2- Preproc plugin
require_once('config.php');
$code = '
#define myvar 45
#print "Print a simple text"
#code "microbasic" "print 100+255"
#code "basic"
<<<BASIC
let $a=4
let $b=5
$myvar = $myvar + 100.5
print "a+b=", $a+$b
BASIC
#print
<<<TXT
Ceci est un texte <b>html</b><br>
TXT
#print "Myvar is now equal to ", myvar'
$cody = new cl_cody();
$cody->plugin_install('preproc');
$cody->cy_interpret($code);
3- Logo plugin
require_once('config.php');
$code = 'pour carre avance 90 droite 90 avance 90 droite 90 avance 90 droite 90 avance 90 droite 90 fin
pour rectangle avance 90 droite 90 avance 50 droite 90 avance 90 droite 90 avance 50 droite 90 fin
pour plcarre repete 36 (carre droite 10) fin
pour cercle dans X=36 dans Y=5 repete X (droite 360/X avance Y) fin
pour rosace
couleur 255, 255, 0
dans X = 36
dans Y = 5
dans C = 0
repete X (
dans C = C + 10
couleur 255, 255 - C, C
droite 360/X
repete X (
droite 360/X
avance Y
))
fin
ecris "Test rosace..."
rosace'
$cody = new cl_cody();
$cody->plugin_install('logo');
$cody->cy_interpret($code);
- See plugins in the repository. There are a few interesting cases using Cody class.
- See the wiki to have more tips and documentations.
The first difficult thing is to know how to implement the lexical of the language.
Cody is not an advanced tool for that. It uses only regex to cut your code into interpretable tokens, and can only interpret classical expression like that: 12+4*x-(3+y)
Luckily Cody comes with a default lexical rule like Basic. It is also easily to begin writing his own plugin. A plugin should be written like that:
class cl_cody_mytinylanguage {
function onInstall() {
return array(
// True if this plugin control all others
'main' => true,
// List of words corresponding to your functions
'func' => array('rnd'),
// List of words corresponding to your statements
'word' => array(';', ':', '$', 'if', 'end', 'print', 'let')
);
}
// Called when interpreter found a word corresponding to an existing function
function onFunction($args, $f) {
switch($f) {
case 'mid': return substr($args[0], $args[1], $args[2]);
}
}
// Called when interpreter found a word corresponding to the beginning of a statement
function onStatement($w) {
// In order to call internal functions or variables of Cody Class (parent)
$obj = &$this->PARENT;
switch($w) {
// No effect. Move one token forward.
case ';': case ':':
$obj->cy_nextTok();
break;
case 'if':
// cy_getArgs is used to control and get the right tokens or expressions
$args = $obj->cy_getArgs('(', C_CODY_GETBEXPR, ')', 'then');
$b = $args[1]; // Result of the test expression in the "if" statement
while ($obj->look && $obj->look != 'endif') {
// Look around until the end of the "if" statement
if ($obj->look == 'else' && $obj->cy_nextTok()) $b = !$b;
else if ($b) {
// Interpret the code in the "if" or "else" statement
$w = $obj->cy_statement($obj->look);
}
// This code haven't to be interpret, so move forward
else $obj->cy_nextTok();
}
$obj->cy_nextTok();
break;
// Stop the interpreter
case 'end': return C_CODY_CODE_STOP;
case 'print':
// Get all expressions results (separated with a coma)
echo implode('', $obj->cy_getArgs(C_CODY_GETALLEXPR, '', ',', ''));
break;
case '$': $obj->pc--; // Move back (one token)
case 'let':
$args = $obj->cy_getArgs(C_CODY_GETID, '=', C_CODY_GETEXPR);
// Set a variable
$obj->cy_setVar($args[0], $args[2]);
break;
}
}
}
And to call your plugin:
require_once('config.php');
$cody = new cl_cody();
$cody->plugin_install('mytinylanguage');
$cody->cy_interpret('$a=4 print "a+5=",$a+5');
Please submit bug reports, suggestions and pull requests to the GitHub issue tracker.
See changelog