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(); }