public function createProperties(TES4VariableDeclarationList $variableList, TES5GlobalScope $globalScope)
 {
     /**
      * @var TES4VariableDeclaration[] $alreadyDefinedVariables
      */
     $alreadyDefinedVariables = [];
     foreach ($variableList->getVariableList() as $variable) {
         $theVariableName = strtolower($variable->getVariableName());
         if (isset($alreadyDefinedVariables[$theVariableName])) {
             if ($variable->getVariableType() == $alreadyDefinedVariables[$theVariableName]->getVariableType()) {
                 continue;
                 //Same variable defined twice, smack the original script developer and fallthrough silently.
             }
             throw new ConversionException("Double definition of variable named " . $variable->getVariableName() . " with different types ( " . $alreadyDefinedVariables[$theVariableName]->getVariableType()->value() . " and " . $variable->getVariableType()->value() . " )");
         }
         switch ($variable->getVariableType()) {
             case TES4Type::T_FLOAT():
                 $property = new TES5Property($variable->getVariableName(), TES5BasicType::T_FLOAT(), null);
                 break;
             case TES4Type::T_INT():
             case TES4Type::T_SHORT():
             case TES4Type::T_LONG():
                 $property = new TES5Property($variable->getVariableName(), TES5BasicType::T_INT(), null);
                 break;
             case TES4Type::T_REF():
                 $property = $this->createPropertyFromReference($variable);
                 break;
             default:
                 throw new ConversionException("Unknown variable declaration type.");
         }
         $globalScope->add($property);
         $alreadyDefinedVariables[$theVariableName] = $variable;
     }
 }
 public function __construct()
 {
     $this('Script')->is('ScriptHeader', 'Block+')->call(function ($header, $blockList) {
         return new TES4Script($header, null, $blockList);
     })->is('ScriptHeader', 'VariableDeclaration+')->call(function ($header, $variableList) {
         return new TES4Script($header, $variableList, null);
     })->is('ScriptHeader', 'VariableDeclaration+', 'Block+')->call(function ($header, $variableList, $blockList) {
         return new TES4Script($header, $variableList, $blockList);
     });
     $this('ScriptHeader')->is('ScriptHeaderToken', 'ScriptName')->call(function ($headerToken, CommonToken $scriptName) {
         return new TES4ScriptHeader($scriptName->getValue());
     });
     $this('VariableDeclaration+')->is('VariableDeclaration+', 'VariableDeclaration')->call(function (TES4VariableDeclarationList $list, TES4VariableDeclaration $variableDeclaration) {
         $list->add($variableDeclaration);
         return $list;
     })->is('VariableDeclaration')->call(function (TES4VariableDeclaration $variableDeclaration) {
         $list = new TES4VariableDeclarationList();
         $list->add($variableDeclaration);
         return $list;
     });
     $this('VariableDeclaration')->is('VariableDeclarationType', 'VariableName')->call(function (CommonToken $variableDeclarationType, CommonToken $variableName) {
         return new TES4VariableDeclaration($variableName->getValue(), TES4Type::memberByValue(strtolower($variableDeclarationType->getValue())));
     });
     $this('Block+')->is('Block+', 'Block')->call(function (TES4BlockList $list, TES4CodeBlock $blockDeclaration) {
         $list->add($blockDeclaration);
         return $list;
     })->is('Block')->call(function (TES4CodeBlock $blockDeclaration) {
         $list = new TES4BlockList();
         $list->add($blockDeclaration);
         return $list;
     });
     $this('Block')->is('BlockStart', 'BlockType', 'BlockParameter+', 'Code+', 'BlockEnd')->call(function ($blockStart, CommonToken $blockType, TES4BlockParameterList $blockParameters, TES4CodeChunks $codeChunks, $blockEnd) {
         return new TES4CodeBlock($blockType->getValue(), $blockParameters, $codeChunks);
     })->is('BlockStart', 'BlockType', 'BlockParameter+', 'BlockEnd')->call(function ($blockStart, CommonToken $blockType, TES4BlockParameterList $blockParameters, $blockEnd) {
         return new TES4CodeBlock($blockType->getValue(), $blockParameters, null);
     })->is('BlockStart', 'BlockType', 'Code+', 'BlockEnd')->call(function ($blockStart, CommonToken $blockType, TES4CodeChunks $codeChunks, $blockEnd) {
         return new TES4CodeBlock($blockType->getValue(), null, $codeChunks);
     })->is('BlockStart', 'BlockType', 'BlockEnd')->call(function ($blockStart, CommonToken $blockType, $blockEnd) {
         return new TES4CodeBlock($blockType->getValue(), null, null);
     });
     //rare empty block
     $this('BlockParameter+')->is('BlockParameter+', 'BlockParameter')->call(function (TES4BlockParameterList $list, TES4BlockParameter $blockParameter) {
         $list->add($blockParameter);
         return $list;
     })->is('BlockParameter')->call(function (TES4BlockParameter $blockParameter) {
         $block = new TES4BlockParameterList();
         $block->add($blockParameter);
         return $block;
     });
     $this('BlockParameter')->is('BlockParameterToken')->call(function (CommonToken $token) {
         return new TES4BlockParameter($token->getValue());
     });
     $this->createObscriptCodeParsingTree();
     $this->start('Script');
 }
 /**
  * @param TES4Primitive $value
  * @return TES5Float|TES5Integer|TES5String
  * @throws \Ormin\OBSLexicalParser\TES5\Exception\ConversionException
  */
 public function createValue(TES4Primitive $value)
 {
     switch ($value->getType()) {
         case TES4Type::T_INT():
             return new TES5Integer($value->getData());
         case TES4Type::T_STRING():
             return new TES5String($value->getData());
         case TES4Type::T_FLOAT():
             return new TES5Float($value->getData());
     }
     throw new ConversionException("Unknown value type to be factored from " . get_class($value));
 }
 public function buildVariableDeclarationList($path)
 {
     $list = new TES4VariableDeclarationList();
     if (!file_exists($path)) {
         return $list;
     }
     $references = file($path);
     foreach ($references as $reference) {
         $reference = trim($reference);
         if (empty($reference)) {
             continue;
         }
         $list->add(new TES4VariableDeclaration(trim($reference), TES4Type::T_REF()));
     }
     return $list;
 }
 public function createCodeChunk(TES4VariableDeclarationList $chunk, TES5CodeScope $codeScope)
 {
     foreach ($chunk->getVariableList() as $variable) {
         switch ($variable->getVariableType()) {
             case TES4Type::T_FLOAT():
                 $property = new TES5LocalVariable($variable->getVariableName(), TES5BasicType::T_FLOAT());
                 break;
             case TES4Type::T_INT():
             case TES4Type::T_SHORT():
             case TES4Type::T_LONG():
                 $property = new TES5LocalVariable($variable->getVariableName(), TES5BasicType::T_INT());
                 break;
             case TES4Type::T_REF():
                 //most basic one, if something from inherited class is used, we will set to the inheriting class
                 $property = new TES5LocalVariable($variable->getVariableName(), TES5BasicType::T_FORM());
                 break;
             default:
                 throw new ConversionException("Unknown local variable declaration type.");
         }
         $codeScope->getLocalScope()->addVariable($property);
     }
     return null;
 }
 protected function createObscriptCodeParsingTree()
 {
     $this('Code+')->is('Code+', 'Code')->call(function (TES4CodeChunks $list, TES4CodeChunk $codeDeclaration) {
         $list->add($codeDeclaration);
         return $list;
     })->is('Code')->call(function (TES4CodeChunk $codeDeclaration) {
         $list = new TES4CodeChunks();
         $list->add($codeDeclaration);
         return $list;
     });
     $this('Code')->is('Branch')->is('SetValue', 'NWL')->is('Function', 'NWL')->is('ObjectCall', 'NWL')->is('LocalVariableDeclaration+')->is('Return');
     #todo - THIS should be fixed on lexer level, right now it ignores NWL after the return
     $this('LocalVariableDeclaration+')->is('LocalVariableDeclaration+', 'LocalVariableDeclaration')->call(function (TES4VariableDeclarationList $list, TES4VariableDeclaration $variableDeclaration) {
         $list->add($variableDeclaration);
         return $list;
     })->is('LocalVariableDeclaration')->call(function (TES4VariableDeclaration $variableDeclaration) {
         $list = new TES4VariableDeclarationList();
         $list->add($variableDeclaration);
         return $list;
     });
     $this('LocalVariableDeclaration')->is('LocalVariableDeclarationType', 'VariableName')->call(function (CommonToken $variableDeclarationType, CommonToken $variableName) {
         return new TES4VariableDeclaration($variableName->getValue(), TES4Type::memberByValue(strtolower($variableDeclarationType->getValue())));
     });
     $this('Branch')->is('BranchStart', 'BranchEndToken')->call(function (TES4SubBranch $branchStart, $end) {
         return new TES4Branch($branchStart, null, null);
     })->is('BranchStart', 'BranchSubBranch+', 'BranchEndToken')->call(function (TES4SubBranch $branchStart, TES4SubBranchList $subbranches, $end) {
         return new TES4Branch($branchStart, $subbranches, null);
     })->is('BranchStart', 'BranchElse', 'BranchEndToken')->call(function (TES4SubBranch $branchStart, TES4ElseSubBranch $branchElse, $end) {
         return new TES4Branch($branchStart, null, $branchElse);
     })->is('BranchStart', 'BranchSubBranch+', 'BranchElse', 'BranchEndToken')->call(function (TES4SubBranch $branchStart, TES4SubBranchList $subbranches, TES4ElseSubBranch $branchElse, $end) {
         return new TES4Branch($branchStart, $subbranches, $branchElse);
     });
     $this('BranchElse')->is('BranchElseToken', 'Code+')->call(function ($branchElseToken, TES4CodeChunks $code) {
         return new TES4ElseSubBranch($code);
     })->is('BranchElseToken')->call(function ($branchElseToken) {
         return new TES4ElseSubBranch(null);
     });
     $this('BranchStart')->is('BranchStartToken', 'Value', 'NWL', 'Code+')->call(function ($branchStart, TES4Value $expression, $newLine, TES4CodeChunks $code) {
         return new TES4SubBranch($expression, $code);
     })->is('BranchStartToken', 'Value', 'NWL')->call(function ($branchStart, TES4Value $expression, $newLine) {
         return new TES4SubBranch($expression, null);
     });
     $this('BranchSubBranch+')->is('BranchSubBranch+', 'BranchSubBranch')->call(function (TES4SubBranchList $list, TES4SubBranch $branchSubBranchDeclaration) {
         $list->add($branchSubBranchDeclaration);
         return $list;
     })->is('BranchSubBranch')->call(function (TES4SubBranch $branchSubBranchDeclaration) {
         $list = new TES4SubBranchList();
         $list->add($branchSubBranchDeclaration);
         return $list;
     });
     $this('BranchSubBranch')->is('BranchElseifToken', 'Value', 'NWL', 'Code+')->call(function ($branchElseif, TES4Value $expression, $nwl, TES4CodeChunks $codeChunks) {
         return new TES4SubBranch($expression, $codeChunks);
     })->is('BranchElseifToken', 'Value', 'NWL')->call(function ($branchElseif, TES4Value $expression, $nwl) {
         return new TES4SubBranch($expression, null);
     });
     $this('MathOperator')->is('==')->call(function (CommonToken $operator) {
         return TES4ArithmeticExpressionOperator::memberByValue($operator->getValue());
     })->is('!=')->call(function (CommonToken $operator) {
         return TES4ArithmeticExpressionOperator::memberByValue($operator->getValue());
     })->is('>')->call(function (CommonToken $operator) {
         return TES4ArithmeticExpressionOperator::memberByValue($operator->getValue());
     })->is('<')->call(function (CommonToken $operator) {
         return TES4ArithmeticExpressionOperator::memberByValue($operator->getValue());
     })->is('<=')->call(function (CommonToken $operator) {
         return TES4ArithmeticExpressionOperator::memberByValue($operator->getValue());
     })->is('>=')->call(function (CommonToken $operator) {
         return TES4ArithmeticExpressionOperator::memberByValue($operator->getValue());
     });
     $this('LogicalOperator')->is('||')->call(function (CommonToken $operator) {
         return TES4LogicalExpressionOperator::memberByValue($operator->getValue());
     })->is('&&')->call(function (CommonToken $operator) {
         return TES4LogicalExpressionOperator::memberByValue($operator->getValue());
     });
     $this('Value')->is('Value', 'LogicalOperator', 'NotLogicalValue')->call(function (TES4Value $left, TES4LogicalExpressionOperator $operator, TES4Value $right) {
         return new TES4LogicalExpression($left, $operator, $right);
     })->is('NotLogicalValue');
     $this('NotLogicalValue')->is('NotLogicalValue', 'MathOperator', 'NotLogicalAndBinaryValue')->call(function (TES4Value $left, TES4ArithmeticExpressionOperator $operator, TES4Value $right) {
         return new TES4ArithmeticExpression($left, $operator, $right);
     })->is('NotLogicalAndBinaryValue');
     $this('NotLogicalAndBinaryValue')->is('NotLogicalAndBinaryValue', 'BinaryOperator', 'NonExpressionValue')->call(function (TES4Value $left, TES4BinaryExpressionOperator $operator, TES4Value $right) {
         return new TES4BinaryExpression($left, $operator, $right);
     })->is('NonExpressionValue');
     $this('NonExpressionValue')->is('ObjectAccess')->is('Function')->is('APIToken')->is('Primitive');
     $this('BinaryOperator')->is('+')->call(function (CommonToken $operator) {
         return TES4BinaryExpressionOperator::memberByValue($operator->getValue());
     })->is('-')->call(function (CommonToken $operator) {
         return TES4BinaryExpressionOperator::memberByValue($operator->getValue());
     })->is('*')->call(function (CommonToken $operator) {
         return TES4BinaryExpressionOperator::memberByValue($operator->getValue());
     })->is('/')->call(function (CommonToken $operator) {
         return TES4BinaryExpressionOperator::memberByValue($operator->getValue());
     });
     $this('ObjectAccess')->is('ObjectCall')->is('ObjectProperty');
     $this('ObjectCall')->is('APIToken', 'TokenDelimiter', 'Function')->call(function (TES4ApiToken $apiToken, $delimiter, TES4Function $function) {
         return new TES4ObjectCall($apiToken, $function);
     });
     $this('ObjectProperty')->is('APIToken', 'TokenDelimiter', 'APIToken')->call(function (TES4ApiToken $apiToken, $delimiter, TES4ApiToken $nextApiToken) {
         return new TES4ObjectProperty($apiToken, $nextApiToken);
     });
     $this('SetValue')->is('SetInitialization', 'ObjectProperty', 'Value')->call(function ($setInitialization, TES4ObjectProperty $objectProperty, TES4Value $expression) {
         return new TES4VariableAssignation($objectProperty, $expression);
     })->is('SetInitialization', 'APIToken', 'Value')->call(function ($setInitialization, TES4ApiToken $apiToken, TES4Value $expression) {
         return new TES4VariableAssignation($apiToken, $expression);
     });
     $this('Function')->is('FunctionCall', 'FunctionArguments')->call(function ($functionCall, $functionArguments) {
         return new TES4Function($functionCall, $functionArguments);
     })->is('FunctionCall')->call(function ($functionCall) {
         return new TES4Function($functionCall, new TES4FunctionArguments());
     });
     $this('FunctionCall')->is('FunctionCallToken')->call(function (CommonToken $functionCall) {
         return new TES4FunctionCall($functionCall->getValue());
     });
     $this('APIToken')->is('ReferenceToken')->call(function (CommonToken $token) {
         return new TES4ApiToken($token->getValue());
     });
     $this('FunctionArguments')->is('FunctionArguments', 'FunctionParameter')->call(function (TES4FunctionArguments $list, TES4Value $value) {
         $list->add($value);
         return $list;
     })->is('FunctionParameter')->call(function (TES4Value $value) {
         $list = new TES4FunctionArguments();
         $list->add($value);
         return $list;
     });
     $this('FunctionParameter')->is('ObjectAccess')->is('Function')->is('APIToken')->is('Primitive');
     $this('Primitive')->is('Float')->call(function (CommonToken $float) {
         $floatValue = $float->getValue();
         if (substr((string) $floatValue, 0, 1) == ".") {
             $floatValue = "0" . $floatValue;
         }
         return new TES4Float((double) $floatValue);
     })->is('Integer')->call(function (CommonToken $integer) {
         return new TES4Integer($integer->getValue());
     })->is('Boolean')->call(function (CommonToken $integer) {
         if (strtolower($integer->getValue()) == "true") {
             return new TES4Integer(1);
         }
         return new TES4Integer(0);
     })->is('String')->call(function (CommonToken $string) {
         return new TES4String($string->getValue());
     });
     $this('Return')->is('ReturnToken', 'NWL')->call(function ($returnToken, $nwl) {
         return new TES4Return();
     })->is('ReturnToken')->call(function ($returnToken) {
         return new TES4Return();
     });
 }
 public function getType()
 {
     return TES4Type::T_STRING();
 }
 public function getType()
 {
     return TES4Type::T_FLOAT();
 }