예제 #1
0
int OMP_output_st_pragma(expv v)
{
    switch(OMP_st_flag){
    case OMP_ST_ATOMIC:
	output_statement(OMP_pragma_list(OMP_ATOMIC, list0(LIST), 
					 list1(EXPR_STATEMENT, v)));
	return TRUE;
    default:
	return FALSE;
    }
}
예제 #2
0
static TYPE_DESC
get_intrinsic_return_type(intrinsic_entry *ep, expv args, expv kindV) {
    BASIC_DATA_TYPE bType = TYPE_UNKNOWN;
    TYPE_DESC bTypeDsc = NULL;
    TYPE_DESC ret = NULL;
    expv a = NULL;
    
    if (INTR_RETURN_TYPE(ep) == INTR_TYPE_NONE) {
        return NULL;
    }

    if (INTR_RETURN_TYPE_SAME_AS(ep) >= 0) {
        /* return type is in args. */
        a = expr_list_get_n(args, INTR_RETURN_TYPE_SAME_AS(ep));
        if (!(isValidTypedExpv(a))) {
            return NULL;
        }
        ret = EXPV_TYPE(a);
    } else {
        switch (INTR_RETURN_TYPE_SAME_AS(ep)) {

            case -1 /* if not dynamic return type,
                        argument is scalar/array and
                        return type is scalar/array */ :
            case -6 /* if not dynamic return type,
                        argument is scalar/array, return
                        return type is scalar */ : {

                if (!(INTR_IS_RETURN_TYPE_DYNAMIC(ep)) &&
                    (INTR_RETURN_TYPE(ep) != INTR_TYPE_ALL_NUMERICS &&
                     INTR_RETURN_TYPE(ep) != INTR_TYPE_NUMERICS)) {
                    bType = intr_type_to_basic_type(INTR_RETURN_TYPE(ep));
                    if (bType == TYPE_UNKNOWN) {
                        fatal("invalid intrinsic return type (case -1/-6).");
                        /* not reached. */
                        return NULL;
                    } else {
                        if (kindV == NULL) {
                            ret = (bType != TYPE_CHAR) ? type_basic(bType) :
                                type_char(1);
                        } else {
                            /*
                             * Don't use BASIC_TYPE_DESC(bType) very
                             * here, since we need to set a kind to
                             * the TYPE_DESC.
                             */
                            ret = type_basic(bType);
                            TYPE_KIND(ret) = kindV;
                        }
                    }
                    ret = intr_convert_to_dimension_ifneeded(
                        ep, args, ret);
                } else {
                    expv shape = list0(LIST);
                    TYPE_DESC tp;

                    switch (INTR_OP(ep)) {

                    case INTR_ALL:
                    case INTR_ANY:
                    case INTR_MAXVAL:
                    case INTR_MINVAL:
                    case INTR_PRODUCT:
                    case INTR_SUM:
                    case INTR_COUNT:
                    {
                        /* intrinsic arguments */
                        expv array, dim;

                        array = expr_list_get_n(args, 0);
                        if (!(isValidTypedExpv(array))) {
                            return NULL;
                        }
                        tp = EXPV_TYPE(array);

                        dim = expr_list_get_n(args, 1);
                        if (!(isValidTypedExpv(dim))) {
                            return NULL;
                        }

                        /* set basic type of array type */
                        switch (INTR_OP(ep)) {
                        case INTR_ALL:
                        case INTR_ANY:
                            bType = TYPE_LOGICAL;
                            break;
                        case INTR_COUNT:
                            bType = TYPE_INT;
                            break;
                        default:
                            bType = get_basic_type(tp);
                            break;
                        }

                        if (kindV == NULL) {
                            bTypeDsc = BASIC_TYPE_DESC(bType);
                        } else {
                            bTypeDsc = type_basic(bType);
                            TYPE_KIND(bTypeDsc) = kindV;
                        }

                        dim = expv_reduce(dim, FALSE);

                        if(EXPV_CODE(dim) == INT_CONSTANT) {
                            int nDim;
                            nDim  = (int)EXPV_INT_VALUE(dim);

                            if(nDim > TYPE_N_DIM(tp) || nDim <= 0) {
                                error("value DIM of intrinsic %s "
                                      "out of range.", INTR_NAME(ep));
                                return NULL;
                            }

                            generate_contracted_shape_expr(
                                tp, shape, TYPE_N_DIM(tp) - nDim);
                        } else {
                            generate_assumed_shape_expr(
                                shape, TYPE_N_DIM(tp) - 1);
                        }
                    }
                    break;

                    case INTR_SPREAD:
                    {
                        /* intrinsic arguments */
                        expv array, dim, ncopies;

                        array = expr_list_get_n(args, 0);
                        if (!(isValidTypedExpv(array))) {
                            return NULL;
                        }
                        dim = expr_list_get_n(args, 1);
                        if (!(isValidTypedExpv(dim))) {
                            return NULL;
                        }
                        ncopies = expr_list_get_n(args, 2);
                        if (!(isValidTypedExpv(ncopies))) {
                            return NULL;
                        }

                        tp = EXPV_TYPE(array);
                        bType = get_basic_type(tp);
                        if (kindV == NULL) {
                            bTypeDsc = BASIC_TYPE_DESC(bType);
                        } else {
                            bTypeDsc = type_basic(bType);
                            TYPE_KIND(bTypeDsc) = kindV;
                        }

                        dim = expv_reduce(dim, FALSE);

                        if(EXPR_CODE(dim) == INT_CONSTANT) {
                            int nDim;
                            nDim  = (int)EXPV_INT_VALUE(dim);

                            if(nDim > (TYPE_N_DIM(tp) + 1) || nDim <= 0) {
                                error("value DIM of intrinsic %s "
                                      "out of range.", INTR_NAME(ep));
                                return NULL;
                            }

                            generate_expand_shape_expr(
                                tp, shape, ncopies, TYPE_N_DIM(tp) + 1 - nDim);
                        } else {
                            generate_assumed_shape_expr(
                                shape, TYPE_N_DIM(tp) - 1);
                        }
                    }
                    break;

                    case INTR_RESHAPE:
                    {
                        /* intrinsic arguments */
                        expv source, arg_shape;

                        source = expr_list_get_n(args, 0);
                        if (!(isValidTypedExpv(source))) {
                            return NULL;
                        }
                        arg_shape = expr_list_get_n(args, 1);
                        if (!(isValidTypedExpv(arg_shape))) {
                            return NULL;
                        }

                        tp = EXPV_TYPE(source);
                        bType = get_basic_type(tp);
                        if (kindV == NULL) {
                            bTypeDsc = BASIC_TYPE_DESC(bType);
                        } else {
                            bTypeDsc = type_basic(bType);
                            TYPE_KIND(bTypeDsc) = kindV;
                        }

                        tp = EXPV_TYPE(arg_shape);
                        if (TYPE_N_DIM(tp) != 1) {
                            error("SHAPE argument of intrinsic "
                                  "RESHAPE is not vector.");
                            return NULL;
                        }

                        /*
                         * We can't determine # of the elements in
                         * this array that represents dimension of the
                         * return type, which is identical to the
                         * reshaped array. In order to express this,
                         * we introduce a special TYPE_DESC, which is
                         * having a flag to specify that the type is
                         * generated by the reshape() intrinsic.
                         */

                        /*
                         * dummy one dimensional assumed array.
                         */
                        generate_assumed_shape_expr(shape, 2);
                        ret = compile_dimensions(bTypeDsc, shape);
                        fix_array_dimensions(ret);
                        TYPE_IS_RESHAPED(ret) = TRUE;

                        return ret;
                    }
                    break;

                    case INTR_MATMUL:
                    {
                        expv m1 = expr_list_get_n(args, 0);
                        expv m2 = expr_list_get_n(args, 1);
                        TYPE_DESC t1 = EXPV_TYPE(m1);
                        TYPE_DESC t2 = EXPV_TYPE(m2);
                        expv s1 = list0(LIST);
                        expv s2 = list0(LIST);

                        /*
                         * FIXME:
                         *	Should we use
                         *	get_binary_numeric_intrinsic_operation_type()
                         *	instead of max_type()? I think so but
                         *	not sure at this moment.
                         */
                        bType = get_basic_type(max_type(t1, t2));

                        if (kindV == NULL) {
                            bTypeDsc = BASIC_TYPE_DESC(bType);
                        } else {
                            bTypeDsc = type_basic(bType);
                            TYPE_KIND(bTypeDsc) = kindV;
                        }

                        generate_shape_expr(t1, s1);
                        generate_shape_expr(t2, s2);

                        if (TYPE_N_DIM(t1) == 2 &&
                            TYPE_N_DIM(t2) == 2) {
                            /*
                             * (n, m) * (m, k) => (n, k).
                             */
                            shape = list2(LIST,
                                          EXPR_ARG1(s1), EXPR_ARG2(s2));
                        } else if (TYPE_N_DIM(t1) == 2 &&
                                   TYPE_N_DIM(t2) == 1) {
                            /*
                             * (n, m) * (m) => (n).
                             */
                            shape = list1(LIST, EXPR_ARG1(s1));
                        } else if (TYPE_N_DIM(t1) == 1 &&
                                   TYPE_N_DIM(t2) == 2) {
                            /*
                             * (m) * (m, k) => (k).
                             */
                            shape = list1(LIST, EXPR_ARG2(s2));
                        } else {
                            error("an invalid dimension combination for "
                                  "matmul(), %d and %d.",
                                  TYPE_N_DIM(t1), TYPE_N_DIM(t2));
                            return NULL;
                        }

                        ret = compile_dimensions(bTypeDsc, shape);
                        fix_array_dimensions(ret);

                        return ret;
                    }
                    break;

                    case INTR_DOT_PRODUCT:
                    {
                        expv m1 = expr_list_get_n(args, 0);
                        expv m2 = expr_list_get_n(args, 1);
                        TYPE_DESC t1 = EXPV_TYPE(m1);
                        TYPE_DESC t2 = EXPV_TYPE(m2);

                        if (TYPE_N_DIM(t1) == 1 &&
                            TYPE_N_DIM(t2) == 1) {
                            TYPE_DESC tp =
                                get_binary_numeric_intrinsic_operation_type(
                                    t1, t2);
                            return array_element_type(tp);
                        } else {
                            error("argument(s) is not a one-dimensional "
                                  "array.");
                            return NULL;
                        }
                    }
                    break;

		    case INTR_PACK:
		    {

		      if (INTR_N_ARGS(ep) == 3){
			expv v = expr_list_get_n(args, 2);
			return EXPV_TYPE(v);
		      }
		      else {
			a = expr_list_get_n(args, 0);
			if (!(isValidTypedExpv(a))) {
			  return NULL;
			}

			bType = get_basic_type(EXPV_TYPE(a));
			bTypeDsc = BASIC_TYPE_DESC(bType);
			expr dims = list1(LIST, NULL);
			ret = compile_dimensions(bTypeDsc, dims);
			fix_array_dimensions(ret);
			return ret;
		      }
		    }
		    break;

		    case INTR_UNPACK:
		    {
			a = expr_list_get_n(args, 0);
			if (!(isValidTypedExpv(a))) {
			  return NULL;
			}
			bType = get_basic_type(EXPV_TYPE(a));
			bTypeDsc = BASIC_TYPE_DESC(bType);

			a = expr_list_get_n(args, 1);
			if (!(isValidTypedExpv(a))) {
			  return NULL;
			}
			TYPE_DESC tp = EXPV_TYPE(a);
			ret = copy_dimension(tp, bTypeDsc);
			fix_array_dimensions(ret);
			return ret;
		    }
		    break;

                    default:
                    {
                        /* not  reached ! */
                        ret = BASIC_TYPE_DESC(TYPE_GNUMERIC_ALL);
                    }

                    }

                    ret = compile_dimensions(bTypeDsc, shape);
                    fix_array_dimensions(ret);
                }

                break;
            }

            case -2: {
                /*
                 * Returns BASIC_TYPE of the first arg.
                 */
                a = expr_list_get_n(args, 0);
                if (!(isValidTypedExpv(a))) {
                    return NULL;
                }
                bType = get_basic_type(EXPV_TYPE(a));
                if (kindV == NULL) {
                    ret = BASIC_TYPE_DESC(bType);
                } else {
                    ret = type_basic(bType);
                    TYPE_KIND(ret) = kindV;
                }
                break;
            }

            case -3: {
                /*
                 * Returns single dimension array of integer having
                 * elemnets that equals to the first arg's dimension.
                 */
                /*
                 * FIXME:
                 *	No need to check kindV?? I believe we don't, though.
                 */
                bTypeDsc = BASIC_TYPE_DESC(TYPE_INT);
                TYPE_DESC tp = NULL;
                expr dims = NULL;
                int nDims = 0;
                a = expr_list_get_n(args, 0);
                if (!(isValidTypedExpv(a))) {
                    return NULL;
                }

                bTypeDsc = BASIC_TYPE_DESC(TYPE_INT);
                tp = EXPV_TYPE(a);
                nDims = TYPE_N_DIM(tp);
                dims = list1(LIST, make_int_enode(nDims));
                ret = compile_dimensions(bTypeDsc, dims);
                fix_array_dimensions(ret);

                break;
            }

            case -4:{
                /*
                 * Returns transpose of the first arg (matrix).
                 */
                TYPE_DESC tp = NULL;
                expr dims = list0(LIST);

                a = expr_list_get_n(args, 0);
                if (!(isValidTypedExpv(a))) {
                    return NULL;
                }
                tp = EXPV_TYPE(a);
                bType = get_basic_type(tp);
                if (kindV == NULL) {
                    bTypeDsc = BASIC_TYPE_DESC(bType);
                } else {
                    bTypeDsc = type_basic(bType);
                    TYPE_KIND(bTypeDsc) = kindV;
                }

                if (TYPE_N_DIM(tp) != 2) {
                    error("Dimension is not two.");
                    return NULL;
                }

                generate_reverse_dimension_expr(tp, dims);
                ret = compile_dimensions(bTypeDsc, dims);
                fix_array_dimensions(ret);

                break;
            }

            case -5: {
                /*
                 * -5 : BASIC_TYPE of return type is 'returnType' and
                 * kind of return type is same as first arg.
                 */
                int nDims = 0;
                TYPE_DESC tp = NULL;

                a = expr_list_get_n(args, 0);
                if (!(isValidTypedExpv(a))) {
                    return NULL;
                }

                tp = EXPV_TYPE(a);

                switch (INTR_OP(ep)) {
                    case INTR_AIMAG: case INTR_DIMAG: {
                        bType = get_basic_type(tp);
                        if (bType != TYPE_COMPLEX &&
                            bType != TYPE_DCOMPLEX) {
                            error("argument is not a complex type.");
                            return NULL;
                        }
                        bType = (bType == TYPE_COMPLEX) ?
                            TYPE_REAL : TYPE_DREAL;
                        break;
                    }
                    default: {
                        bType = intr_type_to_basic_type(INTR_RETURN_TYPE(ep));
                        break;
                    }
                }

                if (bType == TYPE_UNKNOWN) {
                    fatal("invalid intrinsic return type (case -5).");
                    /* not reached. */
                    return NULL;
                }
                bTypeDsc = type_basic(bType);
                TYPE_KIND(bTypeDsc) = TYPE_KIND(tp);

                if ((nDims = TYPE_N_DIM(tp)) > 0) {
                    ret = copy_dimension(tp, bTypeDsc);
                    fix_array_dimensions(ret);
                } else {
                    ret = bTypeDsc;
                }

                break;
            }

            case -7: {
                TYPE_DESC lhsTp = new_type_desc();
                TYPE_BASIC_TYPE(lhsTp) = TYPE_LHS;
                TYPE_ATTR_FLAGS(lhsTp) |= TYPE_ATTR_TARGET;
                ret = lhsTp;
                break;
            }

            case -8: {
                bType = intr_type_to_basic_type(INTR_RETURN_TYPE(ep));
                if (bType == TYPE_UNKNOWN) {
                    fatal("invalid intrinsic return type (case -8).");
                    return NULL;
                } else {
                    ret = type_basic(bType);
                }
                TYPE_SET_EXTERNAL(ret);
                break;
            }

            case -9: {
                bType = intr_type_to_basic_type(INTR_RETURN_TYPE(ep));
                ret = type_basic(bType);
                break;
            }

            default: {
                fatal("%s: Unknown return type specification.", __func__);
                break;
            }
        }
    }

    return ret;
}
예제 #3
0
expv 
compile_intrinsic_call(ID id, expv args) {
    intrinsic_entry *ep = NULL;
    int found = 0;
    int nArgs = 0;
    int nIntrArgs = 0;
    int i;
    expv ret = NULL;
    expv a = NULL;
    TYPE_DESC tp = NULL, ftp;
    list lp;
    INTR_OPS iOps = INTR_END;
    const char *iName = NULL;
    expv kindV = NULL;
    int typeNotMatch = 0;
    int isVarArgs = 0;
    EXT_ID extid;

    if (SYM_TYPE(ID_SYM(id)) != S_INTR) {
      //fatal("%s: not intrinsic symbol", __func__);

      // declarea as intrinsic but not defined in the intrinc table

      SYM_TYPE(ID_SYM(id)) = S_INTR;

      if (args == NULL) {
        args = list0(LIST);
      }

      if (ID_TYPE(id) == NULL) implicit_declaration(id);
      tp = ID_TYPE(id);
      //tp = BASIC_TYPE_DESC(TYPE_SUBR);

      expv symV = expv_sym_term(F_FUNC, NULL, ID_SYM(id));

      ftp = function_type(tp);
      TYPE_SET_INTRINSIC(ftp);

      extid = new_external_id_for_external_decl(ID_SYM(id), ftp);
      ID_TYPE(id) = ftp;
      PROC_EXT_ID(id) = extid;
      if (TYPE_IS_EXTERNAL(tp)){
	ID_STORAGE(id) = STG_EXT;
      }
      else{
	EXT_PROC_CLASS(extid) = EP_INTRINSIC;
      }

      ret = expv_cons(FUNCTION_CALL, tp, symV, args);
      return ret;
    }

    ep = &(intrinsic_table[SYM_VAL(ID_SYM(id))]);
    iOps = INTR_OP(ep);
    iName = ID_NAME(id);

    /* Count a number of argument, first. */
    nArgs = 0;
    if (args == NULL) {
        args = list0(LIST);
    }
    FOR_ITEMS_IN_LIST(lp, args) {
        nArgs++;
    }

    /* Search an intrinsic by checking argument types. */
    found = 0;
    for (;
         ((INTR_OP(ep) == iOps) &&
          ((strcasecmp(iName, INTR_NAME(ep)) == 0) ||
           !(isValidString(INTR_NAME(ep)))));
         ep++) {

        kindV = NULL;
        typeNotMatch = 0;
        isVarArgs = 0;

        /* Check a number of arguments. */
        if (INTR_N_ARGS(ep) < 0 ||
            INTR_N_ARGS(ep) == nArgs) {
            /* varriable args or no kind arg. */
            if (INTR_N_ARGS(ep) < 0) {
                isVarArgs = 1;
            }
            nIntrArgs = nArgs;
        } else if (INTR_HAS_KIND_ARG(ep) &&
                   ((INTR_N_ARGS(ep) + 1) == nArgs)) {
            /* could be intrinsic call with kind arg. */

            expv lastV = expr_list_get_n(args, nArgs - 1);
            if (lastV == NULL) {
                return NULL;    /* error recovery */
            }
            if (EXPV_KW_IS_KIND(lastV)) {
                goto gotKind;
            }
            tp = EXPV_TYPE(lastV);
            if (!(isValidType(tp))) {
                return NULL;    /* error recovery */
            }
            if (TYPE_BASIC_TYPE(tp) != TYPE_INT) {
                /* kind arg must be integer type. */
                continue;
            }

            gotKind:
            nIntrArgs = INTR_N_ARGS(ep);
            kindV = lastV;
        } else {
            continue;
        }

        /* The number of arguments matchs. Then check types. */
        for (i = 0; i < nIntrArgs; i++) {
            a = expr_list_get_n(args, i);
            if (a == NULL) {
                return NULL;    /* error recovery */
            }
            tp = EXPV_TYPE(a);
            if (!(isValidType(tp))) {
	      //return NULL;    /* error recovery */
	      continue;
            }
            if (compare_intrinsic_arg_type(a, tp,
                                           ((isVarArgs == 0) ?
                                            INTR_ARG_TYPE(ep)[i] :
                                            INTR_ARG_TYPE(ep)[0])) != 0) {
                /* Type mismatch. */
                typeNotMatch = 1;
                break;
            }
        }
        if (typeNotMatch == 1) {
            continue;
        } else {
            found = 1;
            break;
        }
    }

    if (found == 1) {
        /* Yes we found an intrinsic to use. */
        SYMBOL sp = NULL;
        expv symV = NULL;

        /* Then we have to determine return type. */
        if (INTR_RETURN_TYPE(ep) != INTR_TYPE_NONE) {
            tp = get_intrinsic_return_type(ep, args, kindV);
            if (!(isValidType(tp))) {
	      //fatal("%s: can't determine return type.", __func__);
	      //return NULL;
	      tp = BASIC_TYPE_DESC(TYPE_GNUMERIC_ALL);
            }
        } else {
            tp = BASIC_TYPE_DESC(TYPE_SUBR);
        }

        /* Finally find symbol for the intrinsic and make it expv. */
        sp = find_symbol((char *)iName);
        if (sp == NULL) {
            fatal("%s: symbol '%s' is not created??",
                  __func__,
                  INTR_NAME(ep));
            /* not reached */
            return NULL;
        }
        symV = expv_sym_term(F_FUNC, NULL, sp);
        if (symV == NULL) {
            fatal("%s: symbol expv creation failure.", __func__);
            /* not reached */
            return NULL;
        }

        ftp = function_type(tp);
        TYPE_SET_INTRINSIC(ftp);
        /* set external id for functionType's type ID.
         * dont call declare_external_id() */
        extid = new_external_id_for_external_decl(ID_SYM(id), ftp);
        ID_TYPE(id) = ftp;
        PROC_EXT_ID(id) = extid;
        if(TYPE_IS_EXTERNAL(tp)){
           ID_STORAGE(id) = STG_EXT;
        }else{
           EXT_PROC_CLASS(extid) = EP_INTRINSIC;
        }
        ret = expv_cons(FUNCTION_CALL, tp, symV, args);
    }

    if (ret == NULL) {
        error_at_node((expr)args,
                      "argument(s) mismatch for an intrinsic '%s()'.",
                      iName);
    }
    return ret;
}
예제 #4
0
void make_target_parser(
    tgt::parsing_table&             table,
    std::map<std::string, size_t>&  token_id_map,
    action_map_type&                actions,
    const value_type&               ast,
    std::map<std::string, Type>&    terminal_types,
    std::map<std::string, Type>&    nonterminal_types) {

    auto doc = get_node<Document>(ast);

    // 各種データ
    // ...終端記号表(名前→terminal)
    std::unordered_map<std::string, tgt::terminal>      terminals;
    // ...非終端記号表(名前→nonterminal)
    std::unordered_map<std::string, tgt::nonterminal>   nonterminals;

    int error_token = -1;

    // terminalsの作成
    token_id_map["eof"] = 0;
    int id_seed = 1;
    for (const auto& x: terminal_types) {
        if (x.second.name != "$error") { continue; }
        token_id_map[x.first] = error_token = id_seed;
        terminals[x.first] = tgt::terminal(x.first, id_seed++);
    }
    for (const auto& x: terminal_types) {
        if (x.second.name == "$error") { continue; }
        token_id_map[x.first] = id_seed;
        terminals[x.first] = tgt::terminal(x.first, id_seed++);
    }

    // nonterminalsの作成
    for (const auto& x: nonterminal_types) {
        nonterminals[x.first] = tgt::nonterminal(x.first);
    }

    // pending(あとでまとめてEBNFを展開したルールを作成する
    std::vector<Pending> pending;

    // 規則
    tgt::grammar g;
    for (const auto& rule: doc->rules->rules) {
        const tgt::nonterminal& rule_left = nonterminals[rule->name];
        if (g.size() == 0) {
            g << (tgt::rule(tgt::nonterminal("$implicit_root")) << rule_left);
        }

        for (const auto& choise: rule->choises->choises) {
            make_target_rule(
                actions,
                g,
                rule_left,
                choise,
                terminal_types,
                nonterminal_types,
                terminals,
                nonterminals,
                pending);
        }
    }

    for (const auto& p: pending) {
        tgt::nonterminal name(p.extended_name);
        nonterminals[p.extended_name] = name;
        nonterminal_types[p.extended_name] =
            Type{p.source_name, p.extension};

        if (p.extension == Extension::Question) {
            tgt::rule list0(name);
            tgt::rule list1(name); list1 << p.element;
            g << list0;
            g << list1;
            actions[list0] = SemanticAction { "opt_nothing", true };
            actions[list1] = SemanticAction { "opt_just", true };
        } else if (p.extension == Extension::Slash) {
            assert(!p.skip.is_epsilon());
            tgt::rule list0(name); list0 << p.element;
            tgt::rule list1(name); list1 << name << p.skip << p.element;
            g << list0;
            g << list1;
            actions[list0] = SemanticAction { "seq_head", true };
            actions[list1] = SemanticAction { "seq_trail2", true };
            
        } else {
            tgt::rule list0(name);
            if (p.extension == Extension::Plus) {
                list0 << p.element;
            }
            tgt::rule list1(name); list1 << name << p.element;
            g << list0;
            g << list1;
            actions[list0] = SemanticAction { "seq_head", true };
            actions[list1] = SemanticAction { "seq_trail", true };
        }
    }

    zw::gr::make_lalr_table(
        table,
        g,
        error_token,
        sr_conflict_reporter(),
        rr_conflict_reporter());
}