पैटर्न आगंतुक एक डिजाइन पैटर्न है कि आप मनमाने ढंग से संचालन को लागू करने की अनुमति देता है (आगंतुकों के रूप में लागू) पर है पार्स पेड़ (उदाहरण के लिए टाइप-चेकिंग) पार्स पेड़ के नोड्स के कार्यान्वयन को संशोधित किए बिना।
यह नीचे दिए तरीक़े (i स्यूडोकोड उपयोग कर रहा हूँ) में लागू किया जा सकता है:
पहले तुम पेड़ नोड्स कि सभी नोड्स को लागू करना का आधार वर्ग को परिभाषित करने की जरूरत है।
abstract class VisitableNode {
abstract void accept(Visitor v);
}
नोड कक्षाओं को लागू करने वाली एकमात्र विधि स्वीकृति विधि है।
फिर आपको अपने पार्स-पेड़ के विज़िटर नोड के बेस-क्लास को परिभाषित करना चाहिए।
abstract class Visitor {
abstract void visit(Root rootNode);
abstract void visit(Op opNode);
abstract void visit(Number number);
}
ध्यान दें कि आगंतुक का आधार स्तर के केवल अपने पार्स पेड़ के लिए किया जाता है, और हर नोड प्रकार आप अपने पार्स पेड़ में परिभाषित के लिए एक यात्रा विधि होनी चाहिए।
फिर, आप अपने नोड कक्षाएं कार्यान्वयन निम्नलिखित तरीके से VisitableNode वर्ग का विस्तार देना चाहिए:
class Root : VisitableNode {
[...]
void accept(Visitor v) {
v.visit(this);
}
}
class Op : VisitableNode {
[...]
void accept(Visitor v) {
v.visit(this);
}
}
class Number : VisitableNode {
[...]
void accept(Visitor v) {
v.visit(this);
}
}
अब आप अपने पार्स-वृक्ष संरचना है कि परिवर्तन नहीं होना चाहिए, और आप के रूप में कई को लागू करने के लिए स्वतंत्र हैं आगंतुकों (संचालन) जैसा आप चाहें। आदि NumberFloat, NumberInteger, NumberDouble,
:
आदेश प्रकार की जाँच करने के लिए, आप अपने मूल्य के साथ एक साथ संख्या वर्ग के अंदर एक प्रकार की दुकान, या अन्यथा हर प्रकार के समर्थन के लिए एक संख्या वर्ग के लिए होगा
उदाहरण के तौर पर, मान लीजिए कि आपके पास अपनी संख्या वर्ग से मूल्य के स्थिर प्रकार का अनुमान लगाने का एक तरीका है।
मैं यह भी मानूंगा कि आप विधि getChild (int childIndex) विधि से नोड के बच्चों तक पहुंच सकते हैं।
अंत में, मैं एक वर्ग प्रकार का उपयोग करूंगा जो तुच्छ रूप से एक स्थिर प्रकार का प्रतिनिधित्व करता है जिसका आप समर्थन करना चाहते हैं (जैसे फ्लोट, इंटेगर, आदि ...)।
class TypeCheckVisitor : Visitor {
// Field used to save resulting type of a visit
Type resultType;
void visit(Root rootNode)
{
rootNode.getChild(0).accept(this);
}
void visit(Op opNode)
{
opNode.getChild(0).accept(this);
Type type1 = resultType;
opNode.getChild(1).accept(this);
Type type2 = resultType;
// Type check
if(!type1.isCompatible(type2)){
// Produce type error
}
// Saves the return type of this OP (ex. Int + Int would return Int)
resultType = typeTableLookup(opNode.getOperator(), type1, type2);
}
void visit(Number number)
{
// Saves the type of this number as result
resultType = number.getType();
}
}
उसके बाद, आप एक तरह से करने के लिए इसी में एक enum के रूप में शायद प्रकार वर्ग को लागू होगा:
enum Type {
Double,
Float,
Integer;
boolean isCompatible(Type type1, Type type2){
// Lookup some type table to determine types compatibility
}
}
और अंत में आप केवल अपने प्रकार टेबल और ऑपरेटर टेबल लागू करने के लिए की जरूरत है।
संपादित करें: विज़िट रिकर्सन में, वास्तव में उन नोड्स की स्वीकृति विधि का उपयोग करके पुनरावृत्ति करना सही है, जिन पर आप पुनरावृत्ति करना चाहते हैं।
TypeCheckVisitor v = new TypeCheckVisitor();
rootNode.accept(v);
print("Root type is: " + v.resultType);
तुम भी की एक मनमाना नोड टाइप-जाँच कर सकते हैं:
उपयोग के लिए के रूप में, आप प्रकार की जाँच पार्स पेड़ की जड़ नोड पर से प्रदर्शन कर सकते हैं (और साथ ही अभिव्यक्ति के प्रकार का निर्धारण) पार्स पेड़ उसी तरह रूट से अलग है।
गृहकार्य? यदि नहीं - आप क्या करने की कोशिश कर रहे हैं? –
आप इस परियोजना में रुचि रखते हैं, [अभिव्यक्ति इंजन] (https://github.com/gsscoder/exprengine)। सी # में लिखा गया; आगंतुक पैटर्न का प्रयोग करें। – jay
पहले से ही पूछा गया है? http://stackoverflow.com/questions/2525677/how-to-write-the-visitor-pattern-for-abstract-syntax-tree-in-python – jwaliszko