0

我有一个声明性语言(twolc实际上)的源文件,我需要编写许多变体:一个规范版本和许多非规范版本,每个版本都有一个或多个与规范不同的变体。例如,假设规范文件具有三个规则:

Rule A:
    Do something A-ish

Rule B:
    Do something B-ish

Rule C:
    Do something C-ish

A那么,一种变体可能具有与and的规范完全相同的规则C,但对于 具有不同的规则B,我将其称为B-1

Rule A:
    Do something A-ish

Rule B-1:
    Do something B-ish, but with a flourish

Rule C:
    Do something C-ish

想象一下,你对许多不同的规则有许多不同的细微变化,你有我的情况。我担心的问题是代码的可维护性。如果稍后我决定Rule A需要以某种方式重构,那么我将有 50 多个文件需要手动编辑完全相同的规则。

我的想法是为每个规则设置单独的文件,并使用cat: cat A.twolc B.twolc C.twolc > norm.twolccat A.twolc B-1.twolc C.twolc > not-norm.twolc等将它们连接成变体。

是否有任何工具旨在管理此类问题?有没有比我想到的更好的方法?我提出的解决方案是否有我应该注意的弱点?

4

1 回答 1

1

当您添加 makefile 标记时,这里是一个基于 GNU-make(且仅限 Gnu make)的解决方案:

# Edit this
RULES       := A B B-1 C
VARIATIONS  := norm not-norm
norm-rules  := A B C
not-norm-rules  := A B-1 C
# Do not edit below this line

VARIATIONSTWOLC := $(patsubst %,%.twolc,$(VARIATIONS))

all: $(VARIATIONSTWOLC)

define GEN_rules
$(1).twolc: $$(patsubst %,%.twolc,$$($(1)-rules))
    cat $$^ > $$@
endef
$(foreach v,$(VARIATIONS),$(eval $(call GEN_rules,$(v))))

clean:
    rm -f $(VARIATIONSTWOLC)

patsubst很简单。这foreach-eval-call有点棘手。长话短说:它遍历所有变体 ( foreach)。对于每个变体,它通过替换(当前变体) 和来v扩展 ( call) 。然后将每个扩展结果实例化 ( ) 作为正常的 make 规则。示例:对于,展开产生:GEN_rules$(1)$(v)$$$evalv=normGEN_rules

norm.twolc: $(patsubst %,%.twolc,$(norm-rules))
    cat $^ > $@

依次扩展为(逐步):

第1步:

norm.twolc: $(patsubst %,%.twolc,A B C)
    cat $^ > $@

第2步:

norm.twolc: A.twolc B.twolc C.twolc
    cat $^ > $@

第三步:

norm.twolc: A.twolc B.twolc C.twolc
    cat A.twolc B.twolc C.twolc > norm.twolc

执行您想要的操作:如果norm.twolc不存在或如果A.twolc, B.twolc,C.twolc中的任何一个比 更新norm.twolc,则执行配方。

于 2017-06-21T11:15:18.310 回答