typedef struct PSI_Token {
token_t type;
- unsigned size, line;
+ unsigned size, line, col;
char *text, *file;
char buf[1];
} PSI_Token;
struct decl_type *real;
struct decl_struct *strct;
struct decl_enum *enm;
+ struct decl *func;
} decl_type;
static inline decl_type *init_decl_type(token_t type, const char *name) {
T->text = &T->buf[0];
T->file = &T->buf[token_len + 1];
T->line = P->line;
+ T->col = P->col;
memcpy(T->text, P->tok, token_len);
memcpy(T->file, P->psi.file.fn, fname_len);
return T;
}
-static inline const char *PSI_TokenLocation(PSI_Token *t) {
- return t ? t->file : "<builtin>:0:0";
+static inline PSI_Token *PSI_TokenAppend(PSI_Token *T, unsigned argc, ...) {
+ va_list argv;
+ unsigned i;
+
+ va_start(argv, argc);
+ for (i = 0; i < argc; ++i) {
+ char *str = va_arg(argv, char *);
+ size_t str_len = strlen(str), token_len = T->size, fname_len = strlen(T->file);
+
+ T = realloc(T, PSI_TokenAllocSize(T->size += str_len + 1, fname_len));
+ T->text = &T->buf[0];
+ T->file = &T->buf[T->size + 1];
+ T->buf[token_len] = ' ';
+ memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
+ memcpy(&T->buf[token_len + 1], str, str_len + 1);
+ }
+ va_end(argv);
+
+ return T;
+}
+
+static inline PSI_Token *PSI_TokenTranslit(PSI_Token *T, char *from, char *to) {
+ php_strtr(T->text, T->size, from, to, MIN(strlen(from), strlen(to)));
+ return T;
+}
+
+static inline uint64_t psi_hash(char *digest_buf, ...)
+{
+ uint64_t hash = 5381;
+ uint8_t c;
+ const uint8_t *ptr;
+ va_list argv;
+
+ va_start(argv, digest_buf);
+ while ((ptr = va_arg(argv, const uint8_t *))) {
+ while ((c = *ptr++)) {
+ hash = ((hash << 5) + hash) + c;
+ }
+ }
+ va_end(argv);
+
+ if (digest_buf) {
+ sprintf(digest_buf, "%" PRIx64, hash);
+ }
+
+ return hash;
+}
+
+static inline uint64_t PSI_TokenHash(PSI_Token *t, char *digest_buf) {
+ char loc_buf[48];
+
+ sprintf(loc_buf, "%u%u", t->line, t->col);
+ return psi_hash(digest_buf, t->file, loc_buf, NULL);
}
#define PSI_PARSER_DEBUG 0x1
#define ADDCOLS \
P->col += P->cur - P->tok
-#define NEWLINE \
+#define NEWLINE(label) \
P->col = 1; \
++P->line; \
- goto nextline
+ goto label
token_t PSI_ParserScan(PSI_Parser *P)
{
QUOTED_STRING = "\"" ([^\"])+ "\"";
NUMBER = [+-]? [0-9]* "."? [0-9]+ ([eE] [+-]? [0-9]+)?;
- ("#"|"//") .* "\n" { NEWLINE; }
+ "/*" { goto comment; }
+ ("#"|"//") .* "\n" { NEWLINE(nextline); }
"(" {RETURN(PSI_T_LPAREN);}
")" {RETURN(PSI_T_RPAREN);}
";" {RETURN(PSI_T_EOS);}
"-" {RETURN(PSI_T_MINUS);}
"/" {RETURN(PSI_T_SLASH);}
"..." {RETURN(PSI_T_ELLIPSIS);}
- [\r\n] { NEWLINE; }
+ [\r\n] { NEWLINE(nextline); }
[\t ]+ { continue; }
'TRUE' {RETURN(PSI_T_TRUE);}
'FALSE' {RETURN(PSI_T_FALSE);}
'FUNCTION' {RETURN(PSI_T_FUNCTION);}
'TYPEDEF' {RETURN(PSI_T_TYPEDEF);}
'STRUCT' {RETURN(PSI_T_STRUCT);}
+ 'UNION' {RETURN(PSI_T_UNION);}
'ENUM' {RETURN(PSI_T_ENUM);}
'CONST' {RETURN(PSI_T_CONST);}
'LIB' {RETURN(PSI_T_LIB);}
QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);}
[^] {break;}
*/
+
+ comment:
+ P->tok = P->cur;
+ /*!re2c
+ "\n" { NEWLINE(comment); }
+ "*" "/" { continue; }
+ [^] { goto comment; }
+ */
}
return -1;
}
#define PSI_T_RETURN 10
#define PSI_T_LIB 11
#define PSI_T_STRING 12
-#define PSI_T_EOF 13
-#define PSI_T_EOS 14
-#define PSI_T_QUOTED_STRING 15
-#define PSI_T_ENUM 16
-#define PSI_T_LBRACE 17
-#define PSI_T_RBRACE 18
-#define PSI_T_COMMA 19
-#define PSI_T_EQUALS 20
-#define PSI_T_STRUCT 21
-#define PSI_T_COLON 22
-#define PSI_T_LPAREN 23
-#define PSI_T_NUMBER 24
-#define PSI_T_RPAREN 25
-#define PSI_T_BOOL 26
-#define PSI_T_INT 27
-#define PSI_T_FLOAT 28
-#define PSI_T_CONST 29
-#define PSI_T_NSNAME 30
-#define PSI_T_TYPEDEF 31
-#define PSI_T_VOID 32
-#define PSI_T_LBRACKET 33
-#define PSI_T_RBRACKET 34
-#define PSI_T_ELLIPSIS 35
-#define PSI_T_CHAR 36
-#define PSI_T_SHORT 37
-#define PSI_T_LONG 38
-#define PSI_T_DOUBLE 39
-#define PSI_T_UNSIGNED 40
-#define PSI_T_SIGNED 41
-#define PSI_T_INT8 42
-#define PSI_T_UINT8 43
-#define PSI_T_INT16 44
-#define PSI_T_UINT16 45
-#define PSI_T_INT32 46
-#define PSI_T_UINT32 47
-#define PSI_T_INT64 48
-#define PSI_T_UINT64 49
-#define PSI_T_FUNCTION 50
-#define PSI_T_NULL 51
-#define PSI_T_TRUE 52
-#define PSI_T_FALSE 53
-#define PSI_T_DOLLAR 54
-#define PSI_T_CALLOC 55
-#define PSI_T_OBJVAL 56
-#define PSI_T_ARRVAL 57
-#define PSI_T_PATHVAL 58
-#define PSI_T_STRLEN 59
-#define PSI_T_STRVAL 60
-#define PSI_T_FLOATVAL 61
-#define PSI_T_INTVAL 62
-#define PSI_T_BOOLVAL 63
-#define PSI_T_TO_OBJECT 64
-#define PSI_T_TO_ARRAY 65
-#define PSI_T_TO_STRING 66
-#define PSI_T_TO_INT 67
-#define PSI_T_TO_FLOAT 68
-#define PSI_T_TO_BOOL 69
-#define PSI_T_MIXED 70
-#define PSI_T_ARRAY 71
-#define PSI_T_OBJECT 72
-#define PSI_T_AMPERSAND 73
+#define PSI_T_STRUCT 13
+#define PSI_T_UNION 14
+#define PSI_T_EOF 15
+#define PSI_T_EOS 16
+#define PSI_T_QUOTED_STRING 17
+#define PSI_T_ENUM 18
+#define PSI_T_LBRACE 19
+#define PSI_T_RBRACE 20
+#define PSI_T_COMMA 21
+#define PSI_T_EQUALS 22
+#define PSI_T_COLON 23
+#define PSI_T_LPAREN 24
+#define PSI_T_NUMBER 25
+#define PSI_T_RPAREN 26
+#define PSI_T_BOOL 27
+#define PSI_T_INT 28
+#define PSI_T_FLOAT 29
+#define PSI_T_CONST 30
+#define PSI_T_NSNAME 31
+#define PSI_T_TYPEDEF 32
+#define PSI_T_VOID 33
+#define PSI_T_LBRACKET 34
+#define PSI_T_RBRACKET 35
+#define PSI_T_ELLIPSIS 36
+#define PSI_T_CHAR 37
+#define PSI_T_SHORT 38
+#define PSI_T_LONG 39
+#define PSI_T_DOUBLE 40
+#define PSI_T_UNSIGNED 41
+#define PSI_T_SIGNED 42
+#define PSI_T_INT8 43
+#define PSI_T_UINT8 44
+#define PSI_T_INT16 45
+#define PSI_T_UINT16 46
+#define PSI_T_INT32 47
+#define PSI_T_UINT32 48
+#define PSI_T_INT64 49
+#define PSI_T_UINT64 50
+#define PSI_T_FUNCTION 51
+#define PSI_T_NULL 52
+#define PSI_T_TRUE 53
+#define PSI_T_FALSE 54
+#define PSI_T_DOLLAR 55
+#define PSI_T_CALLOC 56
+#define PSI_T_OBJVAL 57
+#define PSI_T_ARRVAL 58
+#define PSI_T_PATHVAL 59
+#define PSI_T_STRLEN 60
+#define PSI_T_STRVAL 61
+#define PSI_T_FLOATVAL 62
+#define PSI_T_INTVAL 63
+#define PSI_T_BOOLVAL 64
+#define PSI_T_TO_OBJECT 65
+#define PSI_T_TO_ARRAY 66
+#define PSI_T_TO_STRING 67
+#define PSI_T_TO_INT 68
+#define PSI_T_TO_FLOAT 69
+#define PSI_T_TO_BOOL 70
+#define PSI_T_MIXED 71
+#define PSI_T_ARRAY 72
+#define PSI_T_OBJECT 73
+#define PSI_T_AMPERSAND 74
%left PLUS MINUS.
%left SLASH ASTERISK.
%fallback NAME TEMP FREE SET LET RETURN LIB STRING.
+%fallback STRUCT UNION.
file ::= blocks.
P->enums = add_decl_enum(P->enums, e);
}
-enum_name(n) ::= ENUM NAME(N). {
+optional_name(n) ::= .{
+ n = NULL;
+}
+optional_name(n) ::= NAME(N). {
n = N;
}
+enum_name(n) ::= ENUM(E) optional_name(N). {
+ if (N) {
+ n = N;
+ free(E);
+ } else {
+ char digest[17];
+
+ PSI_TokenHash(E, digest);
+ n = PSI_TokenTranslit(PSI_TokenAppend(E, 1, digest), " ", "@");
+ }
+}
+
%type decl_enum {decl_enum *}
%destructor decl_enum {free_decl_enum($$);}
i->token = N;
}
-struct_name(n) ::= STRUCT NAME(N). {
- n = N;
+struct_name(n) ::= STRUCT(S) optional_name(N). {
+ if (N) {
+ n = N;
+ free(S);
+ } else {
+ char digest[17];
+
+ PSI_TokenHash(S, digest);
+ n = PSI_TokenTranslit(PSI_TokenAppend(S, 1, digest), " ", "@");
+ }
}
%type decl_struct_args_block {decl_args*}
decl_typedef(def) ::= TYPEDEF decl_typedef_body(def_) EOS. {
def = def_;
}
-%type decl_typedef_body {decl_typedef*}
-%destructor decl_typedef_body {free_decl_typedef($$);}
-decl_typedef_body(def) ::= struct_name(N) struct_size(size_) decl_struct_args_block(args) NAME(ALIAS). {
+%type decl_typedef_body_ex {decl_typedef*}
+%destructor decl_typedef_body_ex {free_decl_typedef($$);}
+decl_typedef_body_ex(def) ::= struct_name(N) struct_size(size_) decl_struct_args_block(args) NAME(ALIAS). {
def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_STRUCT, N->text));
def->token = ALIAS;
+ def->type->token = PSI_TokenCopy(N);
def->type->strct = init_decl_struct(N->text, args);
def->type->strct->token = N;
def->type->strct->size = size_;
}
+decl_typedef_body_ex(def) ::= decl_enum(e) NAME(ALIAS). {
+ def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_ENUM, e->name));
+ def->type->token = PSI_TokenCopy(e->token);
+ def->token = ALIAS;
+ def->type->enm = e;
+}
+%type decl_typedef_body {decl_typedef*}
+%destructor decl_typedef_body {free_decl_typedef($$);}
+decl_typedef_body(def) ::= decl_typedef_body_ex(def_). {
+ def = def_;
+}
decl_typedef_body(def) ::= decl_type(type) NAME(ALIAS). {
def = init_decl_typedef(ALIAS->text, type);
def->token = ALIAS;
def->token = ALIAS;
def->type->token = V;
}
+decl_typedef_body(def) ::= decl_func(func) LPAREN decl_args(args) RPAREN. {
+ def = init_decl_typedef(func->var->name, init_decl_type(PSI_T_FUNCTION, func->var->name));
+ def->type->token = PSI_TokenCopy(func->token);
+ def->type->func = init_decl(init_decl_abi("default"), func, args);
+ def->token = PSI_TokenCopy(func->token);
+}
%type decl {decl*}
%destructor decl {free_decl($$);}
}
%type struct_arg {decl_arg*}
%destructor struct_arg {free_decl_arg($$);}
+struct_arg(arg_) ::= decl_typedef_body_ex(def) EOS. {
+ arg_ = init_decl_arg(def->type, init_decl_var(def->alias, 0, 0));
+ arg_->var->arg = arg_;
+ arg_->token = PSI_TokenCopy(def->type->token);
+ arg_->var->token = def->token;
+ free(def->alias);
+ free(def);
+}
struct_arg(arg) ::= decl_arg(arg_) struct_layout(layout_) EOS. {
arg_->layout = layout_;
arg = arg_;