예제 #1
1
static struct block *cast_expression(struct block *block)
{
    struct typetree *type;
    struct token tok;
    struct symbol *sym;

    /* This rule needs two lookahead; to see beyond the initial parenthesis if
     * it is actually a cast or an expression. */
    if (peek().token == '(') {
        tok = peekn(2);
        switch (tok.token) {
        case IDENTIFIER:
            sym = sym_lookup(&ns_ident, tok.strval);
            if (!sym || sym->symtype != SYM_TYPEDEF)
                break;
        case FIRST(type_name):
            consume('(');
            type = declaration_specifiers(NULL);
            if (peek().token != ')') {
                type = declarator(type, NULL);
            }
            consume(')');
            block = cast_expression(block);
            block->expr = eval_cast(block, block->expr, type);
            return block;
        default:
            break;
        }
    }

    return unary_expression(block);
}
예제 #2
1
파일: parser.c 프로젝트: mdiaztello/zcc
TOKEN parameter_declaration(void)
{
    SYMBOL s = symalloc();
    TOKEN dec = NULL;
    declaration_specifiers(s);
    dec = declarator(s);
    set_token_symbol_type(dec,s);

    return dec;
}
예제 #3
0
void declaratorlist(void){
		declarator();	   
		while(lookahead == ','){
	     match(',');
        declarator();
		}
}
예제 #4
0
파일: parser.c 프로젝트: palmerc/lab
int function_definition(void) {
	if( declaration_specifiers() ) {
		declarator();
		
		if( declaration_list() ) {
		}
	} else if ( declarator() ) {
		if(	declaration_list() ) {
		}
	} else {
		abort();
	}
	compound_statement();
}
예제 #5
0
/**

形参列表
<parameter_type_list>::=<type_specifier>{<declarator>}
    {<TK_COMMA><type_specifier>{<declarator>}}<TK_COMMA><TK_ELLIPSIS>
*/
void parameter_type_list(){
    int func_call;          /// 原书将这个变量当做参数
    get_token();
    while(TK_CLOSEPA != token){
        if(!type_specifier())
            error("invalid identifier");
        declarator();
        if(TK_CLOSEPA == token)
            break;
        skip(TK_COMMA);
        if(TK_ELLIPSIS == token){
            func_call = KW_CDECL;
            get_token();
            break;
        }
    }
    syntax_state = SNTX_DELAY;
    skip(TK_CLOSEPA);
	get_token();
    if(TK_BEGIN == token)   /// define function
        syntax_state = SNTX_LF_HT;
    else
        syntax_state = SNTX_NUL;
    syntax_indent();
}
예제 #6
0
/**
	@brief 解析外部命令
	@param l 存储类型,局部的or全局的
*/
void external_declaration(int l){
	if(!type_specifier()){
		expect("<类型区分符>");
	}
	if(token == TK_SEMICOLON){
		get_token();
		return;
	}
	while(1){
		declarator();
		if(token == TK_BEGIN){
			if(l == SC_LOCAL){
				error("不支持函数嵌套定义");
			}
			funcbody();
			break;
		}else{
			if(token == TK_ASSIGN){
				get_token();
				initializer();
			}
			if(token == TK_COMMA){
				get_token();
			}else{
				syntax_state = SNTX_LE_HT;
				skip(TK_SEMICOLON);
				break;
			}
		}
	}
}
예제 #7
0
/**
外部声明
<external_declaration>::=<type_specifier>(<TK_SEMICOLON>
                                         |<declarator><funcbody>
                                         |<declarator>[<TK_ASSIGN><initializer>]
                                         {TK_COMMA><declarator>[<TK_ASSIGN><initializer>]}<TK_SEMICOLON>
                                          )
DO:parse external statement
storage type:local | global
*/
void external_declaration(int l){
    if(!type_specifier())
        expect("<Type specifier>");
    if(token == TK_SEMICOLON){
        get_token();
        return;
    }
    while(1){
        declarator();
        if(token == TK_BEGIN){
            if(l == SC_LOCAL)
                error("don't support function nesting define");
            funcbody();
            break;
        }else {
            if(token == TK_ASSIGN){
                get_token();
                initializer();
            }
            if(token == TK_COMMA)
                get_token();
            else{
                syntax_state = SNTX_LF_HT;
                skip(TK_SEMICOLON);
                break;
            }
        }
    }
}
예제 #8
0
파일: vparser.c 프로젝트: stakira/vinyl.js
int parameter_list(ParserState* ps) {
	if (curris(ps, PLParen)) {
		enterblk();

		while (ps->curr != 0) {
			VVar id;
			if (!declarator(ps, &id))
				parerr(ps, "invalid parameter syntax");

			if (curris(ps, PComma)) {
				Ast* comma = ps->curr;
				if (comma->next != 0) {
					ast_swap(comma, comma->next);
					ast_rmnext(comma);
				}
			}
			else if (ps->curr != 0) {
				parerr(ps, "expecting \',\' in parameter list");
			}
		}

		exitblk();
		return 1;
	}
	else return 0;
}
예제 #9
0
파일: parser.c 프로젝트: palmerc/lab
int init_declarator(void) {
	declarator();
	if( lookaheadT.type == EQUAL ) {
		match(EQUAL);
		initializer();
	}
}
예제 #10
0
int declaration(char* result)
{
    char token[MAXTOKEN];
    char token2[MAXTOKEN];
    bool is_const = false;
    int type = -1;
    int ret = 0;
    
    ret -= try_tokens_until(&type, token, try_declaration, try_declarator, 
                            "Missing data type to form a declaration");
    if (type == NAME) {
        if (gettoken(token2) == CONST) {
            // T const XXX
            is_const = true;
        } else {
            unget_token();
        }

    } else if (type == CONST) {
        is_const = true;
        ret -= try_tokens_until(&type, token, try_name, try_declarator,
                                "Missing data type to form a declaration");
    } 

    ret += declarator(result);
    strcat(result, " ");
    if (is_const) {
        strcat(result, "const ");
    }
    strcat(result, token);
    return ret;
}
예제 #11
0
파일: parse.c 프로젝트: xtao/c
static void
params(CTy *fty)
{
	int     sclass;
	CTy    *t;
	char   *name;
	SrcPos *pos;

	fty->Func.isvararg = 0;
	if(tok->k == ')')
		return;
	for(;;) {
		pos = &tok->pos;
		t = declspecs(&sclass);
		t = declarator(t, &name, 0);
		if(sclass != SCNONE)
			errorposf(pos, "storage class not allowed in parameter decl");
		vecappend(fty->Func.params, newnamety(name, t));
		if(tok->k != ',')
			break;
		next();
	}
	if(tok->k == TOKELLIPSIS) {
		fty->Func.isvararg = 1;
		next();
	}
}
예제 #12
0
/*----------------------------------------------------------------------------*/
void
c_semantic::free_declarator(c_context & context, c_token token)
{
    if (1 == options.verbose_flag) {
        printf("## c_semantic::free_declarator()\n\n");
    }

    if (NO_CLASS_STATUS !=
            context.class_specifier_status) {
        printf
        ("error c_semantic::free_declarator() NO_CLASS_STATUS !=	context.class_specifier_status\n\n");
        exit(-1);
    }

    c_declarator declarator(token, vector_decl_specifier);
    context.declarator = declarator;
    /*
      template <class myType>
      myType GetMax (myType a, myType b) {
        return (a>b?a:b);
      }
      we are in GetMax line ...
    */
    if ( TEMPLATE_DECLARATION == context.template_status ) {
        context.declarator.is_template = 1;
    }
}
예제 #13
0
파일: parse.c 프로젝트: xtao/c
static CTy *
directdeclarator(CTy *basety, char **name) 
{
	CTy *ty, *stub;

	*name = 0;
	switch(tok->k) {
	case '(':
		expect('(');
		stub = gcmalloc(sizeof(CTy));
		*stub = *basety;
		ty = declarator(stub, name, 0);
		expect(')');
		*stub = *declaratortail(basety);
		return ty;
	case TOKIDENT:
		if(name)
			*name = tok->v;
		next();
		return declaratortail(basety);
	default:
		if(!name)
			errorposf(&tok->pos, "expected ident or ( but got %s", tokktostr(tok->k));
		return declaratortail(basety);
	}
	errorf("unreachable");
	return 0;
}
예제 #14
0
파일: decl.c 프로젝트: JamesLinus/mcc
static void param_declarator(node_t ** ty, struct token **id)
{
    if (token->id == '*') {
        node_t *pty = ptr_decl();
        prepend_type(ty, pty);
    }

    if (token->id == '(') {
        if (first_decl(lookahead())) {
            abstract_declarator(ty);
        } else {
            node_t *type1 = *ty;
            node_t *rtype = NULL;
            expect('(');
            param_declarator(&rtype, id);
            expect(')');
            if (token->id == '(' || token->id == '[') {
                node_t *faty;
                cc_assert(id);
                if (*id) {
                    faty = func_or_array(false, NULL);
                } else {
                    faty = func_or_array(true, NULL);
                }
                attach_type(&faty, type1);
                attach_type(&rtype, faty);
            }
            *ty = rtype;
        }
    } else if (token->id == '[') {
        abstract_declarator(ty);
    } else if (token->id == ID) {
        declarator(ty, id, NULL);
    }
}
예제 #15
0
파일: parse.c 프로젝트: xtao/c
/* Declarator is what introduces names into the program. */
static CTy *
declarator(CTy *basety, char **name, Node **init) 
{
	CTy *t;

	while (tok->k == TOKCONST || tok->k == TOKVOLATILE)
		next();
	switch(tok->k) {
	case '*':
		next();
		basety = mkptr(basety);
		t = declarator(basety, name, init);
		return t;
	default:
		t = directdeclarator(basety, name);
		if(tok->k == '=') {
			if(!init)
				errorposf(&tok->pos, "unexpected initializer");
			next();
			*init = declinit();
		} else {
			if(init)
				*init = 0;
		}
		return t; 
	}

}
예제 #16
0
파일: vparser.c 프로젝트: stakira/vinyl.js
static int variable_decl(ParserState* ps) {
	Ast* rvar = ps->curr;
	if (stepifis(ps, RVar)) {
		int count = 0;
		while (count == 0 || curris(ps, PComma)) {
			if (stepifis(ps, PComma)) free(ast_rmnext(rvar));

			VVar id;
			if (declarator(ps, &id)) {
				ast_next_to_last_child(rvar);
			}
			else {
				parerr(ps, "invalid declarator");
				break;
			}
			count++;
		}

		if (!stepifis(ps, PSemi)) {
			parerr(ps, "expecting ',' or ';'");
		}

		return 1;
	}
	else return 0;
}
예제 #17
0
파일: parse.c 프로젝트: xtao/c
static Node *
decl()
{
	Node   *n, *init;
	char   *name;
	CTy    *type, *basety;
	SrcPos *pos;
	Sym    *sym;
	Vec    *syms;
	int     sclass;

	pos = &tok->pos;
	syms  = vec();
	basety = declspecs(&sclass);
	while(tok->k != ';' && tok->k != TOKEOF) {
		type = declarator(basety, &name, &init);
		switch(sclass){
		case SCNONE:
			if(isglobal()) {
				sclass = SCGLOBAL;
			} else {
				sclass = SCAUTO;
			}
			break;
		case SCTYPEDEF:
			if(init)
				errorposf(pos, "typedef cannot have an initializer");
			break;
		}
		if(!name)
			errorposf(pos, "decl needs to specify a name");
		sym = definesym(pos, sclass, name, type, init);
		vecappend(syms, sym);
		if(isglobal() && tok->k == '{') {
			if(init)
				errorposf(pos, "function declaration has an initializer");
			if(type->t != CFUNC)
				errorposf(pos, "expected a function");
			curfunc = mknode(NFUNC, pos);
			curfunc->type = type;
			curfunc->Func.name = name;
			curfunc->Func.params = vec();
			curfunc->Func.stkslots = vec();
			fbody();
			definesym(pos, sclass, name, type, curfunc);
			curfunc = 0;
			goto done;
		}
		if(tok->k == ',')
			next();
		else
			break;
	}
	expect(';');
  done:
	n = mknode(NDECL, pos);
	n->Decl.syms = syms;
	return n;
}
예제 #18
0
파일: parser.c 프로젝트: palmerc/lab
int struct_declarator(void) {
	if( declarator() ) {
	}
	if( lookaheadT.type == COLON ) {
		match(COLON);
		constant_expression();
	}
}
예제 #19
0
파일: decl.c 프로젝트: JamesLinus/mcc
static void fields(node_t * sym)
{
    int follow[] = {INT, CONST, '}', IF, 0};
    node_t *sty = SYM_TYPE(sym);

    if (!first_decl(token)) {
        error("expect type name or qualifiers");
        return;
    }

    struct vector *v = vec_new();
    do {
        node_t *basety = specifiers(NULL, NULL);

        for (;;) {
            node_t *field = new_field();
            if (token->id == ':') {
                bitfield(field);
                FIELD_TYPE(field) = basety;
            } else {
                node_t *ty = NULL;
                struct token *id = NULL;
                declarator(&ty, &id, NULL);
                attach_type(&ty, basety);
                if (token->id == ':')
                    bitfield(field);
                FIELD_TYPE(field) = ty;
                if (id) {
                    for (int i = 0; i < vec_len(v); i++) {
                        node_t *f = vec_at(v, i);
                        if (FIELD_NAME(f) &&
                                !strcmp(FIELD_NAME(f), id->name)) {
                            errorf(id->src,
                                   "redefinition of '%s'",
                                   id->name);
                            break;
                        }
                    }
                    FIELD_NAME(field) = id->name;
                    AST_SRC(field) = id->src;
                }
            }

            vec_push(v, field);
            if (token->id != ',')
                break;
            expect(',');
            ensure_field(field, vec_len(v), false);
        }

        match(';', follow);
        ensure_field(vec_tail(v), vec_len(v),
                     isstruct(sty) && !first_decl(token));
    } while (first_decl(token));

    TYPE_FIELDS(sty) = (node_t **) vtoa(v);
    set_typesize(sty);
}
예제 #20
0
/**
结构声明
<struct_declaration>::=
    <type_specifier><declarator>{<TK_COMMA><declarator>}
    <TK_SEMICOLON>
*/
void struct_declaration(){
    type_specifier();
    while(1){
        declarator();
        if(token == TK_SEMICOLON)
            break;
        skip(TK_COMMA);
    }
    syntax_state = SNTX_LF_HT;
    skip(TK_SEMICOLON);
}
예제 #21
0
/* Parse function and array declarators. Some trickery is needed to handle
 * declarations like `void (*foo)(int)`, where the inner *foo has to be 
 * traversed first, and prepended on the outer type `* (int) -> void` 
 * afterwards making it `* (int) -> void`.
 * The type returned from declarator has to be either array, function or
 * pointer, thus only need to check for type->next to find inner tail.
 */
static struct typetree *direct_declarator(
    struct typetree *base,
    const char **symbol)
{
    struct typetree *type = base;
    struct typetree *head, *tail = NULL;
    struct token ident;

    switch (peek().token) {
    case IDENTIFIER:
        ident = consume(IDENTIFIER);
        if (!symbol) {
            error("Unexpected identifier in abstract declarator.");
            exit(1);
        }
        *symbol = ident.strval;
        break;
    case '(':
        consume('(');
        type = head = tail = declarator(NULL, symbol);
        while (tail->next) {
            tail = (struct typetree *) tail->next;
        }
        consume(')');
        break;
    default:
        break;
    }

    while (peek().token == '[' || peek().token == '(') {
        switch (peek().token) {
        case '[':
            type = direct_declarator_array(base);
            break;
        case '(':
            consume('(');
            type = parameter_list(base);
            consume(')');
            break;
        default:
            assert(0);
        }
        if (tail) {
            tail->next = type;
            type = head;
        }
        base = type;
    }

    return type;
}
예제 #22
0
/*----------------------------------------------------------------------------*/
void c_semantic::identifier_typedef(c_context & context, c_token token)
{
    if (1 == options.verbose_flag) {
        printf("## void c_semantic::identifier_typedef(c_token token) token.text[%s]\n\n",token.text.c_str());
    }

    /*
      ## it must search in the stack

      stack 0
        class A{};

      stack 1
        int A;

      typedef class A t_A;

      typedef vector < c_decl_specifier > t_vector_decl_specifier;
    */

    if ( 0 != context.class_name_declaration.size() ) {
        c_symbol symbol(token);

        symbol.is_typedef = 1;
        symbol.typedef_points_to = context.class_name_declaration;
        symbol.type = TYPEDEF_NAME;

        if ( 1 == context.is_template_instantiation ) {
            symbol.is_template_instantiation = context.is_template_instantiation;
            symbol.vector_template_argument = context.vector_template_argument;
            symbol.map_template_argument    = context.map_template_argument;
        }

        ts.insert(symbol);
    }

    if (NO_CLASS_STATUS ==
            context.class_specifier_status) {
        c_declarator declarator(token, vector_decl_specifier);
        declarator.is_typedef = 1;

        if ( 1 == context.is_template_instantiation ) {
            declarator.is_template_instantiation = context.is_template_instantiation;
            declarator.vector_template_argument = context.vector_template_argument;
            declarator.map_template_argument    = context.map_template_argument;
        }
        context.declarator = declarator;
    }
}
예제 #23
0
/* Parse call to builtin symbol __builtin_va_arg, which is the result of calling
 * va_arg(arg, T). Return type depends on second input argument.
 */
static struct block *parse__builtin_va_arg(struct block *block)
{
    struct typetree *type;

    consume('(');
    block = assignment_expression(block);
    consume(',');
    type = declaration_specifiers(NULL);
    if (peek().token != ')') {
        type = declarator(type, NULL);
    }
    consume(')');
    block->expr = eval__builtin_va_arg(block, block->expr, type);
    return block;
}
예제 #24
0
파일: parser.c 프로젝트: mdiaztello/zcc
TOKEN init_declarator(SYMBOL s)
{
    TOKEN decl = declarator(s);
    TOKEN tok = peek_token();
    if(tok == NULL)
    {
        return NULL;
    }
    TOKEN initial_value = NULL;
    if(true == token_matches_operator(tok, ASSIGNMENT))
    {
        initial_value = NULL;//initializer();
    }
    return decl;
}
예제 #25
0
// Parse a concept definition.
//
//    concept-declaration:
//      'concept' identifier '<' template-parameter-list '>' concept-definition
//
// TODO: I'm not sure that I like this syntax. Maybe we should make
// concepts look like any other template:
//
//    template<typename T> concept C = ...
//
// Note that this would allow for non-template concepts as well:
//
//    concept C = X && Y && Z;
//
// The benefit to doing this is that C would now be usable as a constraint
// in non-function templates.
//
// FIXME: Make this happen.
Decl&
Parser::concept_declaration()
{
  Token tok = require(tk::concept_tok);
  Name& n = declarator();

  // Enter_template_parameter_scope pscope(cxt);
  match(tk::lt_tok);
  Decl_list ps = template_parameter_list();
  match(tk::gt_tok);

  // Point of declaration. Enter the associated context prior
  // to defininging the concept.
  Decl& con = on_concept_declaration(tok, n, ps);
  // Enter_scope cscope(cxt, cxt.make_concept_scope(con));
  concept_definition(con);
  return con;
}
예제 #26
0
파일: parser.c 프로젝트: palmerc/lab
int direct_declarator(void) {
	if( lookaheadT.type == ID ) {
		match(ID);
	} else if( lookaheadT.type == LPAREN ) {
		match(LPAREN);
		declarator();
		match(RPAREN);
	} else if( direct_declarator() ) {
		if( lookaheadT.type == LBRACKET ) {
			match(LBRACKET);
			if( constant_expression() ) {
			}
			match(RBRACKET);
		} else if( lookaheadT.type == LPAREN ) {
			match(LPAREN);
			if( parameter_type_list() ) {
			} else if ( identifier_list() ) {
			}
			match(RPAREN);
		}
	}
}
예제 #27
0
/* FOLLOW(parameter-list) = { ')' }, peek to return empty list; even though K&R
 * require at least specifier: (void)
 * Set parameter-type-list = parameter-list, including the , ...
 */
static struct typetree *parameter_list(const struct typetree *base)
{
    struct typetree *func = type_init(T_FUNCTION);
    func->next = base;

    while (peek().token != ')') {
        const char *name = NULL;
        struct typetree *type;

        type = declaration_specifiers(NULL);
        type = declarator(type, &name);
        if (is_void(type)) {
            if (nmembers(func)) {
                error("Incomplete type in parameter list.");
            }
            break;
        }

        type_add_member(func, name, type);
        if (peek().token != ',') {
            break;
        }

        consume(',');
        if (peek().token == ')') {
            error("Unexpected trailing comma in parameter list.");
            exit(1);
        } else if (peek().token == DOTS) {
            consume(DOTS);
            assert(!is_vararg(func));
            type_add_member(func, "...", NULL);
            assert(is_vararg(func));
            break;
        }
    }

    return func;
}
예제 #28
0
파일: decl.c 프로젝트: JamesLinus/mcc
static void declarator(node_t ** ty, struct token **id, int *params)
{
    int follow[] = { ',', '=', IF, 0 };

    cc_assert(ty && id);

    if (token->id == '*') {
        node_t *pty = ptr_decl();
        prepend_type(ty, pty);
    }

    if (token->id == ID) {
        *id = token;
        expect(ID);
        if (token->id == '[' || token->id == '(') {
            node_t *faty = func_or_array(false, params);
            prepend_type(ty, faty);
        }
    } else if (token->id == '(') {
        node_t *type1 = *ty;
        node_t *rtype = NULL;
        expect('(');
        declarator(&rtype, id, params);
        match(')', follow);
        if (token->id == '[' || token->id == '(') {
            node_t *faty = func_or_array(false, params);
            attach_type(&faty, type1);
            attach_type(&rtype, faty);
        } else {
            attach_type(&rtype, type1);
        }
        *ty = rtype;
    } else {
        error("expect identifier or '('");
    }
}
예제 #29
0
int direct_declarator(char* result)
{
    char token[MAXTOKEN];
    int type = -1;
    int ret = 0;

    ret -= try_tokens_until(&type, token, try_direct_declarator,
                            try_func_array, "Missing declarator's name");
    if (type == '(') {
        ret += declarator(result);
        ret -= try_tokens_until(&type, token, try_right_paran, try_func_array,
                                "Missing ')' to close a declarator");
    } else if (type == NAME) {
        strcat(result, token);
        strcat(result, ":");
    }

    while (true) {
        type = gettoken(token);
        if (type == '[') {
            strcat(result, " array");
            ret -= try_tokens_until(&type, token, try_array, try_func_array,
                                    "Missing ']' to close an array");
            if (type == NUMBER) {
                strcat(result, "[");
                strcat(result, token);
                strcat(result, "]");
                ret -= try_tokens_until(&type, token, try_right_bracket, 
                                        try_func_array,
                                        "Missing ']' to close an array");
            }
            if (ret == 0) {
                strcat(result, " of");
            }
            
        } else if (type == '(') {
            strcat(result, " function");
            bool has_param = false;
            while (true) {
                ret -= try_tokens_until(&type, token, try_func_param, 
                                        try_func_array,
                                        "Missing ')' to close a function");
                if (try_declaration(type)) {
                    if (!has_param) {
                        strcat(result, " with parameter [");
                        has_param = true;
                    }
                    unget_token();
                    ret += declaration(result);
                    ret -= try_tokens_until(&type, token, try_func_comma, 
                                            try_func_array_dcl,
                                            "Missing ')' to close a function");
                    if (type == ',') {
                        strcat(result, ", ");
                        continue;
                    } else if (try_declaration(type)) {
                        continue;
                    } else {
                        // Fall through to break
                    }
                } 
                break;
            }
            if (ret == 0) {
                if (has_param) {
                    strcat(result, "]");
                }
                strcat(result, " returning");
            }

        } else {
            // Don't try to do error recovery here. Simply ends a
            // direct declarator and leaves the remaining tokens
            // to the outside.
            unget_token();
            break;
        }
    }

    return ret;
}
예제 #30
0
파일: parser.c 프로젝트: palmerc/lab
int parameter_declaration(void) {
	declaration_specifiers();
	if( declarator() ) {
	} else if( abstract_declarator() ) {
	}
}