Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- $ERROR;
- class Prog
- {
- protected $_code;
- protected $_error_type;
- private $_length;
- public function __construct($file_name)
- {
- global $ERROR;
- $this->_error_type = [
- "LOG",
- "WRG",
- "ERR",
- ];
- $this->read_file($file_name);
- if (isset($this->_code))
- $flexer = new Lexer($this->_code, $this->_error_type);
- if (isset($flexer->_lexer))
- {new parser($flexer->_lexer, $this->_error_type);}
- $this->end();
- $this->read_error();
- }
- protected function add_error($type, $number, $error)
- {
- global $ERROR;
- if(!isset($ERROR))
- $ERROR = [];
- $array = [
- 'typ' => $this->_error_type[$type],
- 'nbr' => $number,
- 'txt' => $error,
- ];
- $ERROR[] = $array;
- }
- private function read_file($file_name)
- {
- if (isset($file_name[1]))
- if (explode('.', $file_name[1])[1] == "mcdo")
- $this->get_code($file_name[1]);
- else
- $this->add_error(2, "00x0002", "File is not valid");
- else
- $this->add_error(2, "00x0001", "No file specified");
- }
- private function get_code($file_name)
- {
- $code_arr;
- if (file_exists($file_name))
- if (($code_arr = file($file_name)) && isset($code_arr))
- {
- $this->_code = "";
- foreach ($code_arr as $i)
- $this->_code .= $i . " ";
- }
- else
- $this->add_error(2, "00x0004", "File is empty");
- else
- $this->add_error(2, "00x0003", "File does not exist");
- }
- private function end()
- {
- global $ERROR;
- $count_err = 0;
- $count_wrg = 0;
- if(isset($ERROR))
- foreach ($ERROR as $i)
- if ($i["typ"] == "ERR")
- $count_err++;
- elseif ($i["typ"] == "WRG")
- $count_wrg++;
- $end = "Process finished with " . $count_wrg . " Warning";
- $end .= ($count_wrg > 1) ? "s " : " ";
- $end .= "and " . $count_err . " Error";
- $end .= ($count_err > 1) ? "s" : "";
- $this->add_error(0, "", $end );
- }
- private function read_error()
- {
- global $ERROR;
- foreach ($ERROR as $i)
- {
- $to_echo = $i["typ"] . ": ";
- $to_echo .= ($i["typ"] == "ERR") ? $i["nbr"] . ": " : "";
- $to_echo .= $i["txt"] . ".\n";
- echo $to_echo;
- }
- }
- }
- class Lexer extends Prog
- {
- public $_lexer;
- protected $_rules;
- public function __construct($code, $error_type)
- {
- global $ERROR;
- $this->_error_type = $error_type;
- $this->_code = $code;
- $this->set_rule();
- $this->lexer();
- }
- private function set_rule()
- {
- $this->_rules = [
- ['else', 'ELSE'],
- ['if', 'IF'],
- ['{', 'LEFT_BRACE'],
- ['}', 'RIGHT_BRACE'],
- ['\?[a-zA-Z0-9]+', 'VAR'],
- ['func_[a-zA-Z0-9]+', 'FUNC'],
- ["'[^']'", 'CHAR'],
- ['"[^"]*"', 'STRING'],
- ["[\d|?a-zA-Z0-9]+ < [\d|?a-zA-Z0-9]+", "IF_INF"],
- ["[\d|?a-zA-Z0-9]+ > [\d|?a-zA-Z0-9]+", "IF_SUP"],
- ["[\d|?a-zA-Z0-9]+ == [\d|?a-zA-Z0-9]+", "IF_EQU"],
- ["[\d|?a-zA-Z0-9]+ != [\d|?a-zA-Z0-9]+", "IF_DIF"],
- ['=', 'ATT'],
- ['\+', 'ADD'],
- ['-', 'SUB'],
- ['\/', 'DIV'],
- ['\*', 'MUL'],
- ["\d+", 'INTEGER'],
- ["\(", 'LEFT_PAREN'],
- ["\)", 'RIGHT_PAREN'],
- ['print', 'PRINT'],
- [';', 'SEMICOLON'],
- ];
- }
- private function lexer()
- {
- $result = [];
- while($this->_code != " ")
- {
- $this->_code = ltrim($this->_code);
- $valid = false;
- foreach ($this->_rules as $rule) {
- $pattern = '/^' . $rule[0] . '/';
- $type = $rule[1];
- if(preg_match($pattern, $this->_code, $capture))
- {
- $result[] = [
- 'type' => $type,
- 'value' => $capture[0],
- ];
- $valid = true;
- $this->_code = substr($this->_code, strlen($capture[0]));
- break;
- }
- }
- if(!$valid){
- $error = "can't recognize: '" . explode("\n", $this->_code)[0] . "'";
- if($this->_code != '')
- $this->add_error(2, "01x0001", $error);
- break;
- }
- }
- $this->_lexer = $result;
- }
- }
- class Parser extends Prog
- {
- public function __construct($parser, $error_type)
- {
- global $ERREUR;
- $this->_error_type = $error_type;
- $this->_parser = $parser;
- $this->_var_tab = [];
- $this->_result = $this->parse_func();
- //var_dump($this->_result);
- new interpreter($this->_result);
- }
- private function peek(){
- if(isset($this->_parser[0]))
- return $this->_parser[0];
- }
- private function pop(){
- return array_shift($this->_parser);
- }
- private function expect($types){
- $token = $this->pop();
- $valid = False;
- foreach ($types as $type)
- {
- if ($type == $token['type'])
- $valid = True;
- }
- if (!$valid)
- $this->add_error(2, "02x0001", "Unexpected type: ".$token['type']);
- return $token;
- }
- private function parse_statement(){
- $to_return = NULL;
- if ($this->peek()['type'] == 'PRINT')
- {
- $this->pop();
- $value = $this->expect(['STRING']);
- $this->expect(['SEMICOLON']);
- $to_return = array('type' => 'print', 'value' => $value);
- }
- elseif($this->peek()['type'] == "IF" || $this->peek()['type'] == "WHILE")
- $to_return = $this->parse_if();
- elseif($this->peek()['type'] == "VAR")
- if($this->_parser[1]['type'] == "ATT")
- $to_return = $this->parse_att();
- return $to_return;
- }
- private function parse_block(){
- $this->expect(['LEFT_BRACE']);
- $statements = [];
- while ($statement = $this->parse_statement())
- {
- $statements [] = $statement;
- }
- $this->expect(['RIGHT_BRACE']);
- return array('type' => 'block', 'statements' => $statements);
- }
- private function check_var($name){
- $to_return = [False, NULL];
- foreach ($this->_var_tab as $var) {
- if ( $var[0] == $name['value']){
- $to_return = [True, $var[1]];
- }
- }
- return $to_return;
- }
- private function check_add($name){
- if($this->check_var($name)[0] != True)
- $this->_var_tab [] = [$name['value'], NULL];
- }
- private function parse_att(){
- $to_return = [];
- $name = $this->pop();
- $this->check_add($name);
- $this->pop();
- if($this->peek()['type'] == "LEFT_PAREN"){
- $this->pop();
- $value1 = $this->expect(['INTEGER', 'VAR']);
- $op = $this->expect(['ADD', 'SUB', 'DIV', 'MUL']);
- $value2 = $this->expect(['INTEGER', 'VAR']);
- $this->expect(['RIGHT_PAREN']);
- $this->expect(['SEMICOLON']);
- $to_return = ['type' => $name["type"], 'name' => $name["value"], 'op'=> $op, 'value' => [$value1, $value2]];
- }else{
- $value = $this->expect(['INTEGER', 'VAR']);
- $this->expect(['SEMICOLON']);
- $to_return = ['type' => $name["type"], 'name' => $name["value"],'op' => NULL, 'value' => [$value]];
- }
- return $to_return;
- }
- private function parse_if(){
- $to_return = [];
- if($this->peek()['type'] == "IF")
- {
- $this->pop();
- $this->expect(['LEFT_PAREN']);
- $value = $this->expect(['INTEGER', 'IF_INF', 'IF_SUP', 'IF_EQU', 'IF_DIF']);
- $this->expect(['RIGHT_PAREN']);
- $block = $this->parse_block();
- if(empty($block["statements"]))
- $this->add_error(1, "", "Empty 'if'");
- if ($value["type"] == "IF")
- $value["value"] = [explode(" ", $value["value"])[0], explode(" ", $value["value"])[1]];
- else
- $value["value"] = [$value["value"], NULL];
- $to_return = array('type' => 'if', 'condition' => $value , 'block' => [$block]);
- if ($this->peek()['type'] == "ELSE"){
- $this->pop();
- $block= $this->parse_block();
- if(empty($block["statements"]))
- $this->add_error(1, "", "Empty 'else'");
- $to_return['block'][] = $block;
- }
- }
- if($this->peek()['type'] == "WHILE")
- {
- $this->pop();
- $this->expect(['LEFT_PAREN']);
- $value = $this->expect(['INTEGER', 'IF_INF', 'IF_SUP', 'IF_EQU', 'IF_DIF']);
- $this->expect(['RIGHT_PAREN']);
- $block = $this->parse_block();
- if(empty($block["statements"]))
- $this->add_error(1, "", "Empty 'while'");
- $to_return = array('type' => 'while', 'condition' => $value, 'block' => [$block]);
- }
- return $to_return;
- }
- private function parse_func()
- {
- $to_return = [];
- $valid = true;
- while ($valid == true)
- {
- if($this->peek()['type'] == "FUNC")
- {
- $this->pop();
- $this->expect(['LEFT_PAREN']);
- $this->expect(['RIGHT_PAREN']);
- $block = $this->parse_block();
- $to_return [] = ['type' => 'func', 'block' => $block];
- }
- else
- $valid = false;
- }
- $to_return ['var'] = $this->_var_tab;
- return $to_return;
- }
- }
- $prog = new Prog($argv);
- class interpreter extends Parser
- {
- private $_tree;
- public function __construct($tree)
- {
- $this->interpreteur($tree);
- }
- public function interpreteur($tree)
- {
- $this->_tree = $tree;
- $count = -1;
- $error = NULL;
- while (isset($tree[++$count]))
- {
- if ($error != 1)
- {
- $this->exec_block($tree[$count]['block']);
- } else {
- echo "Une erreur est survenu dans votre code !";
- return 1;
- }
- }
- return 0;
- }
- private function exec_block($tree)
- {
- $count = -1;
- $tree = $tree['statements'];
- $error = NULL;
- while (isset($tree[++$count]))
- {
- if ($error != 1)
- {
- $this->exec_stat($tree[$count]);
- var_dump($tree);
- } else {
- return 1;
- }
- }
- return 0;
- }
- private function exec_stat($tree)
- {
- if ($tree['type'] == "if")
- {
- $var0 = NULL;
- $var1 = NULL;
- if ($tree['condition']['value'][0][0] == '?')
- {
- $var0 = $this->check_var($tree['condition']['value'][0]);
- }
- if ($tree['condition']['value'][1][0] == '?')
- {
- $var1 = $this->check_var($tree['condition']['value'][1]);
- }
- echo "----------------------------------------------------";
- var_dump($this->_tree);
- echo "----------------------------------------------------";
- $type = $this->exec_if_type($tree['condition']);
- $result = $this->exec_if($tree, $type, $var0, $var1);
- /*if ($result == 0)
- $this->exec_block($tree[0]);
- else
- $this->exec_block($tree[0]);*/
- return 0;
- }
- if ($tree['type'] == "print")
- {
- print($tree['value']);
- return $tree['value'];
- }
- if ($tree['type'] == 'var') // att var with no op
- {
- if ($tree['op'] == NULL)
- $var = $this->exec_var($tree['value']);
- return $var;
- }
- if ($tree['type'] == "while")
- {
- $var0 = NULL;
- $var1 = NULL;
- $result = NULL;
- if ($tree['value'][0]{0} == "?")
- {
- $var0 = $this->check_var($tree['value'][0]);
- }
- if ($tree['value'][1]{0} == "?")
- {
- $var1 = $this->check_var($tree['value'][1]);
- }
- $type = $this->exec_if_type($tree['condition']);
- while ($result != 1)
- $result = $this->exec_while($tree, $type, $var0, $var1);
- return $result;
- }
- return 1;
- }
- private function exec_var($tree)
- {
- $count = -1;
- while (isset($this->_tree["var"][++$count]))
- {
- if ($this->_tree["var"][++$count][0] == $tree)
- return $this->_tree["var"][++$count][1];
- }
- return $this->_tree["var"][++$count][1];
- }
- private function exec_while($tree, $type, $var0, $var1)
- {
- if ($var0 != NULL && $var1 != NULL)
- {
- if ($var0.$type.$var1)
- {
- return 0;
- }
- }
- else if ($var0 != NULL)
- {
- if ($var0.$type.$tree['value'][1])
- {
- return 0;
- }
- }
- else if ($var1 != NULL)
- {
- if ($tree['value'][0].$type.$var1)
- {
- return 0;
- }
- }
- else if ($var1 == NULL && $var1 == NULL)
- {
- if ($tree['value'][0].$type.$tree['value'][1])
- {
- return 0;
- }
- }
- return 1;
- }
- private function exec_if($tree, $type, $var0, $var1)
- {
- if ($var0 != NULL && $var1 != NULL)
- {
- if ($var0.$type.$var1)
- {
- return 0;
- }
- }
- else if ($var0 != NULL)
- {
- if ($var0.$type.$tree['condition']['value'][1])
- {
- return 0;
- }
- }
- else if ($var1 != NULL)
- {
- if ($tree['condition']['value'][0].$type.$var1)
- {
- return 0;
- }
- }
- else if ($var1 == NULL && $var1 == NULL)
- {
- if ($tree['condition']['value'][0].$type.$tree['condition']['value'][1])
- {
- return 0;
- }
- }
- return 1;
- }
- private function exec_if_type($tree)
- {
- $type = ["IF_INF" => "<", "IF_SUP" => ">", "IF_EQU" => "==", "IF_DIF" => "!="];
- $i = 0;
- // while ($tree["type"] != $type[$i])
- // {
- // $i++;
- // }
- foreach ($tree['type'] as $trees)
- {
- var_dump($tree['type']);
- echo "----------------------------------------------------";
- var_dump($trees);
- }
- return $type[$i];
- }
- private function check_var($name)
- {
- $to_return = [False, NULL];
- if (count($this->_tree['var']) <= 1) {
- if ($this->_tree['var'][0][0] == $name)
- {
- $to_return = [True, $this->_tree['var'][0][1]];
- }
- } else {
- foreach ($this->_tree['var'] as $var)
- {
- if ($var[0] == $name)
- {
- $to_return = [True, $var[1]];
- }
- }
- }
- return $to_return;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement