コード例 #1
0
ファイル: parserapi.c プロジェクト: DevL/ponyc
static void syntax_error(parser_t* parser, const char* expected,
  ast_t* ast, const char* terminating)
{
  assert(parser != NULL);
  assert(expected != NULL);
  assert(parser->token != NULL);

  if(parser->last_matched == NULL)
  {
    error(parser->source, token_line_number(parser->token),
      token_line_position(parser->token), "syntax error: no code found");
  }
  else
  {
    if(terminating == NULL)
    {
      error(parser->source, token_line_number(parser->token),
        token_line_position(parser->token),
        "syntax error: expected %s after %s", expected, parser->last_matched);
    }
    else
    {
      assert(ast != NULL);
      errorframe_t frame = NULL;
      ast_error_frame(&frame, ast, "syntax error: unterminated %s",
        terminating);
      errorframe(&frame, parser->source, token_line_number(parser->token),
        token_line_position(parser->token),
        "expected terminating %s before here", expected);
      errorframe_report(&frame);
    }
  }
}
コード例 #2
0
ファイル: ast.c プロジェクト: awaidmann/ponyc
void ast_error_continue(errors_t* errors, ast_t* ast, const char* fmt, ...)
{
  va_list ap;
  va_start(ap, fmt);
  errorv_continue(errors, token_source(ast->t), token_line_number(ast->t),
    token_line_position(ast->t), fmt, ap);
  va_end(ap);
}
コード例 #3
0
ファイル: parserapi.c プロジェクト: DevL/ponyc
static void fetch_next_lexer_token(parser_t* parser, bool free_prev_token)
{
  token_t* old_token = parser->token;
  token_t* new_token = lexer_next(parser->lexer);

  if(old_token != NULL)
    parser->last_token_line = token_line_number(old_token);

  if(old_token != NULL && token_get_id(new_token) == TK_EOF)
  {
    // Use location of last token for EOF to get better error reporting
    token_set_pos(new_token, token_source(old_token),
      token_line_number(old_token), token_line_position(old_token));
  }

  if(free_prev_token)
    token_free(old_token);

  parser->token = new_token;
}
コード例 #4
0
ファイル: ast.c プロジェクト: awaidmann/ponyc
void ast_error_frame(errorframe_t* frame, ast_t* ast, const char* fmt, ...)
{
  assert(frame != NULL);
  assert(ast != NULL);
  assert(fmt != NULL);

  va_list ap;
  va_start(ap, fmt);
  errorframev(frame, token_source(ast->t), token_line_number(ast->t),
    token_line_position(ast->t), fmt, ap);
  va_end(ap);
}
コード例 #5
0
ファイル: parserapi.c プロジェクト: DevL/ponyc
/* Tidy up a successfully parsed rule.
 * Args:
 *    rule_set is a NULL terminated list.
 *    out_found reports whether an optional token was found. Only set on
 *      success. May be set to NULL if this information is not needed.
 *
 * Returns:
 *    AST created, NULL for none.
 */
ast_t* parse_rule_complete(parser_t* parser, rule_state_t* state)
{
  assert(parser != NULL);
  assert(state != NULL);

  process_deferred_ast(parser, state);

  if(state->scope && state->ast != NULL)
    ast_scope(state->ast);

  if(trace_enable)
    printf("Rule %s: Complete\n", state->fn_name);

  if(state->restart == NULL)
    return state->ast;

  // We have a restart point, check next token is legal
  token_id id = current_token_id(parser);

  if(trace_enable)
    printf("Rule %s: Check restart set for next token %s\n", state->fn_name,
      token_print(parser->token));

  for(const token_id* p = state->restart; *p != TK_NONE; p++)
  {
    if(*p == id)
    {
      // Legal token found
      if(trace_enable)
        printf("Rule %s: Restart check successful\n", state->fn_name);

      return state->ast;
    }
  }

  // Next token is not in restart set, error
  if(trace_enable)
    printf("Rule %s: Restart check error\n", state->fn_name);

  assert(parser->token != NULL);
  error(parser->source, token_line_number(parser->token),
    token_line_position(parser->token),
    "syntax error: unexpected token %s after %s", token_print(parser->token),
    state->desc);

  ast_free(state->ast);
  parser->failed = true;
  ditch_restart(parser, state);
  return NULL;
}
コード例 #6
0
ファイル: parserapi.c プロジェクト: DevL/ponyc
// Add an AST node for the specified token, which may be deferred
void add_deferrable_ast(parser_t* parser, rule_state_t* state, token_id id)
{
  assert(parser->token != NULL);

  if(!state->matched && state->ast == NULL && !state->deferred)
  {
    // This is the first AST node, defer creation
    state->deferred = true;
    state->deferred_id = id;
    state->line = token_line_number(parser->token);
    state->pos = token_line_position(parser->token);
    return;
  }

  add_ast(parser, state, ast_new(parser->token, id), default_builder);
}
コード例 #7
0
ファイル: builder.c プロジェクト: Potpourri/ponyc
// Get the next token ready for when we need it
static void get_next_token(build_parser_t* builder)
{
  assert(builder != NULL);

  if(builder->have_token)
    return;

  if(builder->token != NULL)
    token_free(builder->token);

  builder->token = lexer_next(builder->lexer);
  assert(builder->token != NULL);
  ast_token_id id;

  switch(token_get_id(builder->token))
  {
    case TK_LPAREN_NEW:
    case TK_LPAREN:     id = AT_LPAREN;  break;
    case TK_RPAREN:     id = AT_RPAREN;  break;
    case TK_LSQUARE_NEW:
    case TK_LSQUARE:    id = AT_LSQUARE; break;
    case TK_RSQUARE:    id = AT_RSQUARE; break;
    case TK_LBRACE:     id = AT_LBRACE;  break;
    case TK_RBRACE:     id = AT_RBRACE;  break;
    case TK_EOF:        id = AT_EOF;     break;
    case TK_LEX_ERROR:  id = AT_ERROR;   break;
    case TK_ID:         id = AT_ID;      break;
    case TK_STRING:     id = AT_STRING;  break;
    default:            id = AT_TOKEN;   break;
  }

  //printf("Got token %s %d -> %d\n", token_print(builder->token),
  //  token_get_id(builder->token), id);
  builder->id = id;
  builder->have_token = true;
  builder->line = token_line_number(builder->token);
  builder->pos = token_line_position(builder->token);
}
コード例 #8
0
ファイル: ast.c プロジェクト: awaidmann/ponyc
size_t ast_line(ast_t* ast)
{
  assert(ast != NULL);
  return token_line_number(ast->t);
}
コード例 #9
0
ファイル: parserapi.c プロジェクト: DevL/ponyc
/* Check if current token matches any in given set and consume on match.
 * Args:
 *    terminating is the description of the structure this token terminates,
 *      NULL for none. Used only for error messages.
 *    id_set is a TK_NONE terminated list.
 *    make_ast specifies whether to construct an AST node on match or discard
 *      consumed token.
 *    out_found reports whether an optional token was found. Only set on
 *      success. May be set to NULL if this information is not needed.
 *
 * Returns:
 *    PARSE_OK on success.
 *    PARSE_ERROR to propogate a lexer error.
 *    RULE_NOT_FOUND if current token is not is specified set.
 *    NULL to propogate a restarted error.
 */
ast_t* parse_token_set(parser_t* parser, rule_state_t* state, const char* desc,
  const char* terminating, const token_id* id_set, bool make_ast,
  bool* out_found)
{
  assert(parser != NULL);
  assert(state != NULL);
  assert(id_set != NULL);

  token_id id = current_token_id(parser);

  if(id == TK_LEX_ERROR)
    return propogate_error(parser, state);

  if(desc == NULL)
    desc = token_id_desc(id_set[0]);

  if(trace_enable)
  {
    printf("Rule %s: Looking for %s token%s %s. Found %s. ",
      state->fn_name,
      (state->deflt_id == TK_LEX_ERROR) ? "required" : "optional",
      (id_set[1] == TK_NONE) ? "" : "s", desc,
      token_print(parser->token));
  }

  for(const token_id* p = id_set; *p != TK_NONE; p++)
  {
    // Match new line if the next token is the first on a line
    if(*p == TK_NEWLINE)
    {
      assert(parser->token != NULL);
      size_t last_token_line = parser->last_token_line;
      size_t next_token_line = token_line_number(parser->token);
      bool is_newline = (next_token_line != last_token_line);

      if(out_found != NULL)
        *out_found = is_newline;

      if(trace_enable)
        printf("\\n %smatched\n", is_newline ? "" : "not ");

      state->deflt_id = TK_LEX_ERROR;
      return PARSE_OK;
    }

    if(id == *p)
    {
      // Current token matches one in set
      if(trace_enable)
        printf("Compatible\n");

      parser->last_matched = token_print(parser->token);

      if(make_ast)
        return handle_found(parser, state, consume_token(parser),
          default_builder, out_found);

      // AST not needed, discard token
      consume_token_no_ast(parser);
      return handle_found(parser, state, NULL, NULL, out_found);
    }
  }

  // Current token does not match any in current set
  if(trace_enable)
    printf("Not compatible\n");

  return handle_not_found(parser, state, desc, terminating, out_found);
}