Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /*********************************************
- IPP - 1.projekt
- Iva Kavankova
- *********************************************/
- // TODO: ignor entru mezi radky a instrukce malymi pismeny
- error_reporting(-1); // vypis vsech chyb
- function error($msg) {
- fprintf(STDERR, "CHYBA: $msg!\n");
- }
- class InstructionRegister {
- public static $options = array(
- "MOVE" => "var_symb",
- "CREATEFRAME" => "",
- "PUSHFRAME" => "",
- "POPHFRAME" => "",
- "DEFVAR" => "var",
- "CALL" => "label",
- "RETURN" => "",
- "PUSHS" => "symb",
- "POPS" => "var",
- "ADD" => "var_symb_symb",
- "SUB" => "var_symb_symb",
- "MUL" => "var_symb_symb",
- "IDIV" => "var_symb_symb",
- "LT" => "var_symb_symb",
- "GT" => "var_symb_symb",
- "EQ" => "var_symb_symb",
- "AND" => "var_symb1_symb2",
- "OR" => "var_symb_symb",
- "NOT" => "var_symb_symb",
- "INT2CHAR" => "var_symb",
- "STRI2INT" => "var_symb_symb",
- "READ" => "var_type",
- "WRITE" => "symb",
- "CONCAT" => "var_symb_symb",
- "STRLEN" => "var_symb",
- "GETCHAR" => "var_symb_symb",
- "SETCHAR" => "var_symb_symb",
- "TYPE" => "var_symb",
- "LABEL" => "label",
- "JUMP" => "label",
- "JUMPIFEQ" => "label_symb_symb",
- "JUMPIFNEQ" => "label_symb_symb",
- "DPRINT" => "symb",
- "BREAK" => "",
- );
- }
- // napoveda
- function help() {
- echo "Tento skript parse.php nacte ze standardniho vstupu zdrojovy kod v jazyce IPPcode18, zkontroluje lexikalni a syntaktickou spravnost kodu.\nNakonec vypise na stdout vystup ve forme XML reprezentace programu.";
- }
- // nacteni argumentu
- if ($argc == 2) {
- if ($argc > 1 && strcmp($argv[1], "--help") == 0) {
- help();
- exit(0);
- }
- else {
- error("chybne zadani argumentu");
- exit(10);
- }
- }
- else if ($argc > 2) {
- error("chybne zadani argumentu");
- exit(10);
- }
- // nacitani ze stdin
- $inputStream = STDIN;
- if ($inputStream === FALSE) {
- error("nelze nacist soubor");
- exit(1);
- }
- // kontrola
- function checkSignature($opcode, $foundType, $index) {
- $instructionOptions = array(
- "MOVE" => "var_symb",
- "CREATEFRAME" => "",
- "PUSHFRAME" => "",
- "POPFRAME" => "",
- "DEFVAR" => "var",
- "CALL" => "label",
- "RETURN" => "",
- "PUSHS" => "symb",
- "POPS" => "var",
- "ADD" => "var_symb_symb",
- "SUB" => "var_symb_symb",
- "MUL" => "var_symb_symb",
- "IDIV" => "var_symb_symb",
- "LT" => "var_symb_symb",
- "GT" => "var_symb_symb",
- "EQ" => "var_symb_symb",
- "AND" => "var_symb1_symb2",
- "OR" => "var_symb_symb",
- "NOT" => "var_symb_symb",
- "INT2CHAR" => "var_symb",
- "STRI2INT" => "var_symb_symb",
- "READ" => "var_type",
- "WRITE" => "symb",
- "CONCAT" => "var_symb_symb",
- "STRLEN" => "var_symb",
- "GETCHAR" => "var_symb_symb",
- "SETCHAR" => "var_symb_symb",
- "TYPE" => "var_symb",
- "LABEL" => "label",
- "JUMP" => "label",
- "JUMPIFEQ" => "label_symb_symb",
- "JUMPIFNEQ" => "label_symb_symb",
- "DPRINT" => "symb",
- "BREAK" => "",
- );
- if(array_key_exists($opcode, $instructionOptions) == FALSE)
- {
- error("neznamy operacni kod instrukce: ($opcode)");
- return FALSE;
- }
- $instructionSignature = explode('_', $instructionOptions[$opcode]);
- if($index < count($instructionSignature)) {
- //$instructionOptions[$opcode];
- if ($instructionSignature[$index] == $foundType) {
- return TRUE;
- }
- elseif ($instructionSignature[$index] == 'symb'){
- if(in_array($foundType, ['var', 'int', 'string', 'bool'])) {
- return TRUE;
- }
- else {
- error("spatny typ opreandu");
- return FALSE;
- }
- }
- else {
- error("nenalezen operand");
- return FALSE;
- }
- }
- else {
- error("prebytecny operand");
- return FALSE;
- }
- error("vsechno spatne");
- return FALSE;
- }
- $text = stream_get_contents($inputStream); // retezec
- function parseInput($input) {
- $lines = preg_split('/[\n\r]/', $input);
- $hasHeader = FALSE;
- $parsedLines = [];
- foreach ($lines as $lineNumber => $line) {
- $hashIndex = strpos($line, '#');
- if ($hashIndex !== FALSE) {
- $line = substr($line, 0, $hashIndex);
- }
- $line = trim($line);
- if ($line == '') continue;
- if (mb_strtoupper($line) == '.IPPCODE18' && !$hasHeader) {
- $hasHeader = TRUE;
- continue;
- }
- if (!$hasHeader) {
- error("nema povinnou hlavicku");
- return FALSE;
- }
- $parsedLines[] = $line;
- }
- return $parsedLines;
- }
- // parsovani operandu
- function parseOperand($parentElement, $lineParts, $index) {
- $part = $lineParts[$index];
- $elementText = $elementType = '';
- if (strpos($part, '@') !== FALSE) {
- list($opType, $opContent) = explode('@', $part, 2);
- if ($opType == 'int') {
- $elementText = $opContent;
- $elementType = $opType;
- } else if ($opType == 'bool') {
- $elementText = $opContent;
- $elementType = $opType;
- } else if ($opType == 'string') {
- $elementText = $opContent;
- $elementType = $opType;
- } else if (in_array($opType, ['GF', 'LF', 'TF'])) {
- $elementText = $part;
- $elementType = 'var';
- } else {
- throw new Exception("problem $opType, $part", 1);
- }
- } else {
- if ($lineParts[0] == 'READ' && $index == 2) {
- $elementText = $part;
- $elementType = 'type';
- } else {
- $elementText = $part;
- $elementType = 'label';
- }
- }
- if (checkSignature($lineParts[0], $elementType, $index - 1) == FALSE)
- {
- error("nastal mensi problem: $lineParts, $index, $elementType");
- return NULL;
- }
- $argElement = $parentElement->addChild('arg' . $index, $elementText);
- $argElement->addAttribute('type', $elementType);
- return $argElement;
- }
- $lines = parseInput($text);
- // zacatek generovani XML dokumentu
- $programElement = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><program />');
- $programElement->addAttribute('language', 'IPPcode18');
- function generateInstructions($lines, $programElement) {
- foreach ($lines as $instructionOrder => $line) {
- $parts = preg_split("/\s+/", $line);
- $instructionElement = $programElement->addChild('instruction');
- $opcode = $parts[0];
- $instructionElement->addAttribute('opcode', $opcode);
- $opcode = mb_strtoupper($opcode);
- if (!array_key_exists($opcode, InstructionRegister::$options)) {
- error("nenalezena instrukce");
- return FALSE;
- }
- $operandsCount = count($parts) - 1;
- if ($operandsCount > 0) {
- if(parseOperand($instructionElement, $parts, 1) == NULL) {
- error("nespravny operand 1: $line");
- return FALSE;
- }
- }
- if ($operandsCount > 1) {
- if(parseOperand($instructionElement, $parts, 2) == NULL) {
- error("nespravny operand 2: $line");
- return FALSE;
- }
- }
- if ($operandsCount > 2) {
- if(parseOperand($instructionElement, $parts, 3) == NULL) {
- error("nespravny operand 3: $line");
- return FALSE;
- }
- }
- if ($operandsCount > 3) {
- error("prilis mnoho operandu");
- return FALSE;
- }
- }
- return TRUE;
- }
- // chybovy navratovy kod specificky pro analyzator
- if (!generateInstructions($lines,$programElement)) {
- exit(21);
- }
- // vygenerovani zbytku XML
- echo $programElement->asXML();
- exit(0); // bez problemu
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement