有時候,當我想在合金使用遞歸,我發現我可以傳遞閉包,或序列度日。與傳遞閉包(可達性和生產率非終端)更換遞歸
例如,在上下文無關文法的模型:
abstract sig Symbol {}
sig NT, T extends Symbol {}
// A grammar is a tuple(V, Sigma, Rules, Start)
one sig Grammar {
V : set NT,
Sigma : set T,
Rules : set Prod,
Start : one V
}
// A production rule has a left-hand side
// and a right-hand side
sig Prod {
lhs : NT,
rhs : seq Symbol
}
fact tidy_world {
// Don't fill the model with irrelevancies
Prod in Grammar.Rules
Symbol in (Grammar.V + Grammar.Sigma)
}
可達非終端的一個可能的定義是「開始符號,以及任何非末端出現在右手側一個可達符號的規則。「一個簡單的翻譯將是
// A non-terminal 'refers' to non-terminals
// in the right-hand sides of its rules
pred refers[n1, n2 : NT] {
let r = (Grammar.Rules & lhs.n1) |
n2 in r.rhs.elems
}
pred reachable[n : NT] {
n in Grammar.Start
or some n2 : NT
| (reachable[n2] and refers[n2,n])
}
可以預見,這打擊了堆棧。但是,如果我們簡單地採取Grammar.Start的傳遞閉包下refers
關係(或者,嚴格地說,從refers
謂詞形成的關係),我們可以定義可訪問性:
// A non-terminal is 'reachable' if it's the
// start symbol or if it is referred to by
// (rules for) a reachable symbol.
pred Reachable[n : NT] {
n in Grammar.Start.*(
{n1, n2 : NT | refers[n1,n2]}
)
}
pred some_unreachable {
some n : (NT - Grammar.Start)
| not Reachable[n]
}
run some_unreachable for 4
原則,生產性的定義符號同樣是遞歸的:符號是有生產力的,如果它是終端符號,或者它至少有一個規則,右邊的每個符號都是有生產力的。寫這個頭腦簡單的辦法就是
pred productive[s : Symbol] {
s in T
or some p : (lhs.s) |
all r : (p.rhs.elems) | productive[r]
}
像可達性的簡單定義,這吹堆棧。但是我還沒有找到可以在符號上定義的關係,通過傳遞閉包,我可以得到我想要的結果。我發現了傳遞閉包不能代替遞歸的情況嗎?還是我沒有足夠努力去找到正確的關係?
有一個明顯的,如果費力,黑客:
pred p0[s : Symbol] { s in T }
pred p1[s : Symbol] { p0[s]
or some p : (lhs.s)
| all e : p.rhs.elems
| p0[e]}
pred p2[s : Symbol] { p1[s]
or some p : (lhs.s)
| all e : p.rhs.elems
| p1[e]}
pred p3[s : Symbol] { p2[s]
or some p : (lhs.s)
| all e : p.rhs.elems
| p2[e]}
... etc ...
pred productive[n : NT] {
p5[n]
}
該工程確定,只要一不忘記補充足夠的謂詞來處理非終端的引用可能的最長鏈,如果提高了範圍。
具體來說,我似乎有幾個問題;回答任何人都會受到歡迎:
1有沒有辦法來定義集生產合金非終端而不訴諸P0,P1,P2,...破解?
2如果一個人不得不求助於黑客,有沒有更好的方式來界定呢?
3作爲理論問題:是否有可能以表徵一組可使用的傳遞閉包來定義遞歸謂詞,或原子的序列,而不是遞歸?