예제 #1
0
파일: reference.c 프로젝트: jbmikk/pars
static int _clone_fs_action(BMapAction *action_set, Reference *ref, int key, Action *action)
{
	int result = REF_RESULT_SOLVED;
	//TODO: Make type for clone a parameter, do not override by
	// default.

	// When a symbol is present, assume nonterminal invocation
	int clone_type;

	if(ref->type == REF_TYPE_DEFAULT) {
		// It could happen when merging loops in final states
		// that action->type == ACTION_REDUCE
		clone_type = action->type;
	} else if(ref->type == REF_TYPE_SHIFT) {
		if (action->type == ACTION_REDUCE) {
			// This could happen when the start state of a
			// nonterminal is also an end state.
			trace_op(
				"skip",
				ref->state,
				action,
				key,
				"reduction on first-set",
				0
			);
			goto end;
		}
		clone_type = ACTION_SHIFT;
	} else if(ref->type == REF_TYPE_START) {
		if (action->type == ACTION_REDUCE || action->type == ACTION_ACCEPT) {
			trace_op(
				"skip",
				ref->state,
				action,
				key,
				"reduction on first-set",
				0
			);
			goto end;
		}
		clone_type = ACTION_START;
	}

	//TODO: Detect collision for ranges (only testing `key` for now)
	Action *col = state_get_transition(ref->state, key);

	// TODO: Unify collision detection, skipping and merging with the ones
	// used in the state functions.
	if(col && ref->strategy == REF_STRATEGY_MERGE) {
		if(!action_compare(*action, *col)) {
			trace_op(
				"collision",
				ref->state,
				action,
				key,
				"skip duplicate",
				0
			);
			goto end;
		}

		if(col->state == NULL || action->state == NULL) {
			trace_op(
				"collision",
				ref->state,
				action,
				key,
				"unhandled",
				0
			);
			goto end;
		}

		//Collision: redefine actions in order to disambiguate.
		trace_op(
			"collision",
			ref->state,
			col,
			key,
			"deambiguate state",
			0
		);

		//TODO: should only merge if actions are identical
		//TODO: Make this work with ranges.
		State *merge = malloc(sizeof(State));
		state_init(merge);

		//Merge first set for the actions continuations.
		state_add_reference(merge, REF_TYPE_DEFAULT, REF_STRATEGY_MERGE, NULL, col->state);
		state_add_reference(merge, REF_TYPE_DEFAULT, REF_STRATEGY_MERGE, NULL, action->state);

		//Create unified action pointing to merged state.
		action_init(col, clone_type, col->reduction, merge, col->flags, col->end_symbol);

		result = REF_RESULT_CHANGED;
	} else {

		//No collision detected, clone the action an add it.
		Action clone;
		action_init(&clone, clone_type, action->reduction, action->state, action->flags, action->end_symbol);

		trace_op(
			"add",
			ref->state,
			&clone,
			key,
			"first-set",
			0
		);

		bmap_action_m_append(action_set, key, clone);
	}
end:
	return result;
}
예제 #2
0
파일: reference.c 프로젝트: jbmikk/pars
static void _clone_rs_action(Reference *ref, BMapAction *action_set, Nonterminal *nt, int key, Action *action)
{
	Symbol *sb = ref->symbol;
	// Empty transitions should not be cloned.
	// They should be followed recursively to get the whole follow set,
	// otherwise me might loose reductions.

	// Always reduce?
	int clone_type = ACTION_REDUCE;

	Action *col = state_get_transition(nt->end, key);

	// TODO: Unify collision detection, skipping and merging with the ones
	// used in the state functions.
	if(col) {
		if(!action_compare(*action, *col)) {
			trace_op(
				"collision",
				nt->end,
				action,
				key,
				"skip duplicate",
				0
			);
			goto end;
		}

		//Collision: redefine actions in order to disambiguate.
		trace_op(
			"collision",
			nt->end,
			col,
			key,
			"unhandled return set collision",
			0
		);

		// TODO: sentinel?
	} else {

		//No collision detected, clone the action an add it.
		Action clone;
		action_init(&clone, clone_type, sb->id, NULL, action->flags, action->end_symbol);

		// TODO: Empty transitions should not be cloned.
		// They should be followed recursively to get the whole
		// follow set.
		// This happens when:
		// * A nonterminal is invoked at the end of a repetition and
		//   the repetition is within a group. An empty transition
		//   will be created between the repetition and the group,
		//   when the nonterminal is solved the empty transition will
		//   be found in the follow-set.

		trace_op(
			"add",
			nt->end,
			&clone,
			key,
			"return-set",
			0
		);

		bmap_action_m_append(action_set, key, clone);
	}
end:
	return;
}
예제 #3
0
파일: runops_cores.c 프로젝트: gitpan/ponie
opcode_t *
runops_slow_core(struct Parrot_Interp *interpreter, opcode_t *pc)
{
#ifdef USE_TRACE_INTERP
    Interp * trace_i;
    struct Parrot_Context *trace_ctx;
#endif
    opcode_t *opc, *ostart, *oend;
    static size_t dod, gc;

#ifdef code_start
#  undef code_start
#endif
#ifdef code_end
#  undef code_end
#endif

#define  code_start interpreter->code->byte_code
#define  code_end   (interpreter->code->byte_code + \
        interpreter->code->cur_cs->base.size)


#ifdef USE_TRACE_INTERP
    if (Interp_flags_TEST(interpreter, PARROT_TRACE_FLAG)) {
        trace_i = make_interpreter(interpreter, NO_FLAGS);
        Parrot_init(trace_i);
        /* remeber old context */
        trace_ctx = mem_sys_allocate(sizeof(struct Parrot_Context));
        mem_sys_memcopy(trace_ctx, &trace_i->ctx,
                sizeof(struct Parrot_Context));
        /* copy in current */
        mem_sys_memcopy(&trace_i->ctx, &interpreter->ctx,
                sizeof(struct Parrot_Context));
        trace_i->code = interpreter->code;
        Interp_flags_SET(trace_i, PARROT_EXTERN_CODE_FLAG);
    }
#endif

    dod = interpreter->dod_runs;
    gc = interpreter->collect_runs;
    while (pc) {/* && pc >= code_start && pc < code_end) {*/
        interpreter->cur_pc = pc;
        opc = pc;
        ostart = code_start;
        oend = code_end;

        DO_OP(pc, interpreter);

        if (Interp_flags_TEST(interpreter, PARROT_TRACE_FLAG)) {
#ifdef USE_TRACE_INTERP
            mem_sys_memcopy(&trace_i->ctx, &interpreter->ctx,
                    sizeof(struct Parrot_Context));
            trace_op(trace_i, ostart, oend, opc);
#else
            trace_op(interpreter, ostart, oend, opc);
#endif
            if (dod != interpreter->dod_runs) {
                dod = interpreter->dod_runs;
                PIO_printf(interpreter, "       DOD\n");
            }
            if (gc != interpreter->collect_runs) {
                gc = interpreter->collect_runs;
                PIO_printf(interpreter, "       GC\n");
            }
        }
    }
#ifdef USE_TRACE_INTERP
    if (Interp_flags_TEST(interpreter, PARROT_TRACE_FLAG)) {
        /* restore trace context */
        mem_sys_memcopy(&trace_i->ctx, trace_ctx,
                sizeof(struct Parrot_Context));
        mem_sys_free(trace_ctx);
    }
#endif

    /*    if (pc && (pc < code_start || pc >= code_end)) {
        internal_exception(INTERP_ERROR,
       "Error: Control left bounds of byte-code block (now at location %d)!\n",
       (int)(pc - code_start));
       }*/
#undef code_start
#undef code_end
    return pc;
}