⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gbc_trans_tree.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
字号:
/***************************************************************************  trans_tree.c  Convert expression to a tree  (c) 2000-2004 Beno� Minisini <gambas@users.sourceforge.net>  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; either version 1, or (at your option)  any later version.  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.***************************************************************************/#define __GBC_TRANS_TREE_C#include "gb_common.h"#include "gb_error.h"#include "gbc_compile.h"#include "gbc_trans.h"#include "gb_code.h"#include "gbc_read.h"/*#define DEBUG*/PRIVATE short level;PRIVATE PATTERN *current;PRIVATE TRANS_TREE *tree = NULL;/*PRIVATE PATTERN last_pattern;*/PRIVATE void analyze_expr(short priority, short op_main);PRIVATE void inc_level(){  level++;  if (level > MAX_EXPR_LEVEL)   THROW("Expression too complex");}PRIVATE void dec_level(){  level--;}PRIVATE void add_pattern(PATTERN pattern){  TRANS_TREE *node;  short index;  index = (short)ARRAY_count(tree);  if (index >= MAX_EXPR_PATTERN)    THROW("Expression too complex");  node = ARRAY_add(&tree);  *node = pattern;  /*last_pattern = pattern;*/  /*#ifdef DEBUG  READ_dump_pattern(&pattern);  #endif*/}PRIVATE void remove_last_pattern(){  if (!ARRAY_count(tree))    return;  ARRAY_remove_last(&tree);}PRIVATE PATTERN get_last_pattern(int dep){  short index;  index = (short)ARRAY_count(tree);  if (index < dep)    return NULL_PATTERN;  return tree[index - dep];}PRIVATE void change_last_pattern(int dep, PATTERN pattern){  short index;  index = (short)ARRAY_count(tree);  if (index < dep)    return;  tree[index - dep] = pattern;}PRIVATE void check_last_first(int dep){  if (PATTERN_is_identifier(get_last_pattern(dep)))    change_last_pattern(dep, PATTERN_set_flag(get_last_pattern(dep), RT_FIRST));}PRIVATE void add_reserved_pattern(int reserved){  add_pattern(PATTERN_make(RT_RESERVED, reserved));}PRIVATE void add_operator_output(short op, short nparam, boolean has_output){  PATTERN pattern;  long index;  SYMBOL *sym;  /*     A QUOI SERT CE TEST ?     add_operator() peut �re appel�sans op�ateur. Cf.     if (RES_priority(op) < prio) ...  */  if (op == RS_NONE || op == RS_UNARY)    return;  if (op == RS_EXCL)  {    /*if (!PATTERN_is_identifier(get_last_pattern(1)))      THROW("The operator '!' must be followed by an identifier.");*/    sym = TABLE_get_symbol(JOB->class->table, PATTERN_index(get_last_pattern(1)));    TABLE_add_symbol(JOB->class->string, sym->name, sym->len, NULL, &index);    change_last_pattern(1, PATTERN_make(RT_STRING, index));    op = RS_LSQR;    nparam = 2;    check_last_first(2);  }  pattern = PATTERN_make(RT_RESERVED, op);  if (op == RS_LBRA && has_output)    pattern = PATTERN_set_flag(pattern, RT_OUTPUT);  add_pattern(pattern);  pattern = PATTERN_make(RT_PARAM, nparam);  add_pattern(pattern);}PRIVATE void add_operator(short op, short nparam){  add_operator_output(op, nparam, FALSE);}PRIVATE void add_subr(PATTERN subr_pattern, short nparam, boolean has_output){  PATTERN pattern;  if (has_output)    subr_pattern = PATTERN_set_flag(subr_pattern, RT_OUTPUT);  add_pattern(subr_pattern);  pattern = PATTERN_make(RT_PARAM, nparam);  add_pattern(pattern);}PRIVATE void analyze_make_array(){  int n = 0;  for(;;)  {    n++;    analyze_expr(0, RS_NONE);    if (!PATTERN_is(*current, RS_COMMA))      break;    current++;  }  if (!PATTERN_is(*current, RS_RSQR))    THROW("Missing right square");  current++;  add_operator(RS_RSQR, n);}PRIVATE void analyze_single(int op){  PATTERN *pattern;  bool jump_newline;  jump_newline = PATTERN_is_newline(*current);  if (jump_newline)  {  	add_pattern(PATTERN_make(RT_NEWLINE, 0));  	JOB->line++;    current++;	}  if (op == RS_PT || op == RS_EXCL)    if (!PATTERN_is_identifier(*current))    {      if (op == RS_PT)        THROW("The '.' operator must be followed by an identifier");      else        THROW("The '!' operator must be followed by an identifier");    }  /* ( expr ) */  if (PATTERN_is(*current, RS_LBRA))  {    long index = ARRAY_count(tree);    PATTERN last;    current++;    analyze_expr(0, RS_NONE);    if (!PATTERN_is(*current, RS_RBRA))      THROW("Missing right brace");    current++;    if (ARRAY_count(tree) == (index + 1))    {      last = get_last_pattern(1);      if (PATTERN_is_string(last))        change_last_pattern(1, PATTERN_make(RT_TSTRING, PATTERN_index(last)));    }  }  /* [ expr, expr, ... ] */  else if (PATTERN_is(*current, RS_LSQR))  {    current++;    analyze_make_array();  }  /* - expr | NOT expr */  else if (PATTERN_is(*current, RS_MINUS) || PATTERN_is(*current, RS_NOT))  {    pattern = current;    current++;    analyze_expr(RES_priority(RS_NOT), RS_UNARY);    add_operator(PATTERN_index(*pattern), 1);  }  /* . symbol */  else if (PATTERN_is(*current, RS_PT) && PATTERN_is_identifier(current[1]))  {    add_operator(PATTERN_index(current[0]), 0);    add_pattern(PATTERN_set_flag(current[1], RT_POINT));    current += 2;  }  /* NULL, TRUE, FALSE, ME, LAST, ERROR */  /* nombre, chaine ou symbole */  else if (PATTERN_is(*current, RS_NULL)           || PATTERN_is(*current, RS_ME)           || PATTERN_is(*current, RS_LAST)           || PATTERN_is(*current, RS_TRUE)           || PATTERN_is(*current, RS_FALSE)           || PATTERN_is(*current, RS_ERROR)           || (!PATTERN_is_reserved(*current) && !PATTERN_is_newline(*current)))  {    add_pattern(*current);    if (PATTERN_is_identifier(*current))    {      /*if ((op == RS_NONE || op == RS_UNARY) && (PATTERN_is_identifier(*current)))        change_last_pattern(1, PATTERN_set_flag(get_last_pattern(1), RT_FIRST));*/      if (op == RS_PT)      {        change_last_pattern(1, PATTERN_set_flag(get_last_pattern(1), RT_POINT));        check_last_first(2);      }    }    current++;  }  else  {    if (jump_newline)    {      current--;      JOB->line--;		}    THROW(E_SYNTAX);	}}PRIVATE void analyze_call(){  /*static PATTERN *output[MAX_PARAM_OP];*/  int nparam_post = 0;  PATTERN subr_pattern = NULL_PATTERN;  PATTERN last_pattern = get_last_pattern(1);  boolean has_output = FALSE;  /*int i;  PATTERN *save_current;*/  SUBR_INFO *info;  boolean optional = TRUE;  /*  get_pattern_subr(last_pattern, &subr);  */  if (PATTERN_is_subr(last_pattern))  {    subr_pattern = last_pattern;    remove_last_pattern();    optional = FALSE;  }  else if (PATTERN_is_identifier(last_pattern))  {    check_last_first(1);  }  else if (PATTERN_is_string(last_pattern) || PATTERN_is_number(last_pattern))    THROW(E_SYNTAX);  /* N.B. Le cas o last_pattern = "." n'a pas de test sp�ifique */  for (;;)  {    if (PATTERN_is(*current, RS_RBRA))    {      current++;      break;    }    if (nparam_post > 0)    {      if (!PATTERN_is(*current, RS_COMMA))        THROW("Comma missing");      current++;    }    #if 0    if (FALSE) /*(PATTERN_is(*current, RS_AMP))*/    {      current++;      output[nparam_post] = current;      has_output = TRUE;    }    else    {      output[nparam_post] = NULL;    }    #endif    if (optional && (PATTERN_is(*current, RS_COMMA) || PATTERN_is(*current, RS_RBRA)))    {      add_reserved_pattern(RS_OPTIONAL);    }    else    {      analyze_expr(0, RS_NONE);    }    nparam_post++;    if (nparam_post > MAX_PARAM_FUNC)      THROW("Too many arguments");  }  if (get_last_pattern(1) == PATTERN_make(RT_RESERVED, RS_OPTIONAL))    THROW("Syntax error. Needless arguments");  /*  while (nparam_post > 0)  {    if (get_last_pattern(1) != PATTERN_make(RT_RESERVED, RS_OPTIONAL))      break;    remove_last_pattern();    nparam_post--;  }  */  if (subr_pattern == NULL_PATTERN)    add_operator_output(RS_LBRA, nparam_post, has_output);  else  {    info = &COMP_subr_info[PATTERN_index(subr_pattern)];    if (nparam_post < info->min_param)      THROW("Not enough arguments to &1()", info->name);    else if (nparam_post > info->max_param)      THROW("Too many arguments to &1()", info->name);    add_subr(subr_pattern, nparam_post, has_output);  }  #if 0  if (has_output)  {    save_current = current;    for (i = nparam_post - 1; i >= 0; i--)    {      if (output[i] != NULL)      {        current = output[i];        analyze_expr(0, RS_NONE);        add_reserved_pattern(RS_AT);      }      else        add_reserved_pattern(RS_COMMA); /* Provoque un drop */    }    if (subr_pattern != NULL_PATTERN)      add_reserved_pattern(RS_RBRA); /* Provoque le PUSH RETURN dans le cas d'un call*/    current = save_current;  }  #endif}PRIVATE void analyze_array(){  int i;  check_last_first(1);  for(i = 0; i < MAX_ARRAY_DIM; i++)  {    analyze_expr(0, RS_NONE);    if (!PATTERN_is(*current, RS_COMMA))      break;    current++;  }  if (!PATTERN_is(*current, RS_RSQR))    THROW("Missing right square");  current++;  add_operator(RS_LSQR, i + 2);}PRIVATE void analyze_expr_check_first(int op_curr){  /* On laisse le marqueur RT_FIRST que si on a affaire �l'op�ateur '.' */  /*  last = get_last_pattern();  if (PATTERN_is_first(last))  {    if (op_curr != RS_PT)      change_last_pattern(PATTERN_unset_flag(last, RT_FIRST));  }  */}PRIVATE void analyze_expr(short priority, short op_main){  int op_curr;  int op;  int prio;  int nparam;  inc_level();  op_curr = op_main;  nparam = (op_main == RS_NONE || op_main == RS_UNARY) ? 0 : 1;  /* cas particulier de NEW */  /* obsol�e : ne doit jamais servir, l'analyse est faite ailleurs */  if (PATTERN_is(*current, RS_NEW))    THROW("Cannot use NEW operator there");  /* analyse des op�andes */READ_OPERAND:  analyze_expr_check_first(op_curr);  analyze_single(op_curr);  nparam++;  if (nparam > MAX_PARAM_OP)    THROW("Expression too complex. Too many operands");  /* Lecture de l'op�ateur */READ_OPERATOR:  if (!PATTERN_is_reserved(*current))    goto OPERATOR_END;  op = PATTERN_index(*current);  if (!RES_is_operator(op))    goto OPERATOR_END;  current++;  if (priority)    prio = priority;  else if (op_curr == RS_NONE)    prio = 0;  else    prio = RES_priority(op_curr);  if (op_curr == RS_NONE)  {    if (RES_is_binary(op) || RES_is_n_ary(op))    {      op_curr = op;      goto READ_OPERAND;    }  }  if (op_curr == op)  {    if (!(RES_is_binary(op) && nparam == 2))      goto READ_OPERAND;  }  if (RES_priority(op) > prio)  {    if (op == RS_LSQR)      analyze_array();    else if (op == RS_LBRA)      analyze_call();    else      analyze_expr(RES_priority(op), op);    goto READ_OPERATOR;  }  if (RES_priority(op) == prio)  {    add_operator(op_curr, nparam);    if (op == RS_LSQR)    {      analyze_array();      goto READ_OPERATOR;    }    else if (op == RS_LBRA)    {      analyze_call();      goto READ_OPERATOR;    }    else    {      nparam = 1;      op_curr = op;      goto READ_OPERAND;    }  }  if (RES_priority(op) < prio)  {    if ((op_main != RS_NONE) || (priority > 0))    {      add_operator(op_curr, nparam);      current--;      goto END;    }    add_operator(op_curr, nparam);    if (op == RS_LSQR)    {      analyze_array();      nparam = 1;      op_curr = op_main;      goto READ_OPERATOR;    }    else if (op == RS_LBRA)    {      analyze_call();      nparam = 1;      op_curr = op_main;      goto READ_OPERATOR;    }    else    {      nparam = 1;      op_curr = op;      goto READ_OPERAND;    }  }  dec_level();  return;OPERATOR_END:  analyze_expr_check_first(op_curr);  add_operator(op_curr, nparam);END:  dec_level();  return;}PUBLIC TRANS_TREE *TRANS_tree(){  #ifdef DEBUG  int i;  #endif  /*last_pattern = NULL_PATTERN;*/  ARRAY_create(&tree);  /*ARRAY_add(&tree);*/  current = JOB->current;  TRY  {    analyze_expr(0, RS_NONE);    JOB->current = current;  }  CATCH  {    JOB->current = current;    PROPAGATE();  }  END_TRY  #ifdef DEBUG    printf("\n");    for (i = 0; i < ARRAY_count(tree); i++)    {      printf("[%d] ", i);      READ_dump_pattern(&tree[i]);    }  #endif  return tree;}PUBLIC boolean TRANS_is_statement(TRANS_TREE *_tree){  PATTERN last;  long count;  tree = _tree;  count = ARRAY_count(tree);  if (count == 0)    return FALSE;  count--;  last = tree[count];  if (PATTERN_is_param(last) && (count > 0))  {    count--;    last = tree[count];  }  if (PATTERN_is(last, RS_PT))    goto _ADD_BRACE;  if (PATTERN_is_identifier(last))  {    if (count == 0)      goto _ADD_BRACE;    if (count >= 2)    {      last = tree[count - 1];      if (PATTERN_is_param(last) && (PATTERN_index(last) == 0)          && PATTERN_is(tree[count - 2], RS_PT))        goto _ADD_BRACE;    }  }  else if (PATTERN_is_subr(last)           || PATTERN_is(last, RS_LBRA)           || PATTERN_is(last, RS_RBRA)           || PATTERN_is(last, RS_AT)           || PATTERN_is(last, RS_COMMA))    return TRUE;  #ifdef DEBUG    printf("Last = ");    READ_dump_pattern(&last);  #endif  return FALSE;_ADD_BRACE:  add_operator(RS_LBRA, 0);  #ifdef DEBUG  printf("Add ()\n");  #endif  return TRUE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -