Adding initial interfaces support

This commit is contained in:
Pavel Shevaev 2022-05-18 13:12:26 +03:00
parent dfe29ddf3c
commit 317f67c782
1 changed files with 152 additions and 58 deletions

View File

@ -392,6 +392,50 @@ class mtgMetaStruct extends mtgUserType
}
}
class mtgMetaInterface extends mtgUserType
{
protected $funcs = array();
protected $implements = null;
function __construct($name, array $implements = array(), $tokens = array())
{
parent::__construct($name);
$this->implements = $implements;
$this->tokens = $tokens;
}
function getImplements()
{
return $this->parent ? $this->parent->resolve() : null;
}
function getFuncs()
{
return $this->funcs;
}
function addFunc(mtgMetaFunc $fn)
{
if($this->hasFunc($fn->getName()))
throw new Exception("Interface '{$this->name}' already has func '{$fn->getName()}'");
$this->funcs[$fn->getName()] = $fn;
}
function hasFunc($name)
{
return isset($this->funcs[$name]);
}
function getFunc($name)
{
if(!isset($this->funcs[$name]))
throw new Exception("No such funcs '$name'");
return $this->funcs[$name];
}
}
class mtgMetaFunc extends mtgMetaUnit implements mtgType
{
private $name;
@ -740,30 +784,32 @@ class mtgMetaInfoParser
private $idltypes = array();
private $token_strs = array();
const T_EOF = 1001;
const T_StringConstant = 1002;
const T_IntegerConstant = 1003;
const T_FloatConstant = 1004;
const T_Enum = 1005;
const T_RPC = 1006;
const T_End = 1007;
const T_Identifier = 1008;
const T_Struct = 1009;
const T_Prop = 1010;
const T_Extends = 1011;
const T_Func = 1012;
const T_string = 1020;
const T_uint32 = 1021;
const T_int32 = 1022;
const T_uint16 = 1023;
const T_int16 = 1024;
const T_uint8 = 1025;
const T_int8 = 1026;
const T_float = 1027;
const T_uint64 = 1028;
const T_int64 = 1029;
const T_bool = 1030;
const T_blob = 1031;
const T_EOF = 1001;
const T_StringConstant = 1002;
const T_IntegerConstant = 1003;
const T_FloatConstant = 1004;
const T_Enum = 1005;
const T_RPC = 1006;
const T_End = 1007;
const T_Identifier = 1008;
const T_Struct = 1009;
const T_Prop = 1010;
const T_Extends = 1011;
const T_Func = 1012;
const T_RawStringConstant = 1013;
const T_Interface = 1014;
const T_string = 1020;
const T_uint32 = 1021;
const T_int32 = 1022;
const T_uint16 = 1023;
const T_int16 = 1024;
const T_uint8 = 1025;
const T_int8 = 1026;
const T_float = 1027;
const T_uint64 = 1028;
const T_int64 = 1029;
const T_bool = 1030;
const T_blob = 1031;
function __construct($config = array())
{
@ -789,6 +835,7 @@ class mtgMetaInfoParser
$this->token_strs = array_flip($this->idltypes);
$this->token_strs[self::T_EOF] = '<EOF>';
$this->token_strs[self::T_StringConstant] = '<StringConstant>';
$this->token_strs[self::T_RawStringConstant] = '<RawStringConstant>';
$this->token_strs[self::T_IntegerConstant] = '<IntegerConstant>';
$this->token_strs[self::T_FloatConstant] = '<FloatConstant>';
$this->token_strs[self::T_Enum] = '<enum>';
@ -796,6 +843,7 @@ class mtgMetaInfoParser
$this->token_strs[self::T_End] = '<end>';
$this->token_strs[self::T_Identifier] = '<Identifier>';
$this->token_strs[self::T_Struct] = '<struct>';
$this->token_strs[self::T_Interface] = '<interface>';
$this->token_strs[self::T_Prop] = '<@prop>';
$this->token_strs[self::T_Extends] = '<extends>';
$this->token_strs[self::T_Func] = '<func>';
@ -865,6 +913,8 @@ class mtgMetaInfoParser
$this->_parseEnum();
else if($this->token == self::T_Struct)
$this->_parseStruct();
else if($this->token == self::T_Interface)
$this->_parseInterface();
else if($this->token == self::T_Func)
$this->_parseFreeFunc();
else if($this->token == self::T_RPC)
@ -886,19 +936,20 @@ class mtgMetaInfoParser
while(true)
{
$type = null;
$type_name = $this->attribute;
if($this->token == self::T_Identifier)
{
$type = new mtgTypeRef($type_name, $this->current_meta, $this->file, $this->line);
$this->_next();
}
else if($this->token == self::T_Func)
if($this->token == self::T_Func)
{
$func_type = $this->_parseFuncType();
$type = new mtgTypeRef($func_type);
}
else if($this->token == self::T_Identifier)
{
$type_name = $this->_parseDotName();
$type = new mtgTypeRef($type_name, $this->current_meta, $this->file, $this->line);
}
else
{
$type_name = $this->attribute;
$type = new mtgTypeRef(new mtgBuiltinType($type_name));
$this->_next();
}
@ -1019,7 +1070,7 @@ class mtgMetaInfoParser
{
$this->_next();
$name = $this->_checkThenNext(self::T_Identifier);
$name = $this->_parseDotName();
$enum = new mtgMetaEnum($name);
$this->current_meta->addUnit(new mtgMetaInfoUnit($this->file, $enum));
@ -1073,9 +1124,7 @@ class mtgMetaInfoParser
$fld = new mtgMetaField($name, $type);
if($this->token == self::T_Prop)
{
$fld->setTokens($this->_parsePropTokens());
}
$flds[] = $fld;
}
@ -1112,15 +1161,31 @@ class mtgMetaInfoParser
return $funcs;
}
private function _parseDotName()
{
$dot_name = '';
while(true)
{
if($this->token != self::T_Identifier)
$this->_error("unexpected name token");
$dot_name .= $this->attribute;
$this->_next();
if($this->token != ord('.'))
break;
$dot_name .= '.';
$this->_next();
}
return $dot_name;
}
private function _parseFunc()
{
if($this->token != self::T_Identifier)
$this->_error("unexpected func token");
$name = $this->attribute;
$name = $this->_parseDotName();
$fn = new mtgMetaFunc($name);
$this->_next();
$this->_checkThenNext('(');
if($this->token == self::T_Prop)
$fn->setTokens($this->_parsePropTokens());
@ -1157,7 +1222,7 @@ class mtgMetaInfoParser
private function _parseStruct()
{
$this->_next();
$name = $this->_checkThenNext(self::T_Identifier);
$name = $this->_parseDotName();
$parent = null;
if($this->token == self::T_Extends)
@ -1171,9 +1236,7 @@ class mtgMetaInfoParser
$this->current_meta->addUnit(new mtgMetaInfoUnit($this->file, $s));
if($this->token == self::T_Prop)
{
$s->setTokens($this->_parsePropTokens());
}
$seen_funcs = false;
$flds = $this->_parseFields(
@ -1199,6 +1262,23 @@ class mtgMetaInfoParser
}
}
private function _parseInterface()
{
$this->_next();
$name = $this->_parseDotName();
$s = new mtgMetaInterface($name);
$this->current_meta->addUnit(new mtgMetaInfoUnit($this->file, $s));
if($this->token == self::T_Prop)
$s->setTokens($this->_parsePropTokens());
$this->_next();
$funcs = $this->_parseFuncs();
foreach($funcs as $fn)
$s->addFunc($fn);
}
private function _parseRPC()
{
$this->_next();
@ -1254,13 +1334,15 @@ class mtgMetaInfoParser
$this->_next();
break;
}
$tmp = $this->attribute;
if($this->token == self::T_StringConstant)
$tmp = "\"$tmp\"";
if($value === null)
$value = '';
$value .= $tmp;
else
{
$tmp = $this->attribute;
if($this->token == self::T_StringConstant)
$tmp = "\"$tmp\"";
if($value === null)
$value = '';
$value .= $tmp;
}
}
}
if($value && substr($value, 0, 1) == '{')
@ -1273,12 +1355,12 @@ class mtgMetaInfoParser
}
}
$this->_validatePropToken($name, $value);
$prop_tokens[$name] = $value;
}
return $prop_tokens;
}
private function _validatePropToken($name, $value)
{
if(!isset($this->config['valid_tokens']) || !$this->config['valid_tokens'])
@ -1354,6 +1436,17 @@ class mtgMetaInfoParser
$this->cursor++;
return;
case '`':
$this->attribute = "";
while($this->_symbol() != '`')
{
$this->attribute .= $this->_symbol();
$this->cursor++;
}
$this->token = self::T_RawStringConstant;
$this->cursor++;
return;
case '/':
if($this->_symbol() == '/')
{
@ -1398,12 +1491,13 @@ class mtgMetaInfoParser
}
//check for declaration keywords:
if($this->attribute == "struct") { $this->token = self::T_Struct; return; }
if($this->attribute == "enum") { $this->token = self::T_Enum; return; }
if($this->attribute == "RPC") { $this->token = self::T_RPC; return; }
if($this->attribute == "end") { $this->token = self::T_End; return; }
if($this->attribute == "extends") { $this->token = self::T_Extends; return; }
if($this->attribute == "func") { $this->token = self::T_Func; return; }
if($this->attribute == "struct") { $this->token = self::T_Struct; return; }
if($this->attribute == "interface") { $this->token = self::T_Interface; return; }
if($this->attribute == "enum") { $this->token = self::T_Enum; return; }
if($this->attribute == "RPC") { $this->token = self::T_RPC; return; }
if($this->attribute == "end") { $this->token = self::T_End; return; }
if($this->attribute == "extends") { $this->token = self::T_Extends; return; }
if($this->attribute == "func") { $this->token = self::T_Func; return; }
//if not it's a user defined identifier
$this->token = self::T_Identifier;
@ -1979,7 +2073,7 @@ function mtg_run(mtgGenerator $gen, array $config)
foreach($targets as $t)
$t->execute();
$METAGEN_CONFIG = $config_copy;
}