Beispiel #1
0
struct high_syntax *load_syntax_subr(unsigned char *name, unsigned char *subr, struct high_param *params)
{
    struct high_syntax *syntax; /* New syntax table */

    /* Find syntax table */

    /* Already loaded? */
    for (syntax = syntax_list; syntax; syntax = syntax->next)
    {
        if (syntax_match(syntax, name, subr, params))
        {
            return syntax;
        }
    }

    /* Create new one */
    syntax = joe_malloc(sizeof(struct high_syntax));
    syntax->name = zdup(name);
    syntax->subr = subr ? zdup(subr) : 0;
    syntax->params = params;
    syntax->next = syntax_list;
    syntax->nstates = 0;
    syntax->color = 0;
    syntax->states = joe_malloc(sizeof(struct high_state *) * (syntax->szstates = 64));
    syntax->ht_states = htmk(syntax->szstates);
    iz_cmd(&syntax->default_cmd);
    syntax->default_cmd.reset = 1;
    syntax->stack_base = 0;
    syntax_list = syntax;

    if (load_dfa(syntax))
    {
        /* dump_syntax(syntax); */
        return syntax;
    }
    else
    {
        if (syntax_list == syntax)
        {
            syntax_list = syntax_list->next;
        }
        else
        {
            struct high_syntax *syn;
            for (syn = syntax_list; syn->next != syntax; syn = syn->next);
            syn->next = syntax->next;
        }
        htrm(syntax->ht_states);
        joe_free(syntax->name);
        joe_free(syntax->states);
        joe_free(syntax);
        return 0;
    }
}
Beispiel #2
0
static void
find_context (struct buffer *buf, Bufpos pt)
{
  /* This function can GC */
#ifndef emacs
#ifdef UTF2000
  Lisp_Char_Table *mirrortab = XCHAR_TABLE (buf->syntax_table);
#else
  Lisp_Char_Table *mirrortab = XCHAR_TABLE (buf->mirror_syntax_table);
#endif
  Lisp_Object syntaxtab = buf->syntax_table;
#endif
  Emchar prev_c, c;
  int prev_syncode, syncode;
  Bufpos target = pt;
  setup_context_cache (buf, pt);
  pt = context_cache.cur_point;

  SCS_STATISTICS_SET_FUNCTION (scs_find_context);
  SETUP_SYNTAX_CACHE (pt - 1, 1);
  if (pt > BUF_BEGV (buf))
    {
      c = BUF_FETCH_CHAR (buf, pt - 1);
      syncode = SYNTAX_CODE_FROM_CACHE (mirrortab, c);
    }
  else
    {
      c = '\n'; /* to get bol_context_cache at point-min */
      syncode = Swhitespace;
    }

  for (; pt < target; pt++, context_cache.cur_point = pt)
    {
      if (context_cache.needs_its_head_reexamined)
	{
	  if (context_cache.depth == 0
	      && context_cache.context == context_none)
	    {
	      /* We've found an anchor spot.
		 Try to put the start of defun within 6000 chars of
		 the target, and the end of defun as close as possible.
		 6000 is also arbitrary but tries to strike a balance
		 between two conflicting pulls when dealing with a
		 file that has lots of stuff sitting outside of a top-
		 level form:

		 a) If you move past the start of defun, you will
		    have to recompute defun, which in this case
		    means that start of defun goes all the way back
		    to the beginning of the file; so you want
		    to set start of defun a ways back from the
		    current point.
		 b) If you move a line backwards but within start of
		    defun, you have to move back to start of defun;
		    so you don't want start of defun too far from
		    the current point.
		 */
	      if (target - context_cache.start_point > 6000)
		context_cache.start_point = pt;
	      context_cache.end_point = pt;
	      bol_context_cache = context_cache;
	    }
	}

      UPDATE_SYNTAX_CACHE_FORWARD (pt);
      prev_c = c;
      prev_syncode = syncode;
      c = BUF_FETCH_CHAR (buf, pt);
      syncode = SYNTAX_CODE_FROM_CACHE (mirrortab, c);

      if (prev_c == '\n')
	bol_context_cache = context_cache;

      if (context_cache.backslash_p)
	{
	  context_cache.backslash_p = 0;
	  continue;
	}

      switch (SYNTAX_FROM_CACHE (mirrortab, c))
	{
	case Sescape:
	  context_cache.backslash_p = 1;
	  break;

	case Sopen:
	  if (context_cache.context == context_none)
	    context_cache.depth++;
	  break;

	case Sclose:
	  if (context_cache.context == context_none)
	    context_cache.depth--;
	  break;

	case Scomment:
	  if (context_cache.context == context_none)
	    {
	      context_cache.context = context_comment;
	      context_cache.ccontext = ccontext_none;
	      context_cache.style = SINGLE_SYNTAX_STYLE (syncode);
	      if (context_cache.style == comment_style_none) ABORT ();
	    }
	  break;

	case Sendcomment:
	  if (context_cache.style != SINGLE_SYNTAX_STYLE (syncode))
	    ;
	  else if (context_cache.context == context_comment)
	    {
	      context_cache.context = context_none;
	      context_cache.style = comment_style_none;
	    }
	  else if (context_cache.context == context_block_comment &&
		   (context_cache.ccontext == ccontext_start2 ||
		    context_cache.ccontext == ccontext_end1))
	    {
	      context_cache.context = context_none;
	      context_cache.ccontext = ccontext_none;
	      context_cache.style = comment_style_none;
	    }
	  break;

	case Sstring:
          {
            if (context_cache.context == context_string &&
                context_cache.scontext == c)
	      {
		context_cache.context = context_none;
		context_cache.scontext = '\000';
	      }
            else if (context_cache.context == context_none)
	      {
		Lisp_Object stringtermobj =
		  syntax_match (syntax_cache.current_syntax_table, c);
		Emchar stringterm;

		if (CHARP (stringtermobj))
		  stringterm = XCHAR (stringtermobj);
		else
		  stringterm = c;
		context_cache.context = context_string;
		context_cache.scontext = stringterm;
		context_cache.ccontext = ccontext_none;
	      }
            break;
          }

	case Scomment_fence:
	  {
	    if (context_cache.context == context_generic_comment)
	      {
		context_cache.context = context_none;
	      }
	    else if (context_cache.context == context_none)
	      {
		context_cache.context = context_generic_comment;
		context_cache.ccontext = ccontext_none;
	      }
	    break;
	  }

	case Sstring_fence:
	  {
	    if (context_cache.context == context_generic_string)
	      {
		context_cache.context = context_none;
	      }
	    else if (context_cache.context == context_none)
	      {
		context_cache.context = context_generic_string;
		context_cache.ccontext = ccontext_none;
	      }
	    break;
	  }

	default:
	  ;
	}

      /* That takes care of the characters with manifest syntax.
	 Now we've got to hack multi-char sequences that start
	 and end block comments.
       */
      if ((SYNTAX_CODE_COMMENT_BITS (syncode) &
	   SYNTAX_SECOND_CHAR_START) &&
	  context_cache.context == context_none &&
	  context_cache.ccontext == ccontext_start1 &&
	  SYNTAX_CODES_START_P (prev_syncode, syncode) /* the two chars match */
	  )
	{
	  context_cache.ccontext = ccontext_start2;
	  context_cache.style = SYNTAX_START_STYLE (prev_syncode, syncode);
	  if (context_cache.style == comment_style_none) ABORT ();
	}
      else if ((SYNTAX_CODE_COMMENT_BITS (syncode) &
		SYNTAX_FIRST_CHAR_START) &&
	       context_cache.context == context_none &&
	       (context_cache.ccontext == ccontext_none ||
		context_cache.ccontext == ccontext_start1))
	{
	  context_cache.ccontext = ccontext_start1;
	  context_cache.style = comment_style_none; /* should be this already*/
	}
      else if ((SYNTAX_CODE_COMMENT_BITS (syncode) &
		SYNTAX_SECOND_CHAR_END) &&
	       context_cache.context == context_block_comment &&
	       context_cache.ccontext == ccontext_end1 &&
	       SYNTAX_CODES_END_P (prev_syncode, syncode) &&
	       /* the two chars match */
	       context_cache.style ==
	       SYNTAX_END_STYLE (prev_syncode, syncode)
	       )
	{
	  context_cache.context = context_none;
	  context_cache.ccontext = ccontext_none;
	  context_cache.style = comment_style_none;
	}
      else if ((SYNTAX_CODE_COMMENT_BITS (syncode) &
		SYNTAX_FIRST_CHAR_END) &&
	       context_cache.context == context_block_comment &&
#if 0
	       /* #### pre-Matt code had: */
	       (context_cache.style ==
		SYNTAX_END_STYLE (c, BUF_FETCH_CHAR (buf, pt+1))) &&
	       /* why do these differ here?! */
#endif
	       context_cache.style == SINGLE_SYNTAX_STYLE (syncode) &&
	       (context_cache.ccontext == ccontext_start2 ||
		context_cache.ccontext == ccontext_end1))
	/* check end1, to detect a repetition of the first char of a
	   comment-end sequence. ie, '/xxx foo xxx/' or '/xxx foo x/',
	   where 'x' = '*' -- mct */
	{
	  if (context_cache.style == comment_style_none) ABORT ();
	  context_cache.ccontext = ccontext_end1;
	}

      else if (context_cache.ccontext == ccontext_start1)
	{
	  if (context_cache.context != context_none) ABORT ();
	  context_cache.ccontext = ccontext_none;
	}
      else if (context_cache.ccontext == ccontext_end1)
	{
	  if (context_cache.context != context_block_comment) ABORT ();
	  context_cache.context = context_none;
	  context_cache.ccontext = ccontext_start2;
	}

      if (context_cache.ccontext == ccontext_start2 &&
	  context_cache.context == context_none)
	{
	  context_cache.context = context_block_comment;
	  if (context_cache.style == comment_style_none) ABORT ();
	}
      else if (context_cache.ccontext == ccontext_none &&
	       context_cache.context == context_block_comment)
	{
	  context_cache.context = context_none;
	}
    }

  context_cache.needs_its_head_reexamined = 0;
}
Beispiel #3
0
int syntax_precedence()
{
	int i=1;

	Stack stack;
	Stack stack_index;

	Stack_Init(&stack_index);
	Stack_Init(&stack);

	stack_push(&stack, symbol_dollar);

	do
	{
		if(current_token.type == LEX_IDENTIFIER && !stable_search_scopes(&symbol_table, current_token.val, &ptr_data))
		{
			syntax_match(LEX_IDENTIFIER);
			if(current_token.type != LEX_LPAREN) {
				syntax_error_ec(IFJ_DEF_ERR, "Undefined variable");
			} else {
				return -1;
			}
		}


		if(stack_top(&stack) == 'E')
			i=2;
		else
			i=1;

		switch(precedence_table[stack_offset(&stack, i)][get_sign(&current_token)])
		{
			case '=':
				if((stack_top(&stack) == sign_lparen) && (get_sign(&current_token) == sign_rparen))
				{
					fprintf(stderr,"%s:() ilegal operation\n", __func__);
					exit(IFJ_SYNTAX_ERR);

				}
				stack_push(&stack, get_sign(&current_token));
				lex_get_token(&lex_data, &current_token);
				break;

			case '<':
				if(stack_top(&stack) == 'E')
				{
					stack_pop(&stack);
					stack_push(&stack, '<');
					stack_push(&stack, 'E');
					stack_push(&stack, get_sign(&current_token));

				}
				else
				{
					stack_push(&stack,'<');
					if((current_token.type == LEX_INTEGER) || (current_token.type == LEX_DOUBLE) || (current_token.type == LEX_STRING) || (current_token.type == LEX_LITERAL))
					{
						constant_check(&current_token, &stack_index);
					}
					else if(current_token.type == LEX_IDENTIFIER)
					{
						stable_search_scopes(&symbol_table, current_token.val, &ptr_data);
						int offset = symbol_table.active->stack_idx++;
						if(ptr_data->var.dtype == 0)
							curr_instr = instr_insert_after_instr(&instr_list, curr_instr, INSTR_MOVI, offset, ptr_data->var.offset, 0);
						else if(ptr_data->var.dtype == 1)
							curr_instr = instr_insert_after_instr(&instr_list, curr_instr, INSTR_MOVD, offset, ptr_data->var.offset, 0);
						else if(ptr_data->var.dtype == 2)
							curr_instr = instr_insert_after_instr(&instr_list, curr_instr, INSTR_MOVS, offset, ptr_data->var.offset, 0);
						stack_push(&stack_index, offset);
						final_index = offset;
					}
					stack_push(&stack, get_sign(&current_token));
				}

				lex_get_token(&lex_data, &current_token);
				break;

			/*
			   -----REDUCTION-----
			   according to rules that are described in expr.h
		   */	   

			case '>':
				//E->i
				if(stack_top(&stack) == symbol_id)
				{
					stack_pop(&stack);
					
					if(stack_top(&stack) == '<')
					{
						stack_pop(&stack);
						stack_push(&stack, 'E');
						//printf("Reduction rule E->i used\n");
					}
					else
					{
						fprintf(stderr,"%s: Precedence error in stack\n", __func__);
						exit(IFJ_SYNTAX_ERR);
					}
				}

				//E->(E)
				else if(stack_top(&stack) == sign_rparen)
				{
					stack_pop(&stack);
					if(stack_top(&stack) == 'E')
					{
						stack_pop(&stack);
						if(stack_top(&stack) == sign_lparen)
						{
							stack_pop(&stack);
							if(stack_top(&stack) == '<')
							{
								stack_pop(&stack);
								stack_push(&stack, 'E');
								//printf("Reduction rule E->(E) used\n");
							}
						}
					}
					else
					{
						fprintf(stderr,"%s: Precedence error in stack\n", __func__);
						exit(IFJ_SYNTAX_ERR);
					}

					
				}
				
				//E->E_sign_E
				else if(stack_top(&stack) == 'E')
				{
					stack_pop(&stack);

					switch(stack_top(&stack))
					{
						case sign_not_equal:
							type(&stack, &stack_index, INSTR_NEQ);
							break;

						case sign_equal:
							type(&stack, &stack_index, INSTR_EQ);
							break;

						case sign_greater_equal:
							type(&stack, &stack_index, INSTR_GTE);
							break;

						case sign_less_equal:
							type(&stack, &stack_index, INSTR_LTE);
							break;

						case sign_less:
							type(&stack, &stack_index, INSTR_LT);
							break;

						case sign_greater:
							type(&stack, &stack_index, INSTR_GT);
							break;

						case sign_slash:
							type(&stack, &stack_index, INSTR_DIV);
							break;

						case sign_times:
							type(&stack, &stack_index, INSTR_MUL);
							break;

						case sign_minus:
							type(&stack, &stack_index, INSTR_SUB);
							break;
						case sign_plus:
							type(&stack, &stack_index, INSTR_ADD);
							break;
						default:
							fprintf(stderr,"%s: Expected sign token\n", __func__);
							exit(IFJ_SYNTAX_ERR);
							break;
					}
				}
				
			case '#':

				/* Check for function call, if ID( then we will expect it to be function and return &current_token to syntax. analyator
				   */
				if(stack_top(&stack) == symbol_id)
				{
					if(get_sign(&current_token) == sign_lparen) {
						if(syntax_data.id != NULL) {
							free(syntax_data.id);
							syntax_data.id = ifj_strdup(current_token.val);
						}
						return -1; 
					}
					else
					{
						fprintf(stderr, "%s: Variable after variable is not allowed without sign between them\n", __func__);
						exit(IFJ_SEM_OTHER_ERR);
					}
				}
		}

		if(current_token.type == LEX_IDENTIFIER)
		{
			if(syntax_data.id != NULL)
			{
				free(syntax_data.id);
			}
			syntax_data.id = ifj_strdup(current_token.val);
		}
	}while(!(((stack_top(&stack) == 'E') && (stack_offset(&stack, 2) == symbol_dollar)) && ((get_sign(&current_token) == sign_rparen) || (current_token.type ==
						LEX_SEMICOLON))));

return final_index;	
}
Beispiel #4
0
ast_result_t pass_syntax(ast_t** astp, pass_opt_t* options)
{
  assert(astp != NULL);
  ast_t* ast = *astp;
  assert(ast != NULL);

  token_id id = ast_id(ast);
  ast_result_t r = AST_OK;

  switch(id)
  {
    case TK_SEMI:       r = syntax_semi(options, ast); break;
    case TK_TYPE:       r = syntax_entity(options, ast, DEF_TYPEALIAS); break;
    case TK_PRIMITIVE:  r = syntax_entity(options, ast, DEF_PRIMITIVE); break;
    case TK_STRUCT:     r = syntax_entity(options, ast, DEF_STRUCT); break;
    case TK_CLASS:      r = syntax_entity(options, ast, DEF_CLASS); break;
    case TK_ACTOR:      r = syntax_entity(options, ast, DEF_ACTOR); break;
    case TK_TRAIT:      r = syntax_entity(options, ast, DEF_TRAIT); break;
    case TK_INTERFACE:  r = syntax_entity(options, ast, DEF_INTERFACE); break;
    case TK_THISTYPE:   r = syntax_thistype(options, ast); break;
    case TK_ARROW:      r = syntax_arrowtype(options, ast); break;
    case TK_MATCH:      r = syntax_match(options, ast); break;
    case TK_FFIDECL:    r = syntax_ffi(options, ast, false); break;
    case TK_FFICALL:    r = syntax_ffi(options, ast, true); break;
    case TK_ELLIPSIS:   r = syntax_ellipsis(options, ast); break;
    case TK_CONSUME:    r = syntax_consume(options, ast); break;
    case TK_RETURN:
    case TK_BREAK:      r = syntax_return(options, ast, 1); break;
    case TK_CONTINUE:
    case TK_ERROR:      r = syntax_return(options, ast, 0); break;
    case TK_LET:
    case TK_VAR:        r = syntax_local(options, ast); break;
    case TK_EMBED:      r = syntax_embed(options, ast); break;
    case TK_TYPEPARAM:  r = syntax_type_param(options, ast); break;
    case TK_IFDEF:      r = syntax_ifdef(options, ast); break;
    case TK_USE:        r = syntax_use(options, ast); break;
    case TK_LAMBDACAPTURE:
                        r = syntax_lambda_capture(options, ast); break;
    case TK_COMPILE_INTRINSIC:
                        r = syntax_compile_intrinsic(options, ast); break;
    case TK_COMPILE_ERROR:
                        r = syntax_compile_error(options, ast); break;

    case TK_ISO:
    case TK_TRN:
    case TK_REF:
    case TK_VAL:
    case TK_BOX:
    case TK_TAG:        r = syntax_cap(options, ast); break;

    case TK_LAMBDA:     r = syntax_lambda(options, ast); break;
    case TK_OBJECT:     r = syntax_object(options, ast); break;
    case TK_FUN:        r = syntax_fun(options, ast); break;

    case TK_CAP_READ:
    case TK_CAP_SEND:
    case TK_CAP_SHARE:
    case TK_CAP_ALIAS:
    case TK_CAP_ANY:    r = syntax_cap_set(options, ast); break;

    case TK_VALUEFORMALARG:
    case TK_VALUEFORMALPARAM:
      ast_error(options->check.errors, ast,
        "Value formal parameters not yet supported");
      r = AST_ERROR;
      break;

    case TK_CONSTANT:
      ast_error(options->check.errors, ast,
        "Compile time expressions not yet supported");
      r = AST_ERROR;
      break;

    default: break;
  }

  if(is_expr_infix(id))
    r = syntax_infix_expr(options, ast);

  if(ast_checkflag(ast, AST_FLAG_MISSING_SEMI))
  {
    ast_error(options->check.errors, ast,
      "Use a semi colon to separate expressions on the same line");
    r = AST_ERROR;
  }

  return r;
}
Beispiel #5
0
ast_result_t pass_syntax(ast_t** astp, pass_opt_t* options)
{
  typecheck_t* t = &options->check;

  assert(astp != NULL);
  ast_t* ast = *astp;
  assert(ast != NULL);

  token_id id = ast_id(ast);

  // These node all use the data field as pointers to stuff
  if(id == TK_PROGRAM || id == TK_PACKAGE || id == TK_MODULE)
    return AST_OK;

  if(ast_checkflag(ast, AST_FLAG_TEST_ONLY))
  {
    // Test node, not allowed outside parse pass
    ast_error(ast, "Illegal character '$' found");
    return AST_ERROR;
  }

  ast_result_t r = AST_OK;

  switch(id)
  {
    case TK_SEMI:       r = syntax_semi(ast); break;
    case TK_TYPE:       r = syntax_entity(ast, DEF_TYPEALIAS); break;
    case TK_PRIMITIVE:  r = syntax_entity(ast, DEF_PRIMITIVE); break;
    case TK_CLASS:      r = syntax_entity(ast, DEF_CLASS); break;
    case TK_ACTOR:      r = syntax_entity(ast, DEF_ACTOR); break;
    case TK_TRAIT:      r = syntax_entity(ast, DEF_TRAIT); break;
    case TK_INTERFACE:  r = syntax_entity(ast, DEF_INTERFACE); break;
    case TK_THISTYPE:   r = syntax_thistype(t, ast); break;
    case TK_ARROW:      r = syntax_arrowtype(ast); break;
    case TK_MATCH:      r = syntax_match(ast); break;
    case TK_FFIDECL:    r = syntax_ffi(ast, false); break;
    case TK_FFICALL:    r = syntax_ffi(ast, true); break;
    case TK_ELLIPSIS:   r = syntax_ellipsis(ast); break;
    case TK_CONSUME:    r = syntax_consume(ast); break;
    case TK_RETURN:
    case TK_BREAK:      r = syntax_return(options, ast, 1); break;
    case TK_CONTINUE:
    case TK_ERROR:      r = syntax_return(options, ast, 0); break;
    case TK_LET:
    case TK_VAR:        r = syntax_local(ast); break;
    case TK_EMBED:      r = syntax_embed(ast); break;
    case TK_PARAM:      r = syntax_param(ast); break;
    case TK_TYPEPARAM:  r = syntax_type_param(ast); break;
    case TK_USE:        r = syntax_use(ast); break;
    case TK_LAMBDACAPTURE:
                        r = syntax_lambda_capture(ast); break;
    default: break;
  }

  if(is_expr_infix(id))
    r = syntax_infix_expr(ast);

  if(ast_checkflag(ast, AST_FLAG_MISSING_SEMI))
  {
    ast_error(ast,
      "Use a semi colon to separate expressions on the same line");
    r = AST_ERROR;
  }

  return r;
}