OpenCores
URL https://opencores.org/ocsvn/raptor64/raptor64/trunk

Subversion Repositories raptor64

[/] [raptor64/] [trunk/] [software/] [c64/] [source/] [ParseStatements.c] - Rev 51

Compare with Previous | Blame | View Log

// ============================================================================
// (C) 2012 Robert Finch
// All Rights Reserved.
// robfinch<remove>@opencores.org
//
// C64 - Raptor64 'C' derived language compiler
//  - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify 
// it under the terms of the GNU Lesser General Public License as published 
// by the Free Software Foundation, either version 3 of the License, or     
// (at your option) any later version.                                      
//                                                                          
// This source file is distributed in the hope that it will be useful,      
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// GNU General Public License for more details.                             
//                                                                          
// You should have received a copy of the GNU General Public License        
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
//                                                                          
// ============================================================================
//
#include <stdio.h> 
#include "c.h" 
#include "expr.h" 
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h" 
 
extern TYP *head, *tail;
extern char *declid;
extern int catchdecl;
Statement *ParseStatement();   /* forward declararation */ 
Statement *ParseCatchStatement();
 
Statement *NewStatement(int typ, int gt) {
	Statement *s = (Statement *)xalloc(sizeof(Statement));
	s->stype = typ;
	if (gt) NextToken();
	return s;
};
 
 
int GetTypeHash(TYP *p)
{
	int n;
	TYP *p1;
 
	n = 0;
	do {
		if (p->type==bt_pointer)
			n+=20000;
		p1 = p;
		p = p->btp;
	} while (p);
	n += p1->typeno;
	return n;
}
 
 
//struct snode    *interrupt_stmt()
//{       struct snode    *snp; 
//        SYM             *sp; 
//	       TYP     *temp1;
//
//	   NextToken(); 
//		if( lastst != id ) { 
//			error(ERR_IDEXPECT); 
//			return 0; 
//        } 
//        sp = allocSYM(); 
//        sp->name = litlate(lastid); 
//        sp->value.i = nextlabel++; 
//        sp->storage_class = sc_global;
//        sp->tp = temp1; 
//        temp1 = maketype(bt_long,0);
//        temp1->val_flag = 1;
//        insert(sp,&lsyms); 
//        NextToken();       /* get past label name */ 
//        needpunc( colon );
//		snp = (struct snode *)xalloc(sizeof(struct snode)); 
//        snp->stype = st_interrupt; 
//        snp->label = sp->name;
//        snp->next = 0; 
//		snp->s1 = statement(); 
//        return snp; 
//} 
//  
struct snode    *vortex_stmt()
{       struct snode    *snp; 
        SYM             *sp; 
	       TYP     *temp1;
 
	   NextToken(); 
		if( lastst != id ) { 
			error(ERR_IDEXPECT); 
			return 0; 
        } 
        temp1 = maketype(bt_long,0);
        temp1->val_flag = 1;
        sp = allocSYM(); 
        sp->name = litlate(lastid); 
        sp->value.i = nextlabel++; 
        sp->storage_class = sc_global;
        sp->tp = temp1; 
        insert(sp,&lsyms); 
        NextToken();       /* get past label name */ 
        needpunc( colon );
		snp = (struct snode *)xalloc(sizeof(struct snode)); 
        snp->stype = st_vortex; 
        snp->label = sp->name;
        snp->next = 0; 
		snp->s1 = ParseStatement(); 
        return snp; 
} 
 
Statement *ParseWhileStatement() 
{       
	Statement *snp;
 
    snp = NewStatement(st_while, TRUE);
    if( lastst != openpa ) 
        error(ERR_EXPREXPECT); 
    else { 
        NextToken(); 
        if( expression(&(snp->exp)) == 0 ) 
            error(ERR_EXPREXPECT); 
        needpunc( closepa ); 
		if (lastst==kw_do)
			NextToken();
        snp->s1 = ParseStatement(); 
    } 
    return snp; 
} 
 
Statement *ParseUntilStatement()
{
	Statement *snp; 
    snp = NewStatement(st_until, TRUE);
    if( lastst != openpa ) 
        error(ERR_EXPREXPECT); 
    else { 
        NextToken(); 
        if( expression(&(snp->exp)) == 0 ) 
            error(ERR_EXPREXPECT); 
        needpunc( closepa ); 
        snp->s1 = ParseStatement(); 
    } 
    return snp; 
} 
 
Statement *ParseDoStatement() 
{       
	Statement *snp; 
    snp = NewStatement(st_do, TRUE); 
    snp->s1 = ParseStatement(); 
	if (lastst == kw_until)
		snp->stype = st_dountil;
	else if (lastst== kw_loop)
		snp->stype = st_doloop;
    if( lastst != kw_while && lastst != kw_until && lastst != kw_loop ) 
        error(ERR_WHILEXPECT); 
    else { 
        NextToken(); 
		if (snp->stype!=st_doloop) {
        if( expression(&(snp->exp)) == 0 ) 
            error(ERR_EXPREXPECT); 
		}
        if( lastst != end )
            needpunc( semicolon );
    } 
    return snp; 
} 
 
Statement *ParseForStatement() 
{
	Statement *snp; 
    snp = NewStatement(st_for, TRUE);
    needpunc(openpa); 
    if( expression(&(snp->initExpr)) == NULL ) 
        snp->initExpr = NULL; 
    needpunc(semicolon); 
    if( expression(&(snp->exp)) == NULL ) 
        snp->exp = NULL; 
    needpunc(semicolon); 
    if( expression(&(snp->incrExpr)) == NULL ) 
        snp->incrExpr = NULL; 
    needpunc(closepa); 
    snp->s1 = ParseStatement(); 
    return snp; 
} 
 
Statement *ParseForeverStatement() 
{
	Statement *snp; 
    snp = NewStatement(st_forever, TRUE);
    snp->stype = st_forever; 
    snp->s1 = ParseStatement(); 
    return snp; 
} 
 
struct snode *ParseCriticalStatement()
{
	struct snode    *snp; 
	SYM *sp;
    snp = (struct snode*)xalloc(sizeof(struct snode)); 
    NextToken(); 
	if (lastst==openpa)
		NextToken();
    if( lastst != id ) { 
        error(ERR_IDEXPECT); 
        return 0; 
    }
    if( (sp = search(lastid,&gsyms[0])) == NULL ) { 
            error( ERR_UNDEFINED ); 
			return 0;
            }
	NextToken();
	if (lastst==closepa)
		NextToken();
    snp->stype = st_critical; 
    snp->label = sp->name; 
    snp->next = 0; 
	snp->s1 = ParseStatement();
	return snp;
}
 
Statement *ParseSpinlockStatement()
{
	Statement *snp; 
	SYM *sp;
 
	snp = NewStatement(st_spinlock, TRUE); 
	if (lastst==openpa)
		NextToken();
    if( NonCommaExpression(&(snp->exp)) == 0 ) 
        error(ERR_EXPREXPECT); 
	snp->incrExpr = 1;
	snp->initExpr = 0;
	//if( lastst != id ) { 
 //       error(ERR_IDEXPECT); 
 //       return 0; 
 //   }
 //   if( (sp = search(lastid,&gsyms[0])) == NULL ) { 
 //           error( ERR_UNDEFINED ); 
	//		return 0;
 //           }
//	NextToken();
	if (lastst==comma) {
		NextToken();
		snp->incrExpr = GetIntegerExpression();
		if (snp->incrExpr < 1 || snp->incrExpr > 15)
			error(ERR_SEMA_INCR);
		snp->incrExpr = (int)snp->incrExpr & 15;
	}
	if (lastst==comma) {
		NextToken();
		snp->initExpr = GetIntegerExpression();
	}
	if (lastst==closepa)
		NextToken();
//    snp->label = sp->name; 
    snp->next = 0; 
	snp->s1 = ParseStatement();
	if (lastst==kw_lockfail) {
		NextToken();
		snp->s2 = ParseStatement();
	}
	return snp;
}
 
Statement *ParseSpinunlockStatement()
{
	Statement *snp; 
	SYM *sp;
 
    snp = NewStatement(st_spinunlock, TRUE); 
	snp->incrExpr = 1;
	if (lastst==openpa)
		NextToken();
    if( expression(&(snp->exp)) == 0 ) 
        error(ERR_EXPREXPECT); 
	if (lastst==comma) {
		NextToken();
		snp->incrExpr = GetIntegerExpression();
		if (snp->incrExpr < 1 || snp->incrExpr > 15)
			error(ERR_SEMA_INCR);
		snp->incrExpr = (int)snp->incrExpr & 15;
	}
    //if( lastst != id ) { 
    //    error(ERR_IDEXPECT); 
    //    return 0; 
    //}
  //  if( (sp = search(lastid,&gsyms[0])) == NULL ) { 
  //      error( ERR_UNDEFINED ); 
		//return 0;
  //  }
	NextToken();
	if (lastst==closepa)
		NextToken();
    //snp->label = sp->name; 
    snp->next = 0; 
	return snp;
}
 
Statement *ParseFirstcallStatement() 
{
	Statement *snp; 
    snp = NewStatement(st_firstcall, TRUE); 
    snp->s1 = ParseStatement(); 
    return snp; 
} 
 
Statement *ParseIfStatement() 
{
	Statement *snp; 
 
    snp = NewStatement(st_if, TRUE); 
    if( lastst != openpa ) 
        error(ERR_EXPREXPECT); 
    else {
        NextToken(); 
        if( expression(&(snp->exp)) == 0 ) 
            error(ERR_EXPREXPECT); 
        needpunc( closepa ); 
		if (lastst==kw_then)
			NextToken();
        snp->s1 = ParseStatement(); 
        if( lastst == kw_else ) { 
            NextToken(); 
            snp->s2 = ParseStatement(); 
        } 
		else if (lastst == kw_elsif) {
            snp->s2 = ParseIfStatement(); 
		}
        else 
            snp->s2 = 0; 
    } 
    return snp; 
} 
 
Statement *ParseCatchStatement()
{
	Statement *snp;
	SYM *sp;
	TYP *tp,*tp1,*tp2;
 
	snp = NewStatement(st_catch, TRUE);
	if (lastst != openpa) {
		snp->label = NULL;
		snp->s2 = 99999;
		snp->s1 = ParseStatement();
		return snp;
	}
    needpunc(openpa);
	tp = head;
	tp1 = tail;
	catchdecl = TRUE;
	ParseAutoDeclarations();
	catchdecl = FALSE;
	tp2 = head;
	head = tp;
	tail = tp1;
    needpunc(closepa);
 
	if( (sp = search(declid,&lsyms)) == NULL)
        sp = makeint(declid);
	snp->s1 = ParseStatement();
	snp->label = (char *)sp;	// save off symbol pointer
	if (sp->tp->typeno >= bt_last)
		error(ERR_CATCHSTRUCT);
	snp->s2 = GetTypeHash(sp->tp);
	return snp;
}
 
Statement *ParseCaseStatement()
{
	Statement *snp; 
    Statement *head, *tail;
	int buf[256];
	int nn;
	int *bf;
 
    snp = NewStatement(st_case, FALSE); 
	if (lastst == kw_fallthru)	// ignore "fallthru"
		NextToken();
    if( lastst == kw_case ) { 
        NextToken(); 
        snp->s2 = 0;
		nn = 0;
		do {
			buf[nn] = GetIntegerExpression();
			nn++;
			if (lastst != comma)
				break;
			NextToken();
		} while (nn < 256);
		if (nn==256)
			error(ERR_TOOMANYCASECONSTANTS);
		bf = (int *)xalloc(sizeof(int)*(nn+1));
		bf[0] = nn;
		for (; nn > 0; nn--)
			bf[nn]=buf[nn-1];
		snp->label = bf;
    }
    else if( lastst == kw_default) { 
        NextToken(); 
        snp->s2 = 1; 
		snp->stype = st_default;
    } 
    else { 
        error(ERR_NOCASE); 
        return NULL;
    } 
    needpunc(colon); 
    head = NULL; 
    while( lastst != end && lastst != kw_case && lastst != kw_default ) { 
		if( head == NULL )
			head = tail = ParseStatement(); 
		else { 
			tail->next = ParseStatement(); 
			if( tail->next != NULL ) 
				tail = tail->next;
		}
        tail->next = 0; 
    } 
    snp->s1 = head; 
    return snp; 
} 
 
int CheckForDuplicateCases(Statement *head) 
{     
	Statement *top, *cur;
 
	cur = top = head;
	while( top != NULL )
	{
		cur = top->next;
		while( cur != NULL )
		{
			if( (!(cur->s1 || cur->s2) && cur->label == top->label)
				|| (cur->s2 && top->s2) )
			{
				printf(" duplicate case value %d\n",cur->label);
				return TRUE;
			}
			cur = cur->next;
		}
		top = top->next;
	}
	return FALSE;
} 
 
Statement *ParseSwitchStatement() 
{       
	Statement *snp; 
    Statement *head, *tail; 
 
    snp = NewStatement(st_switch, TRUE); 
    if( expression(&(snp->exp)) == NULL ) 
        error(ERR_EXPREXPECT); 
    needpunc(begin); 
    head = 0; 
    while( lastst != end ) { 
		if( head == NULL )
			head = tail = ParseCaseStatement(); 
		else { 
			tail->next = ParseCaseStatement(); 
			if( tail->next != NULL ) 
				tail = tail->next;
		}
		if (tail==NULL) break;	// end of file in switch
        tail->next = NULL; 
    } 
    snp->s1 = head; 
    NextToken(); 
    if( CheckForDuplicateCases(head) ) 
        error(ERR_DUPCASE); 
    return snp; 
} 
 
Statement *ParseReturnStatement() 
{       
	Statement *snp;
 
	snp = NewStatement(st_return, TRUE);
    expression(&(snp->exp));
    if( lastst != end )
        needpunc( semicolon );
    return snp; 
} 
 
Statement *ParseThrowStatement() 
{  
	Statement *snp;
	TYP *tp;
 
	currentFn->DoesThrow = TRUE;
	snp = NewStatement(st_throw, TRUE);
    tp = expression(&(snp->exp));
	snp->label = GetTypeHash(tp);
    if( lastst != end )
        needpunc( semicolon );
    return snp;
} 
 
Statement *ParseBreakStatement() 
{     
	Statement *snp; 
 
	snp = NewStatement(st_break, TRUE);
    if( lastst != end )
        needpunc( semicolon );
    return snp; 
} 
 
Statement *ParseContinueStatement() 
{
	Statement *snp; 
 
    snp = NewStatement(st_continue, TRUE);
    if( lastst != end )
        needpunc( semicolon );
    return snp;
} 
 
Statement *ParseIntoffStatement() 
{       
	Statement *snp; 
    snp = NewStatement(st_intoff, TRUE); 
    if( lastst != end )
        needpunc( semicolon );
    return snp;
} 
 
Statement *ParseIntonStatement() 
{       
	Statement *snp; 
 
    snp = NewStatement(st_inton, TRUE); 
    if( lastst != end )
        needpunc( semicolon );
    return snp;
} 
 
Statement *ParseStopStatement() 
{
	Statement *snp; 
 
	snp = NewStatement(st_stop, TRUE); 
	if( lastst != end )
		needpunc( semicolon );
	return snp;
} 
 
Statement *ParseAsmStatement() 
{
	static char buf[2001];
	int nn;
 
	Statement *snp; 
    snp = NewStatement(st_asm, FALSE); 
    while( isspace(lastch) )
		getch(); 
    NextToken();
	if (lastst != begin)
		error(ERR_PUNCT);
	nn = 0;
	do {
		getch();
		if (lastch=='}')
			break;
		buf[nn++] = lastch;
	}
	while(lastch!=-1 && nn < 2000);
	if (nn >= 2000)
		error(ERR_ASMTOOLONG);
	buf[nn] = '\0';
	snp->label = litlate(buf);
    return snp;
} 
 
Statement *ParseTryStatement()
{
	Statement *snp;
	TYP *tp,*tp1,*tp2;
	SYM *sp;
	Statement *hd, *tl;
 
	hd = NULL;
	tl = NULL;
	snp = NewStatement(st_try, TRUE);
    snp->s1 = ParseStatement();
	if (lastst != kw_catch)
        error(ERR_CATCHEXPECT);
    while( lastst == kw_catch ) {
		if( hd == NULL )
			hd = tl = ParseCatchStatement(); 
		else { 
			tl->next = ParseCatchStatement(); 
			if( tl->next != NULL ) 
				tl = tl->next;
		}
		if (tl==NULL) break;	// end of file in try
        tl->next = NULL; 
    } 
    snp->s2 = hd;
    return snp;
} 
 
Statement *ParseExpressionStatement() 
{       
	Statement *snp;
    snp = NewStatement(st_expr, FALSE); 
    if( expression(&(snp->exp)) == NULL ) { 
        error(ERR_EXPREXPECT); 
        NextToken(); 
    } 
    if( lastst != end )
        needpunc( semicolon );
    return snp; 
} 
 
Statement *ParseCompoundStatement()
{  
	Statement *head, *tail; 
 
	head = 0; 
	while( lastst != end ) {
		if( head == NULL )
			head = tail = ParseStatement(); 
		else { 
			tail->next = ParseStatement(); 
			if( tail->next != NULL ) 
				tail = tail->next;
		}
	}
    NextToken(); 
    return head; 
} 
 
Statement *ParseLabelStatement()
{      
	Statement *snp;
    SYM *sp;
 
    snp = NewStatement(st_label, FALSE); 
    if( (sp = search(lastid,&lsyms)) == NULL ) { 
        sp = allocSYM(); 
        sp->name = litlate(lastid); 
        sp->storage_class = sc_label; 
        sp->tp = 0; 
        sp->value.i = nextlabel++; 
        insert(sp,&lsyms); 
    } 
    else { 
        if( sp->storage_class != sc_ulabel ) 
            error(ERR_LABEL); 
        else 
            sp->storage_class = sc_label; 
    } 
    NextToken();       /* get past id */ 
    needpunc(colon); 
    if( sp->storage_class == sc_label ) { 
        snp->label = sp->value.i; 
        snp->next = NULL; 
        return snp; 
    } 
    return 0; 
} 
 
Statement *ParseGotoStatement() 
{       
	Statement *snp; 
    SYM *sp;
 
    NextToken(); 
    if( lastst != id ) { 
        error(ERR_IDEXPECT); 
        return NULL;
    } 
    snp = NewStatement(st_goto, FALSE);
    if( (sp = search(lastid,&lsyms)) == NULL ) { 
        sp = allocSYM(); 
        sp->name = litlate(lastid); 
        sp->value.i = nextlabel++; 
        sp->storage_class = sc_ulabel; 
        sp->tp = 0; 
        insert(sp,&lsyms); 
    }
    NextToken();       /* get past label name */
    if( lastst != end )
        needpunc( semicolon );
    if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel)
        error( ERR_LABEL );
    else { 
        snp->stype = st_goto;
        snp->label = sp->value.i;
        snp->next = NULL;
        return snp; 
    } 
    return NULL;
} 
 
Statement *ParseStatement() 
{
	Statement *snp; 
    switch( lastst ) { 
    case semicolon: 
        NextToken(); 
        snp = NULL; 
        break; 
    case begin: 
		NextToken(); 
        snp = ParseCompoundStatement();
        return snp; 
    case kw_if: snp = ParseIfStatement(); break; 
    case kw_while: snp = ParseWhileStatement(); break; 
    case kw_until: snp = ParseUntilStatement(); break; 
    case kw_for:   snp = ParseForStatement();   break; 
    case kw_forever: snp = ParseForeverStatement(); break; 
    case kw_firstcall: snp = ParseFirstcallStatement(); break; 
    case kw_return: snp = ParseReturnStatement(); break; 
    case kw_break: snp = ParseBreakStatement(); break; 
    case kw_goto: snp = ParseGotoStatement(); break; 
    case kw_continue: snp = ParseContinueStatement(); break; 
    case kw_do:
	case kw_loop: snp = ParseDoStatement(); break; 
    case kw_switch: snp = ParseSwitchStatement(); break;
	case kw_try: snp = ParseTryStatement(); break;
	case kw_throw: snp = ParseThrowStatement(); break;
	case kw_vortex:
			snp = vortex_stmt();
			break;
	case kw_intoff: snp = ParseIntoffStatement(); break;
	case kw_inton: snp = ParseIntonStatement(); break;
	case kw_stop: snp = ParseStopStatement(); break;
	case kw_asm:
		snp = ParseAsmStatement(); break;
	case kw_critical: snp = ParseCriticalStatement(); break;
	case kw_spinlock: snp = ParseSpinlockStatement(); break;
	case kw_spinunlock: snp = ParseSpinunlockStatement(); break;
    case id:
			SkipSpaces();
            if( lastch == ':' ) 
                return ParseLabelStatement(); 
            // else fall through to parse expression
    default: 
            snp = ParseExpressionStatement(); 
            break; 
    } 
    if( snp != NULL ) 
        snp->next = NULL;
    return snp; 
} 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.