2015-07-23 10 views
8

मेरे पास * .css (कैस्केडिंग स्टाइल शीट्स) प्रारूप में एक दस्तावेज़ है, लेकिन इसमें इसके अपने कीवर्ड हैं। असल में यह एक व्यक्तिगत सीएसएस है (मैं इसे * .pss कहते हैं), अपने टैग और गुणों के साथ। यहाँ मैं एक अंश है:मैं अपने क्यूटी एप्लिकेशन में (!) फ़ाइल जैसे सीएसएस को कैसे पार्स कर सकता हूं?

/* CSS like style sheet file *.pss */ 

@include "otherStyleSheet.pss"; 

/* comment */ 
[propertyID="1230000"] { 
    fillColor : #f3f1ed; 
    minSize : 5; 
    lineWidth : 3; 
} 

/* sphere */ 
[propertyID="124???|123000"] { 
    lineType : dotted; 
} 

/* square */ 
[propertyID="125???"] { 
    lineType : thinline;  
} 

/* ring */ 
[propertyID="133???"] { 
    lineType : thickline; 
    [hasInnerRing=true] { 
    innerLineType : thinline; 
    } 
} 

मैं बहुत आसानी से यह पार्स करने के लिए चाहते हैं, वहाँ पहले से ही क्यूटी से कुछ तैयार करने के लिए उपयोग है? सबसे आसान तरीका क्या होगा?

* .css के अपने कीवर्ड हैं, इसलिए मैं सीएसएस पार्सर्स में पूर्णांक नहीं हूं।

* .pss को पार्स करने के बाद मेरा और इरादा Model संरचना में अपनी गुणों को संग्रहीत करना है।

+0

मुझे उपलब्ध कुछ भी पता नहीं है। क्या वह बाहर जंगली सीएसएस या सीएसएस पर नियंत्रण रखेगा? –

+0

@ फ्रैंकऑस्टरफेल्ड क्षमा करें, मुझे जंगली अंतर में अंतर नहीं है और इसका नियंत्रण है? मैंने अपना प्रश्न संपादित किया .. Thnx –

+0

फ्रैंक का क्या अर्थ है: क्या सीएसएस आपके एप्लिकेशन का एक हिस्सा है, ताकि आप इसे संपादित कर सकें और इसे प्रबंधित कर सकें, या यह इंटरनेट पर संभावित रूप से दुर्भावनापूर्ण स्रोतों से आता है? याद रखें कि अगर आपके सीएसएस पार्सर में बग हैं, तो दुर्भावनापूर्ण सीएसएस उनका फायदा उठा सकता है और आपका आवेदन ले सकता है। आधुनिक सी ++ (या सी) कोड से कम, इस तरह की बग अपवाद से अधिक मानक हैं। क्यूटी का अपना पार्सर दुर्भावनापूर्ण सीएसएस के खिलाफ लचीला होने के लिए डिज़ाइन नहीं किया गया है - इसे कभी भी इंटरनेट से यादृच्छिक इनपुट स्वीकार करने के लिए डिज़ाइन नहीं किया गया था। इसमें बहुत सारे सुरक्षा छेद हैं, मुझे यकीन है। –

उत्तर

1

मैं दो संभावनाएं पता:

  1. boost::spirit और here आप
  2. मैं अपनी खुद की recursive descent parser

कारण लिखने के लिए सिफारिश करेंगे आत्मा पार्सर ढांचे को बढ़ावा देने के लिए :: एक अच्छा परिचय प्राप्त कर सकते हैं इस तथ्य के लिए, कि आपका वैयक्तिकृत * .ps एक सीएसएस (सरल ब्रैकेटिंग इत्यादि) के रूप में जटिल नहीं है, मैं अनुशंसा करता हूं 2.

+0

मैंने पाया कि सरल रिकर्सवे वंश पार्सर उदाहरण, काफी आशाजनक दिखते हैं। बढ़ावा :: भावना उस पर विकसित होने लगती है। Thnx। –

8

क्यूटी के भीतर कुछ भी सार्वजनिक नहीं है। आप निश्चित रूप से क्यूटी के निजी सीएसएस पार्सर का उपयोग करने के लिए स्वतंत्र हैं - आप इसे कॉपी कर सकते हैं और अपनी आवश्यकताओं के अनुरूप संशोधित कर सकते हैं।

देखें, qtbase/src/gui/text में।

अच्छी खबर यह है कि उदाहरण के लिए आपने ऊपर दिखाया है, संशोधन बहुत मामूली होगा। क्यूटी का सीएसएस पार्सर पहले से ही @import का समर्थन करता है, इसलिए हमारे पास केवल nested selector syntax है। उस वाक्यविन्यास के बिना, आप QCss::Parser का उपयोग कर सकते हैं। पार्सर को एक लचीली फैशन में लिखा गया था, जहां आपको औपचारिक सीएसएस कीवर्ड के बारे में चिंता करने की आवश्यकता नहीं है: यह आपको अभी भी सभी घोषणाओं तक पहुंचने देगा, भले ही वे औपचारिक सीएसएस दृष्टिकोण से समझें या नहीं।

int main() { 
    QCss::Parser parser(pss); 
    QCss::StyleSheet styleSheet; 
    if (!parser.parse(&styleSheet)) 
     return 1; 
    for (auto rule : styleSheet.styleRules) { 
     qDebug() << "** Rule **"; 
     for (auto sel : rule.selectors) { 
     for (auto bSel : sel.basicSelectors) 
      qDebug() << bSel; 
     } 
     for (auto decl : rule.declarations) 
     qDebug() << decl; 
    } 
} 

उत्पादन हम क्या उम्मीद थी है:

पार्स पेड़ पुनरावृत्ति के रूप में यह हो जाता है के रूप में सरल है

** Rule ** 
BasicSelector "propertyID"="1230000" 
Declaration "fillColor" = '#f3f1ed' % QColor(ARGB 1, 0.952941, 0.945098, 0.929412) 
Declaration "minSize" = '5' % 5 
Declaration "lineWidth" = '3' 
** Rule ** 
BasicSelector "propertyID"="124???|123000" 
Declaration "lineType" = 'dotted' 
** Rule ** 
BasicSelector "propertyID"="125???" 
Declaration "lineType" = 'thinline' 
** Rule ** 
BasicSelector "propertyID"="133???" 
Declaration "lineType" = 'thickline' 

हम QCss कक्षाओं के लिए डिबग धारा ऑपरेटरों को लागू करना अपने आप को :

QDebug operator<<(QDebug dbg, const QCss::AttributeSelector & sel) { 
    QDebugStateSaver saver(dbg); 
    dbg.noquote().nospace() << "\"" << sel.name << "\""; 
    switch (sel.valueMatchCriterium) { 
    case QCss::AttributeSelector::MatchEqual: 
     dbg << "="; break; 
    case QCss::AttributeSelector::MatchContains: 
     dbg << "~="; break; 
    case QCss::AttributeSelector::MatchBeginsWith: 
     dbg << "^="; break; 
    case QCss::AttributeSelector::NoMatch: 
     break; 
    } 
    if (sel.valueMatchCriterium != QCss::AttributeSelector::NoMatch && !sel.value.isEmpty()) 
     dbg << "\"" << sel.value << "\""; 
    return dbg; 
} 

QDebug operator<<(QDebug dbg, const QCss::BasicSelector & sel) { 
    QDebugStateSaver saver(dbg); 
    dbg.noquote().nospace() << "BasicSelector"; 
    if (!sel.elementName.isEmpty()) 
     dbg << " #" << sel.elementName; 
    for (auto & id : sel.ids) 
     dbg << " id:" << id; 
    for (auto & aSel : sel.attributeSelectors) 
     dbg << " " << aSel; 
    return dbg; 
} 

घोषणा को पार करते समय, QCss::parser पहले से ही हमारे लिए कुछ मानक मानों का व्याख्या करता है, उदा। रंग, पूर्णांकों, आदि

QDebug operator<<(QDebug dbg, const QCss::Declaration & decl) { 
    QDebugStateSaver saver(dbg); 
    dbg.noquote().nospace() << "Declaration"; 
    dbg << " \"" << decl.d->property << "\" = "; 
    bool first = true; 
    for (auto value : decl.d->values) { 
     if (!first) dbg << ", "; 
     dbg << "\'" << value.toString() << "\'"; 
     first = false; 
    } 
    if (decl.d->property == "fillColor") 
     dbg << " % " << decl.colorValue(); 
    else if (decl.d->property == "minSize") { 
     int i; 
     if (decl.intValue(&i)) dbg << " % " << i; 
    } 
    return dbg; 
} 

अंत में, बॉयलरप्लेट और स्टाइलशीट पार्स किया जा सकता: नेस्टेड चयनकर्ताओं के लिए

// https://github.com/KubaO/stackoverflown/tree/master/questions/css-like-parser-31583622 
#include <QtGui> 
#include <private/qcssparser_p.h> 

const char pss[] = 
    "/* @include \"otherStyleSheet.pss\"; */ \ 
    [propertyID=\"1230000\"] { \ 
    fillColor : #f3f1ed; \ 
    minSize : 5; \ 
    lineWidth : 3; \ 
    } \ 
    \ 
    /* sphere */ \ 
    [propertyID=\"124???|123000\"] { \ 
    lineType : dotted; \ 
    } \ 
    \ 
    /* square */ \ 
    [propertyID=\"125???\"] { \ 
    lineType : thinline; \ 
    } \ 
    \ 
    /* ring */ \ 
    [propertyID=\"133???\"] { \ 
    lineType : thickline; \ 
    /*[hasInnerRing=true] { \ 
     innerLineType : thinline; \ 
    }*/ \ 
    }"; 

सहायता/नियम पार्सर स्रोत को संशोधित करके लागू किया जा सकता। Parser::parseRuleset रिकर्सिव बनाने के लिए आवश्यक परिवर्तन बहुत मामूली है। मैं इसे पाठक के लिए अभ्यास के रूप में छोड़ दूंगा :)

सब कुछ, मुझे लगता है कि मौजूदा पार्सर का पुन: उपयोग करना आपके खुद को रोल करने से कहीं अधिक आसान है, खासकर जब आपके उपयोगकर्ता अनिवार्य रूप से आपको अधिक समर्थन देना चाहते हैं और सीएसएस स्पेक के अधिक।

+0

https://github.com/qtproject/qtbase/blob/dev/src/gui/text/qcssparser.cpp में कोड की 2800 से अधिक पंक्तियां हैं। –

+0

@ राल्फविकम और उसके साथ क्या गलत है? मेरा मतलब है - यह एक ठोस वाक्यविन्यास पेड़ के साथ एक पूर्ण सीएसएस लेजर/पार्सर है। आपको सभी 2800 लाइनों को संशोधित नहीं करना है, आपको जिस बदलाव की आवश्यकता है उसे पूरा करें और इसे पूरी तरह से उपयोग करें। इसे स्वयं लागू करके, आप लगभग उसी कोड के साथ समाप्त हो जाएंगे जिसे व्यापक रूप से परीक्षण नहीं किया गया है। क्यूटी से प्राप्त लाभ यह है कि कृपया आपका पूरा कोडबेस आपके उपयोग के लिए है। यह बहुत अच्छी बात है, एक बुरी बात नहीं है :) –

+0

मुझे सभी आवश्यक फाइलों पर एक नज़र डाली गई: https://github.com/qtproject/qtbase/blob/dev/src/gui/text/ qcssparser_p.h, https://github.com/qtproject/qtbase/blob/dev/src/gui/text/qcssparser.cpp और https://github.com/qtproject/qtbase/blob/dev/src/gui/ पाठ/qcssscanner.cpp। मुझे यह समझने के बिना कोड की कुल 4000 लाइनों को लिखने के लिए और अधिक आरामदायक है कि वहां क्या हो रहा है। मैं नहीं कहता, कि पार्सर खराब है। यह मेरे लिए बहुत जटिल था। –

1

ठीक है, मुझे लगता है कि आप ऑब्जेक्ट पार्सर लिखने के व्यवसाय में नहीं रहना चाहते हैं, तो आप बस JSON, या YAML, या जैसा ही पुनर्निर्मित करेंगे। तो आपकी सबसे अच्छी शर्त है कि अपना स्वरूपण किसी ज्ञात कॉन्फ़िगरेशन या ऑब्जेक्ट नोटेशन भाषा के अनुरूप हो और उसके बाद आप जिस भाषा का उपयोग कर रहे हैं उसके लिए कुछ लाइब्रेरी के साथ इसे पार्स करें।बहुत मामूली संशोधन के साथ, प्रारूप आप ऊपर का वर्णन HOCON, जो JSON का एक बहुत ही अच्छा सुपरसेट है, और भी बहुत करीब वाक्यविन्यास है हो सकता है कि तुम क्या प्रयोग कर रहे हैं:

https://github.com/typesafehub/config/blob/master/HOCON.md

फिर आप एक साथ यह पार्स सकता है होकॉन पार्सिंग लाइब्रेरी, और वॉयला, आपके पास इन-मेमोरी ऑब्जेक्ट्स होंगी जिन्हें आप किसी भी तरह से मॉडल या स्टोर कर सकते हैं। मेरा मानना ​​है कि क्यूटी सी ++ आधारित है? सी के लिए एक हॉकन लाइब्रेरी है, मुझे सी ++ के बारे में पता नहीं है, और मुझे लगता है कि आपको किसी अन्य भाषा से होकॉन पार्सिंग को लपेटने के लिए एक क्यूटी प्लग-इन लिखना होगा। https://github.com/reworkcss/css

जो तुम कांटा और अपनी आवश्यकताओं के संशोधित करने की आवश्यकता हो सकता है:

अन्य विकल्प इस तरह का CSS-> वस्तु पार्सर उपयोग करने के लिए है। किसी भी तरह से, मैं अनुमान लगा रहा हूं कि एक क्यूटी ऐप में एकीकृत करने के लिए आपको एक प्लग-इन की आवश्यकता होगी जो कमांड लाइन प्रक्रिया या अन्य कोड मॉड्यूल में कुछ कॉल-आउट को संभालती है।

+0

मैं उस फ़ाइल प्रारूप को अलग-अलग करता हूं। लेकिन चूंकि हमें यह प्रारूप किसी अन्य विभाग से मिला है, इसलिए मैं इसे बदलने के लिए नहीं जा रहा हूं (और मैं सक्षम नहीं हूं)। –

संबंधित मुद्दे

 संबंधित मुद्दे