/* $Id: $ */

/* Copyright (C) 1998 Sverre Hvammen Johansen,
 * Department of Informatics, University of Oslo.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.
 *
 * This program 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, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

#include <stdio.h>
#include <obstack.h>

#include "const.h"
#include "mellbuilder.h"
#include "builder.h"

char *xmalloc();
void free();

#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free

int token;

static struct obstack osStack;
static struct obstack osExpr;

/******************************************************************************
								EBUILDERINIT */

ebuilderInit()
{
  obstack_init(&osStack);
  obstack_init(&osExpr);
  lineno= 1;
}

/******************************************************************************
 								      NEWEXP */

struct EXP *newexp()
{
  struct EXP *re;
  re= (struct EXP *)obstack_alloc (&osExpr, sizeof (struct EXP));
  memset (re, 0, sizeof (struct EXP));
  re->line= lineno;
  return re;
}

/******************************************************************************
								     MAKEEXP */

struct EXP *makeexp (token, left, right) int token; struct EXP *left, *right;
{
  struct EXP *re;
  re= newexp();

  re->token= token;

  re->left= left;
  if (left) left->up= re;
  re->right= right;
  if (right) right->up= re;

  return (re);
}

/******************************************************************************
								     CONCEXP */

struct EXP * concexp (left, right) struct EXP *left, *right;
{
  if (left==NULL) return right;
  if (right==NULL) return left;
  return makeexp (MSENTCONC, left, right);
}

/******************************************************************************
								 REPLACENODE */

struct EXP *replacenode (rep, token) struct EXP **rep; int token;
{
  struct EXP *rex;
  rex= newexp ();
  if (is_after_dot ((*rep))) *rex= *(*rep)->up;
  else
    *rex= **rep;
  remove_dot (rep);
  if (rex->right) rex->right->up=rex;
  if (rex->left) rex->left->up=rex;
  (*rep)->token= token;
  return (rex);
}

/******************************************************************************
                                                                COPYTREE     */

struct EXP *
copytree (re)
     struct EXP *re;
{
  struct EXP *rex;
  if (re == NULL) return NULL;
  rex = newexp();
  if (re->left != NULL)
    {
      rex->left = copytree (re->left);
      rex->left->up = rex;
    }
  else
    rex->left = NULL;
  if (re->right != NULL)
    {
      rex->right = copytree (re->right);
      rex->right->up = rex;
    }
  else
    rex->right = NULL;
  rex->token = re->token;
  rex->line = re->line;
  rex->value = re->value;
  rex->type = re->type;
  rex->danger = re->danger;
  rex->up = re->up;
  rex->rd = re->rd;
  rex->qual = re->qual;
  rex->seenthrough = re->seenthrough;
  return (rex);
}

/******************************************************************************
								  REMOVE_DOT */

remove_dot (rep)
     struct EXP **rep;
{
  if (is_after_dot ((*rep)))
    {
      *rep = (*rep)->up;
      (*rep)->value = (*rep)->right->value;
      (*rep)->token = (*rep)->right->token;
      (*rep)->left = (*rep)->right = NULL;
    }
}

/******************************************************************************
								      ECLEAN */

static eclean()
{
  void *p;
  p= obstack_finish (&osStack);
  obstack_free (&osStack, p);
}

/******************************************************************************
								       EPUSH */

static epush(re)struct EXP *re;
{
#if 0
  obstack_ptr_grow (&osStack, re);
#else
  obstack_grow(&osStack, &re, sizeof (void *));
#endif
}

/******************************************************************************
								        EPOP */

static struct EXP *epop()
{
  struct EXP *re;
  re= * ((struct EXP * *)obstack_next_free (&osStack) - 1);
  obstack_blank (&osStack, - sizeof (void *));
  return (re);
}

/******************************************************************************
								       ELOOK */

struct EXP *elook()
{
  return *((struct EXP * *)obstack_next_free (&osStack) - 1);
}


/******************************************************************************
                                                                   EBUILD    */

/* Bygger opp et uttrykstree, Alle operatorene leses postfix */

ebuild ()
{
  struct EXP *re;

  eclean();
  while (TRUE)
    {
      switch (token)
	{
	case MNOT:
	case MUADD:
	case MUSUB:
	case MNOOP:
	case MQUA:
	  epush(re= makeexp(token, epop(), NULL));
	  /* Sjekke dobbel unær
	   * Eventuelt optimalisere bort noen noop */
	  break;
	case MTEXTKONST:
	case MCHARACTERKONST:
	case MREALKONST:
	case MINTEGERKONST:
	case MBOOLEANKONST:
	case MENDSEP:
	case MNONE:
	case MIDENTIFIER:
	case MTHIS:
	case MLABEL:
	  epush(re= makeexp(token, NULL, NULL));
	  break;
	case MNEWARG:
	case MARGUMENT:
	  epush(re= makeexp(token, NULL, epop()));
	  break;
	case MNEWLINE:
	  lineno++;
	  goto newtoken;
	  break;
	case MFLAG:
	  setFlag ();
	  break;
	default:
	  if (setntokens (token) || token == MERROR || token == MSTOP)
	    {
#ifdef DEBUG
	      if (token == MERROR)
		dumpexp ();
#endif
	      re= elook()->up= makeexp(token, NULL, NULL);
	      re->up= re;
	      return;
	    }
	  /* VANELIG BEHANDLING */
	  {
	    struct EXP *right= epop();
	    epush (re= makeexp (token, epop(), right));
	  }
	}
      if (expridtokens (token))
	re->value.ival= (long) minId();
	  else
	if (token == MTEXTKONST)
	  {
	    re->value.tval.txt= minTval();
	    re->value.tval.id= NOTEXT;
	  }
	    else
	  if (token == MREALKONST)
	    re->value.rval= minRval();
	      else
	    if (exprvaltokens (token))
	      re->value.ival= minIval();
    newtoken:
      token= min();
    }
}




syntax highlighted by Code2HTML, v. 0.9.1