Add parsing functions.

This commit is contained in:
David Anderson
2014-06-26 21:05:19 -07:00
parent 99f4cdb3e4
commit b8bd7c517e
5 changed files with 301 additions and 89 deletions
+242 -82
View File
@@ -3242,70 +3242,6 @@ static void declstruct(void)
matchtoken(';'); /* eat up optional semicolon */
}
int parse_typeexpr(declinfo_t *decl, const token_t *first, int flags)
{
token_t tok;
if (first) {
tok = *first;
} else {
lextok(&tok);
}
if (tok.id == tCONST) {
decl->usage |= uCONST;
lextok(&tok);
}
if (tok.id == tLABEL && (flags & DECLFLAG_ONLY_NEW_TYPES)) {
error(120);
return FALSE;
}
if (tok.id == '[') {
error(121);
return FALSE;
}
switch (tok.id) {
case tINT:
strcpy(decl->type, "int");
decl->tag = 0;
break;
case tCHAR:
strcpy(decl->type, "char");
decl->tag = pc_tag_string;
break;
case tVOID:
strcpy(decl->type, "void");
decl->tag = pc_tag_void;
break;
case tOBJECT:
strcpy(decl->type, "object");
decl->tag = pc_tag_object;
break;
case tSYMBOL:
strcpy(decl->type, tok.str);
if (strcmp(decl->type, "float") == 0) {
decl->tag = sc_rationaltag;
} else {
decl->tag = pc_findtag(decl->type);
if (decl->tag == sc_rationaltag)
error(98, "Float", "float");
else if (decl->tag == pc_tag_string)
error(98, "String", "char");
else if (decl->tag == 0)
error(98, "_", "int");
}
break;
default:
error(122);
return FALSE;
}
return TRUE;
}
// Consumes a line, returns FALSE if EOF hit.
static int consume_line()
{
@@ -3326,18 +3262,240 @@ static int consume_line()
return TRUE;
}
// Parse a new-style declaration. If the name was already fetched (because we
// didn't have enough lookahead), it can be given ahead of time.
int parse_decl(declinfo_t *decl, const token_t *first, int flags)
static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
{
memset(decl, 0, sizeof(*decl));
token_t tok;
if (!parse_typeexpr(decl, first, flags))
if (first)
tok = *first;
else
lextok(&tok);
type->ident = iVARIABLE;
if (tok.id == tCONST) {
type->usage |= uCONST;
lextok(&tok);
}
if (tok.id == '[') {
// Not yet supported for return vals. This is allowed with old decls, but
// it's a huge hack. For now we forbid it in new code until it works right.
if (flags & TYPEFLAG_RETURN)
error(136);
while (tok.id == '[') {
if (type->numdim == sDIMEN_MAX) {
error(53);
break;
}
type->dim[type->numdim++] = 0;
if (!needtoken(']'))
return FALSE;
lextok(&tok);
}
type->ident = iARRAY;
}
switch (tok.id) {
case tINT:
strcpy(type->type, "int");
type->tag = 0;
break;
case tCHAR:
strcpy(type->type, "char");
type->tag = pc_tag_string;
break;
case tVOID:
strcpy(type->type, "void");
type->tag = pc_tag_void;
break;
case tOBJECT:
strcpy(type->type, "object");
type->tag = pc_tag_object;
break;
case tSYMBOL:
strcpy(type->type, tok.str);
if (strcmp(type->type, "float") == 0) {
type->tag = sc_rationaltag;
} else {
type->tag = pc_findtag(type->type);
if (type->tag == sc_rationaltag)
error(98, "Float", "float");
else if (type->tag == pc_tag_string)
error(98, "String", "char");
else if (type->tag == 0)
error(98, "_", "int");
}
break;
default:
error(122);
return FALSE;
}
if (flags & TYPEFLAG_ARGUMENT) {
if (matchtoken('&')) {
if (type->ident == iARRAY) {
error(137);
return FALSE;
}
type->ident = iREFERENCE;
}
}
type->tags[0] = type->tag;
type->numtags = 1;
return TRUE;
}
static void parse_old_array_dims(declinfo_t *decl, int flags)
{
typeinfo_t *type = &decl->type;
constvalue **enumrootp;
// Illegal declaration (we'll have a name since ref requires decl).
if (type->ident == iREFERENCE)
error(67, decl->name);
if (flags & TYPEFLAG_ENUMROOT)
enumrootp = &type->enumroot;
else
enumrootp = NULL;
do {
cell size;
if (type->numdim == sDIMEN_MAX) {
error(53);
return;
}
size = needsub(&type->idxtag[type->numdim], enumrootp);
if (size > INT_MAX)
error(165);
type->dim[type->numdim++] = (int)size;
} while (matchtoken('['));
type->ident = iARRAY;
}
static int parse_old_decl(declinfo_t *decl, int flags)
{
token_t tok;
typeinfo_t *type = &decl->type;
type->ident = iVARIABLE;
if (matchtoken(tCONST))
type->usage |= uCONST;
if (flags & TYPEFLAG_ARGUMENT) {
if (matchtoken('&'))
type->ident = iREFERENCE;
// grammar for multitags is:
// multi-tag ::= '{' (symbol (',' symbol)*)? '}' ':'
if (matchtoken('{')) {
while (type->numtags < MAXTAGS) {
int tag = 0;
if (!matchtoken('_')) {
// If we don't get the magic tag '_', then we should have a symbol.
if (expecttoken(tSYMBOL, &tok))
tag = pc_addtag(tok.str);
}
type->tags[type->numtags++] = tag;
if (matchtoken('}'))
break;
needtoken(',');
}
needtoken(':');
}
} else {
if (matchtoken2(tLABEL, &tok))
type->tags[type->numtags++] = pc_addtag(tok.str);
}
if (flags & TYPEMASK_NAMED_DECL) {
if (expecttoken(tSYMBOL, &tok))
strcpy(decl->name, tok.str);
else
strcpy(decl->name, "<unknown>");
}
if ((flags & TYPEMASK_NAMED_DECL) && !(flags & TYPEFLAG_NO_POSTDIMS)) {
if (matchtoken('['))
parse_old_array_dims(decl, flags);
}
type->tag = type->tags[0];
return TRUE;
}
static int parse_new_decl(declinfo_t *decl, int flags)
{
token_t tok;
if (!parse_new_typeexpr(&decl->type, NULL, flags))
return FALSE;
if (!expecttoken(tSYMBOL, &tok))
return FALSE;
strcpy(decl->name, tok.str);
if ((flags & TYPEMASK_NAMED_DECL) && !(flags & TYPEFLAG_NO_POSTDIMS)) {
if (matchtoken('[')) {
if (decl->type.numdim == 0)
parse_old_array_dims(decl, flags);
else
error(121);
}
}
return TRUE;
}
// Parse a declaration.
//
// Grammar for named declarations is:
// "const"? symbol ('[' ']')* '&'? symbol
// | "const"? label? '&'? symbol '[' ']'
//
int parse_decl(declinfo_t *decl, int flags)
{
token_t tok;
memset(decl, 0, sizeof(*decl));
// If parsing an argument, there are two simple checks for whether this is a
// new or old-style declaration.
if ((flags & TYPEFLAG_ARGUMENT) && (lexpeek('&') || lexpeek('{')))
return parse_old_decl(decl, flags);
// Another dead giveaway is there being a label.
if (lexpeek(tLABEL))
return parse_old_decl(decl, flags);
// Otherwise, we have to eat a symbol to tell.
if (lextok(&tok) == tSYMBOL) {
if (lexpeek('[') || lexpeek(tSYMBOL)) {
// A new-style declaration only allows array dims or a symbol name, so
// this is a new-style declaration. Make sure to push back the first
// symbol.
lexpush();
return parse_new_decl(decl, flags);
}
// Push the symbol back, we've got an old-style decl.
lexpush();
return parse_old_decl(decl, flags);
}
// All else has failed. Probably got a type keyword. New-style.
return parse_new_decl(decl, flags);
}
void define_constructor(methodmap_t *map, methodmap_method_t *method)
{
symbol *sym = findglb(map->name, sGLOBAL);
@@ -3410,7 +3568,7 @@ void check_name_length(char *original)
}
}
symbol *parse_inline_function(methodmap_t *map, const declinfo_t *decl, const char *name, int is_native, int is_ctor, int is_dtor)
symbol *parse_inline_function(methodmap_t *map, const typeinfo_t *type, const char *name, int is_native, int is_ctor, int is_dtor)
{
funcstub_setup_t setup;
if (is_dtor)
@@ -3418,7 +3576,7 @@ symbol *parse_inline_function(methodmap_t *map, const declinfo_t *decl, const ch
else if (is_ctor)
setup.return_tag = map->tag;
else
setup.return_tag = decl->tag;
setup.return_tag = type->tag;
if (is_ctor)
setup.this_tag = -1;
@@ -3474,7 +3632,7 @@ int check_this_tag(methodmap_t *map, symbol *target)
return ok;
}
int parse_property_accessor(const declinfo_t *decl, methodmap_t *map, methodmap_method_t *method)
int parse_property_accessor(const typeinfo_t *type, methodmap_t *map, methodmap_method_t *method)
{
token_ident_t ident;
int is_native = FALSE;
@@ -3517,7 +3675,7 @@ int parse_property_accessor(const declinfo_t *decl, methodmap_t *map, methodmap_
char tmpname[METHOD_NAMEMAX + 1];
strcpy(tmpname, method->name);
strcat(tmpname, ".get");
target = parse_inline_function(map, decl, tmpname, is_native, FALSE, FALSE);
target = parse_inline_function(map, type, tmpname, is_native, FALSE, FALSE);
}
if (!target)
@@ -3537,9 +3695,9 @@ int parse_property_accessor(const declinfo_t *decl, methodmap_t *map, methodmap_
}
// Must return the same tag as the property.
if (decl->tag != target->tag) {
if (type->tag != target->tag) {
const char *kind = getter ? "getter" : "setter";
error(128, "getter", map->name, decl->type);
error(128, "getter", map->name, type->type);
}
if (!check_this_tag(map, target)) {
@@ -3553,11 +3711,12 @@ int parse_property_accessor(const declinfo_t *decl, methodmap_t *map, methodmap_
methodmap_method_t *parse_property(methodmap_t *map)
{
declinfo_t decl;
typeinfo_t type;
token_ident_t ident;
methodmap_method_t *method;
if (!parse_decl(&decl, NULL, DECLFLAG_ONLY_NEW_TYPES))
memset(&type, 0, sizeof(type));
if (!parse_new_typeexpr(&type, NULL, TYPEFLAG_RETURN))
return NULL;
if (!needsymbol(&ident))
return NULL;
@@ -3573,7 +3732,7 @@ methodmap_method_t *parse_property(methodmap_t *map)
return method;
while (!matchtoken('}')) {
if (!parse_property_accessor(&decl, map,method)) {
if (!parse_property_accessor(&type, map,method)) {
if (!consume_line())
return NULL;
}
@@ -3601,8 +3760,10 @@ methodmap_method_t *parse_method(methodmap_t *map)
token_ident_t bindsource;
strcpy(bindsource.name, "<unknown>");
typeinfo_t type;
memset(&type, 0, sizeof(type));
token_t tok;
declinfo_t decl;
if (matchtoken('~')) {
// We got something like "public ~Blah = X"
is_bind = TRUE;
@@ -3657,7 +3818,7 @@ methodmap_method_t *parse_method(methodmap_t *map)
// Parse for type expression, priming it with the token we predicted
// would be an identifier.
if (!parse_decl(&decl, first, DECLFLAG_ONLY_NEW_TYPES))
if (!parse_new_typeexpr(&type, first, TYPEFLAG_RETURN))
return NULL;
// Now, we should get an identifier.
@@ -3697,7 +3858,7 @@ methodmap_method_t *parse_method(methodmap_t *map)
else if (target->ident != iFUNCTN)
error(10);
} else {
target = parse_inline_function(map, &decl, ident.name, is_native, is_ctor, is_dtor);
target = parse_inline_function(map, &type, ident.name, is_native, is_ctor, is_dtor);
}
if (!target)
@@ -5156,7 +5317,6 @@ static int argcompare(arginfo *a1,arginfo *a2)
*/
static int declargs(symbol *sym, int chkshadow, const int *thistag)
{
#define MAXTAGS 16
char *ptr;
int argcnt,oldargcnt,tok,tags[MAXTAGS],numtags;
cell val;