Advertisement
Guest User

Untitled

a guest
Apr 19th, 2018
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 14.98 KB | None | 0 0
  1. <?php
  2.  
  3. $ERROR;
  4.  
  5. class Prog
  6. {
  7.   protected $_code;
  8.   protected $_error_type;
  9.   private   $_length;
  10.  
  11.   public function __construct($file_name)
  12.   {
  13.     global $ERROR;
  14.  
  15.     $this->_error_type = [
  16.           "LOG",
  17.           "WRG",
  18.           "ERR",
  19.         ];
  20.  
  21.     $this->read_file($file_name);
  22.     if (isset($this->_code))
  23.       $flexer = new Lexer($this->_code, $this->_error_type);
  24.     if (isset($flexer->_lexer))
  25.       {new parser($flexer->_lexer, $this->_error_type);}
  26.     $this->end();
  27.     $this->read_error();
  28.   }
  29.  
  30.   protected function add_error($type, $number, $error)
  31.   {
  32.     global $ERROR;
  33.     if(!isset($ERROR))
  34.         $ERROR = [];
  35.     $array = [
  36.             'typ'  => $this->_error_type[$type],
  37.             'nbr'  => $number,
  38.             'txt'  => $error,
  39.           ];
  40.     $ERROR[] = $array;
  41.   }
  42.  
  43.   private function read_file($file_name)
  44.   {
  45.     if (isset($file_name[1]))
  46.       if (explode('.', $file_name[1])[1] == "mcdo")
  47.         $this->get_code($file_name[1]);
  48.       else
  49.           $this->add_error(2, "00x0002", "File is not valid");
  50.     else
  51.         $this->add_error(2, "00x0001", "No file specified");
  52.   }
  53.  
  54.   private function get_code($file_name)
  55.   {
  56.     $code_arr;
  57.  
  58.     if (file_exists($file_name))
  59.          if (($code_arr = file($file_name)) && isset($code_arr))
  60.          {
  61.            $this->_code = "";
  62.             foreach ($code_arr as $i)
  63.               $this->_code .= $i . " ";
  64.           }
  65.          else
  66.             $this->add_error(2, "00x0004", "File is empty");
  67.     else
  68.       $this->add_error(2, "00x0003", "File does not exist");
  69.   }
  70.  
  71.   private function end()
  72.   {
  73.     global $ERROR;
  74.     $count_err = 0;
  75.     $count_wrg = 0;
  76.  
  77.     if(isset($ERROR))
  78.       foreach ($ERROR as $i)
  79.           if ($i["typ"] == "ERR")
  80.             $count_err++;
  81.           elseif ($i["typ"] == "WRG")
  82.             $count_wrg++;
  83.     $end  = "Process finished with " . $count_wrg . " Warning";
  84.     $end .= ($count_wrg > 1) ? "s " : " ";
  85.     $end .= "and " . $count_err . " Error";
  86.     $end .= ($count_err > 1) ? "s" : "";
  87.     $this->add_error(0, "", $end );
  88.   }
  89.  
  90.   private function read_error()
  91.   {
  92.     global $ERROR;
  93.     foreach ($ERROR as $i)
  94.     {
  95.       $to_echo = $i["typ"] . ": ";
  96.       $to_echo .= ($i["typ"] == "ERR") ? $i["nbr"] . ":  " : "";
  97.       $to_echo .= $i["txt"] . ".\n";
  98.       echo $to_echo;
  99.     }
  100.   }
  101. }
  102.  
  103. class Lexer extends Prog
  104. {
  105.   public    $_lexer;
  106.   protected $_rules;
  107.  
  108.   public function __construct($code, $error_type)
  109.   {
  110.     global $ERROR;
  111.     $this->_error_type = $error_type;
  112.     $this->_code = $code;
  113.     $this->set_rule();
  114.     $this->lexer();
  115.   }
  116.  
  117.   private function set_rule()
  118.   {
  119.       $this->_rules = [
  120.         ['else', 'ELSE'],
  121.         ['if', 'IF'],
  122.         ['{', 'LEFT_BRACE'],
  123.         ['}', 'RIGHT_BRACE'],
  124.         ['\?[a-zA-Z0-9]+', 'VAR'],
  125.         ['func_[a-zA-Z0-9]+', 'FUNC'],
  126.         ["'[^']'", 'CHAR'],
  127.         ['"[^"]*"', 'STRING'],
  128.         ["[\d|?a-zA-Z0-9]+ < [\d|?a-zA-Z0-9]+", "IF_INF"],
  129.         ["[\d|?a-zA-Z0-9]+ > [\d|?a-zA-Z0-9]+", "IF_SUP"],
  130.         ["[\d|?a-zA-Z0-9]+ == [\d|?a-zA-Z0-9]+", "IF_EQU"],
  131.         ["[\d|?a-zA-Z0-9]+ != [\d|?a-zA-Z0-9]+", "IF_DIF"],
  132.         ['=', 'ATT'],
  133.         ['\+', 'ADD'],
  134.         ['-', 'SUB'],
  135.         ['\/', 'DIV'],
  136.         ['\*', 'MUL'],
  137.         ["\d+", 'INTEGER'],
  138.         ["\(", 'LEFT_PAREN'],
  139.         ["\)", 'RIGHT_PAREN'],
  140.         ['print', 'PRINT'],
  141.         [';', 'SEMICOLON'],
  142.       ];
  143.   }
  144.  
  145.   private function lexer()
  146.   {
  147.     $result = [];
  148.     while($this->_code != " ")
  149.     {
  150.       $this->_code = ltrim($this->_code);
  151.       $valid = false;
  152.       foreach ($this->_rules as $rule) {
  153.         $pattern = '/^' . $rule[0] . '/';
  154.         $type = $rule[1];
  155.         if(preg_match($pattern, $this->_code, $capture))
  156.         {
  157.           $result[] = [
  158.               'type' => $type,
  159.               'value' => $capture[0],
  160.           ];
  161.           $valid = true;
  162.           $this->_code = substr($this->_code, strlen($capture[0]));
  163.           break;
  164.         }
  165.       }
  166.       if(!$valid){
  167.         $error = "can't recognize: '" . explode("\n", $this->_code)[0] . "'";
  168.         if($this->_code != '')
  169.           $this->add_error(2, "01x0001", $error);
  170.         break;
  171.       }
  172.     }
  173.     $this->_lexer = $result;
  174.   }
  175. }
  176.  
  177. class Parser extends Prog
  178. {
  179.  
  180.   public function __construct($parser, $error_type)
  181.   {
  182.     global $ERREUR;
  183.     $this->_error_type = $error_type;
  184.     $this->_parser = $parser;
  185.     $this->_var_tab = [];
  186.     $this->_result = $this->parse_func();
  187.     //var_dump($this->_result);
  188.     new interpreter($this->_result);
  189.   }
  190.  
  191.   private function peek(){
  192.     if(isset($this->_parser[0]))
  193.       return $this->_parser[0];
  194.   }
  195.  
  196.   private function pop(){
  197.       return array_shift($this->_parser);
  198.     }
  199.  
  200.   private function expect($types){
  201.       $token = $this->pop();
  202.       $valid = False;
  203.       foreach ($types as $type)
  204.       {
  205.         if ($type == $token['type'])
  206.             $valid = True;
  207.       }
  208.       if (!$valid)
  209.           $this->add_error(2, "02x0001", "Unexpected type: ".$token['type']);
  210.       return $token;
  211.       }
  212.  
  213.   private function parse_statement(){
  214.       $to_return = NULL;
  215.       if ($this->peek()['type'] == 'PRINT')
  216.       {
  217.           $this->pop();
  218.           $value = $this->expect(['STRING']);
  219.           $this->expect(['SEMICOLON']);
  220.           $to_return = array('type' => 'print', 'value' => $value);
  221.         }
  222.       elseif($this->peek()['type'] == "IF" || $this->peek()['type'] == "WHILE")
  223.           $to_return = $this->parse_if();
  224.       elseif($this->peek()['type'] == "VAR")
  225.           if($this->_parser[1]['type'] == "ATT")
  226.               $to_return = $this->parse_att();
  227.       return $to_return;
  228.       }
  229.  
  230.   private function parse_block(){
  231.       $this->expect(['LEFT_BRACE']);
  232.       $statements = [];
  233.       while ($statement = $this->parse_statement())
  234.       {
  235.           $statements [] = $statement;
  236.       }
  237.       $this->expect(['RIGHT_BRACE']);
  238.       return array('type' => 'block', 'statements' => $statements);
  239.   }
  240.  
  241.   private function check_var($name){
  242.     $to_return = [False, NULL];
  243.     foreach ($this->_var_tab as $var) {
  244.       if ( $var[0] == $name['value']){
  245.         $to_return = [True, $var[1]];
  246.       }
  247.     }
  248.     return $to_return;
  249.   }
  250.  
  251.   private function check_add($name){
  252.     if($this->check_var($name)[0] != True)
  253.       $this->_var_tab [] = [$name['value'], NULL];
  254.   }
  255.  
  256.   private function parse_att(){
  257.     $to_return = [];
  258.     $name = $this->pop();
  259.     $this->check_add($name);
  260.     $this->pop();
  261.       if($this->peek()['type'] == "LEFT_PAREN"){
  262.         $this->pop();
  263.         $value1 = $this->expect(['INTEGER', 'VAR']);
  264.         $op = $this->expect(['ADD', 'SUB', 'DIV', 'MUL']);
  265.         $value2 = $this->expect(['INTEGER', 'VAR']);
  266.         $this->expect(['RIGHT_PAREN']);
  267.         $this->expect(['SEMICOLON']);
  268.         $to_return = ['type' => $name["type"], 'name' => $name["value"], 'op'=> $op, 'value' => [$value1, $value2]];
  269.       }else{
  270.         $value = $this->expect(['INTEGER', 'VAR']);
  271.         $this->expect(['SEMICOLON']);
  272.         $to_return = ['type' => $name["type"], 'name' => $name["value"],'op' => NULL, 'value' => [$value]];
  273.       }
  274.       return $to_return;
  275.   }
  276.  
  277.   private function parse_if(){
  278.     $to_return = [];
  279.       if($this->peek()['type'] == "IF")
  280.       {
  281.         $this->pop();
  282.         $this->expect(['LEFT_PAREN']);
  283.         $value = $this->expect(['INTEGER', 'IF_INF', 'IF_SUP', 'IF_EQU', 'IF_DIF']);
  284.         $this->expect(['RIGHT_PAREN']);
  285.         $block = $this->parse_block();
  286.         if(empty($block["statements"]))
  287.           $this->add_error(1, "", "Empty 'if'");
  288.         if ($value["type"] == "IF")
  289.             $value["value"] = [explode(" ", $value["value"])[0], explode(" ", $value["value"])[1]];
  290.         else
  291.           $value["value"] = [$value["value"], NULL];
  292.         $to_return = array('type' => 'if', 'condition' => $value , 'block' => [$block]);
  293.         if ($this->peek()['type'] == "ELSE"){
  294.           $this->pop();
  295.           $block= $this->parse_block();
  296.           if(empty($block["statements"]))
  297.             $this->add_error(1, "", "Empty 'else'");
  298.           $to_return['block'][] = $block;
  299.         }
  300.       }
  301.       if($this->peek()['type'] == "WHILE")
  302.       {
  303.         $this->pop();
  304.         $this->expect(['LEFT_PAREN']);
  305.         $value = $this->expect(['INTEGER', 'IF_INF', 'IF_SUP', 'IF_EQU', 'IF_DIF']);
  306.         $this->expect(['RIGHT_PAREN']);
  307.         $block = $this->parse_block();
  308.         if(empty($block["statements"]))
  309.           $this->add_error(1, "", "Empty 'while'");
  310.         $to_return = array('type' => 'while', 'condition' => $value, 'block' => [$block]);
  311.       }
  312.       return $to_return;
  313.     }
  314.  
  315.    private function parse_func()
  316.    {
  317.      $to_return = [];
  318.      $valid = true;
  319.      while ($valid == true)
  320.      {
  321.         if($this->peek()['type'] == "FUNC")
  322.         {
  323.           $this->pop();
  324.           $this->expect(['LEFT_PAREN']);
  325.           $this->expect(['RIGHT_PAREN']);
  326.           $block = $this->parse_block();
  327.           $to_return [] = ['type' => 'func', 'block' => $block];
  328.         }
  329.         else
  330.           $valid = false;
  331.       }
  332.       $to_return ['var'] = $this->_var_tab;
  333.       return $to_return;
  334.    }
  335. }
  336.  
  337. $prog = new Prog($argv);
  338.  
  339. class interpreter extends Parser
  340. {
  341.     private $_tree;
  342.  
  343.     public function __construct($tree)
  344.     {
  345.         $this->interpreteur($tree);
  346.     }
  347.  
  348.     public function interpreteur($tree)
  349.     {
  350.         $this->_tree = $tree;
  351.         $count = -1;
  352.         $error = NULL;
  353.         while (isset($tree[++$count]))
  354.         {
  355.             if ($error != 1)
  356.             {
  357.                 $this->exec_block($tree[$count]['block']);
  358.             } else {
  359.                 echo "Une erreur est survenu dans votre code !";
  360.                 return 1;
  361.             }
  362.         }
  363.         return 0;
  364.     }
  365.  
  366.     private function exec_block($tree)
  367.     {
  368.         $count = -1;
  369.         $tree = $tree['statements'];
  370.         $error = NULL;
  371.         while (isset($tree[++$count]))
  372.         {
  373.             if ($error != 1)
  374.             {
  375.                 $this->exec_stat($tree[$count]);
  376.                 var_dump($tree);
  377.             } else {
  378.                 return 1;
  379.             }
  380.         }
  381.         return 0;
  382.     }
  383.  
  384.     private function exec_stat($tree)
  385.     {
  386.         if ($tree['type'] == "if")
  387.         {
  388.             $var0 = NULL;
  389.             $var1 = NULL;
  390.             if ($tree['condition']['value'][0][0] == '?')
  391.             {
  392.                 $var0 = $this->check_var($tree['condition']['value'][0]);
  393.             }
  394.             if ($tree['condition']['value'][1][0] == '?')
  395.             {
  396.                 $var1 = $this->check_var($tree['condition']['value'][1]);
  397.             }
  398.             echo "----------------------------------------------------";
  399.             var_dump($this->_tree);
  400.             echo "----------------------------------------------------";
  401.             $type = $this->exec_if_type($tree['condition']);
  402.             $result = $this->exec_if($tree, $type, $var0, $var1);
  403.             /*if ($result == 0)
  404.                 $this->exec_block($tree[0]);
  405.             else
  406.                 $this->exec_block($tree[0]);*/
  407.             return 0;
  408.         }
  409.  
  410.         if ($tree['type'] == "print")
  411.         {
  412.             print($tree['value']);
  413.             return $tree['value'];
  414.         }
  415.         if ($tree['type'] == 'var') // att var with no op
  416.         {
  417.             if ($tree['op'] == NULL)
  418.                 $var = $this->exec_var($tree['value']);
  419.             return $var;
  420.         }
  421.         if ($tree['type'] == "while")
  422.         {
  423.             $var0 = NULL;
  424.             $var1 = NULL;
  425.             $result = NULL;
  426.             if ($tree['value'][0]{0} == "?")
  427.             {
  428.                 $var0 = $this->check_var($tree['value'][0]);
  429.             }
  430.             if ($tree['value'][1]{0} == "?")
  431.             {
  432.                 $var1 = $this->check_var($tree['value'][1]);
  433.             }
  434.             $type = $this->exec_if_type($tree['condition']);
  435.             while ($result != 1)
  436.                 $result = $this->exec_while($tree, $type, $var0, $var1);
  437.             return $result;
  438.         }
  439.         return 1;
  440.     }
  441.  
  442.     private function exec_var($tree)
  443.     {
  444.         $count = -1;
  445.         while (isset($this->_tree["var"][++$count]))
  446.         {
  447.             if ($this->_tree["var"][++$count][0] == $tree)
  448.                 return $this->_tree["var"][++$count][1];
  449.         }
  450.         return $this->_tree["var"][++$count][1];
  451.     }
  452.  
  453.     private function exec_while($tree, $type, $var0, $var1)
  454.     {
  455.         if ($var0 != NULL && $var1 != NULL)
  456.         {
  457.             if ($var0.$type.$var1)
  458.             {
  459.                 return 0;
  460.             }
  461.         }
  462.         else if ($var0 != NULL)
  463.         {
  464.             if ($var0.$type.$tree['value'][1])
  465.             {
  466.                 return 0;
  467.             }
  468.         }
  469.         else if ($var1 != NULL)
  470.         {
  471.             if ($tree['value'][0].$type.$var1)
  472.             {
  473.                 return 0;
  474.             }
  475.         }
  476.         else if ($var1 == NULL && $var1 == NULL)
  477.         {
  478.             if ($tree['value'][0].$type.$tree['value'][1])
  479.             {
  480.                 return 0;
  481.             }
  482.         }
  483.         return 1;
  484.     }
  485.  
  486.     private function exec_if($tree, $type, $var0, $var1)
  487.     {
  488.         if ($var0 != NULL && $var1 != NULL)
  489.         {
  490.             if ($var0.$type.$var1)
  491.             {
  492.                 return 0;
  493.             }
  494.         }
  495.         else if ($var0 != NULL)
  496.         {
  497.             if ($var0.$type.$tree['condition']['value'][1])
  498.             {
  499.                 return 0;
  500.             }
  501.         }
  502.         else if ($var1 != NULL)
  503.         {
  504.             if ($tree['condition']['value'][0].$type.$var1)
  505.             {
  506.                 return 0;
  507.             }
  508.         }
  509.         else if ($var1 == NULL && $var1 == NULL)
  510.         {
  511.             if ($tree['condition']['value'][0].$type.$tree['condition']['value'][1])
  512.             {
  513.                 return 0;
  514.             }
  515.         }
  516.         return 1;
  517.     }
  518.  
  519.     private function exec_if_type($tree)
  520.     {
  521.         $type = ["IF_INF" => "<", "IF_SUP" => ">", "IF_EQU" => "==", "IF_DIF" => "!="];
  522.         $i = 0;
  523. //        while ($tree["type"] != $type[$i])
  524. //        {
  525. //            $i++;
  526. //        }
  527.         foreach ($tree['type'] as $trees)
  528.         {
  529.             var_dump($tree['type']);
  530.             echo "----------------------------------------------------";
  531.             var_dump($trees);
  532.         }
  533.         return $type[$i];
  534.     }
  535.     private function check_var($name)
  536.     {
  537.         $to_return = [False, NULL];
  538.         if (count($this->_tree['var']) <= 1) {
  539.             if ($this->_tree['var'][0][0] == $name)
  540.             {
  541.                 $to_return = [True, $this->_tree['var'][0][1]];
  542.             }
  543.         } else {
  544.             foreach ($this->_tree['var'] as $var)
  545.             {
  546.                 if ($var[0] == $name)
  547.                 {
  548.                     $to_return = [True, $var[1]];
  549.                 }
  550.             }
  551.         }
  552.         return $to_return;
  553.     }
  554. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement