2017-03-29 12 views
5

मैं पार्स और भाव का मूल्यांकन करने के लिए फ़ाइल से इनपुट के रूप में मुझे दिया कोशिश कर रहा हूँ,, फार्म की: (वास्तव में मैं भी "multibit उपयोग की अनुमतिपायथन के pyparsing: लागू करने व्याकरण पार्स करने के लिए तार्किक और अभिव्यक्ति

var[3] = 0 and var[2] = 1 
var[0] = 1 and var[2] = 0 and var[3] = 1 
... 

"(यानी var[X:Y]) लेकिन अब इसे अनदेखा करें ...)
जहां var एक पूर्णांक है, और [] बिट पहुंच इंगित करता है।
उदाहरण के लिए, var = 0x9 के लिए, ऊपर की पहली अभिव्यक्ति का मूल्यांकन False पर किया जाना चाहिए, और दूसरे को 0x9 = b1001 के बाद True पर मूल्यांकन किया जाना चाहिए।
and और = एकमात्र द्विआधारी ऑपरेटर हैं जिन्हें मैं अनुमति देता हूं, और = ऑपरेटर के लिए, बाएं ऑपरेंड हमेशा var[X] होता है और दायां ऑपरेंड हमेशा एक संख्या होती है।
मैंने थोड़ा सा देखने की कोशिश की और पाया कि यह पाइथन के pyparsing के साथ हासिल किया जा सकता है, लेकिन मैं इसे लागू करने की कोशिश में कुछ कठिनाइयों में भाग गया।
यहाँ मैं अब तक this example पर मोटे तौर पर आधारित की कोशिश की है, है (जो कई here दिए गए उदाहरणों में से एक है):

#!/usr/bin/env python 
from pyparsing import Word, alphas, nums, infixNotation, opAssoc 

class BoolAnd(): 
    def __init__(self, pattern): 
     self.args = pattern[0][0::2] 

    def __bool__(self): 
     return all(bool(a) for a in self.args) 

    __nonzero__ = __bool__ 


class BoolEqual(): 
    def __init__(self, pattern): 
     self.bit_offset = int(pattern[0][1]) 
     self.value = int(pattern[0][-1]) 

    def __bool__(self): 
     return True if (0xf >> self.bit_offset) & 0x1 == self.value else False # for now, let's assume var == 0xf 

    __nonzero__ = __bool__ 




variable_name = 'var' 
bit_access  = variable_name + '[' + Word(nums) + ']' 
multibit_access = variable_name + '[' + Word(nums) + ':' + Word(nums) + ']' 
value = Word(nums) 

operand = bit_access | multibit_access | value 

expression = infixNotation(operand, 
    [ 
    ('=', 2, opAssoc.LEFT, BoolEqual), 
    ('AND', 2, opAssoc.LEFT, BoolAnd), 
    ]) 


p = expression.parseString('var[3] = 1 AND var[1] = 0', True) 

print 'SUCCESS' if bool(p) else 'FAIL' 

मैं तीन समस्याओं मैं के साथ मदद की जरूरत है।

    रूप var[X:Y] = Z की multibit पहुँच के लिए
  1. , मैं यह कैसे लागू करते हैं:
    एक। X > Y
    बी। Z < 2^{X - Y + 1}
    मुझे लगता है इस व्याकरण ही द्वारा लागू नहीं की जा सकती है (उदाहरण के लिए, प्रपत्र var[X] = Y की एकल बिट पहुँच के लिए, मैं व्याकरण से लागू कर सकते हैं कि Y हो जाएगा या तो 0 या 1, और इस expression.parseString() कारण होगा Y != 0/1 पर अपवाद के साथ असफल होने के लिए)।
  2. सबसे महत्वपूर्ण बात यह है कि यह हमेशा SUCCESS क्यों प्रिंट करता है? मैं क्या गलत कर रहा हूं?
    इनपुट var[3] = 1 AND var[1] = 0 के लिए यह (, तुम मेरे उदाहरण है कि मैं var hardcoded 0xf होने के लिए देख सकते हैं var[3] = 1True है, लेकिन var[1] = 0False है) होना चाहिए मुद्रित किया जा FAIL
  3. कौन मुझे मेरी तीसरी समस्या के लिए लाता है: varBoolEqual के एक वर्ग के सदस्य नहीं है और न ही यह वैश्विक है ... वहाँ एक रास्ता किसी भी तरह BoolEqual के __init__ समारोह को भेजने के लिए है?
+0

# 2 का आसान उत्तर: पी एक खाली खाली पारस्परिक है, इसलिए सामग्री के बावजूद यह हमेशा सत्य का मूल्यांकन करेगा। 'प्रिंट' (सफलता 'अगर बूल (पी [0]) और' FAIL ')' – PaulMcG

उत्तर

3

समस्या हल करने से पहले, मैं आपके व्याकरण में कुछ मामूली परिवर्तन सुझाता हूं, मुख्य रूप से परिणाम नामों को शामिल करता हूं।इन नामों को जोड़ने से आपका परिणाम कोड बहुत साफ और मजबूत हो जाएगा। मैं भी भाव है कि हाल ही में pyparsing संस्करणों में जोड़ा गया था के कुछ का उपयोग कर रहा pyparsing_common नाम स्थान कक्षा में:

from pyparsing import pyparsing_common 

variable_name = pyparsing_common.identifier.copy() 
integer = pyparsing_common.integer.copy() 
bit_access  = variable_name('name') + '[' + integer('bit') + ']' 
multibit_access = variable_name('name') + '[' + integer('start_bit') + ':' + integer('end_bit') + ']' 

भाग 1 क: "[: वाई X] वर"

इस में मान्य मान लागू पार्स क्रियाओं और शर्तों का उपयोग करके काम का सबसे अच्छा काम किया जाता है। पार्स क्रियाएं पार्स-टाइम कॉलबैक हैं जिन्हें आप अपने पाइपर्सिंग एक्सप्रेशन से जोड़ सकते हैं ताकि परिणामों को संशोधित, बढ़ाने, फ़िल्टर करने, या सत्यापन नियम विफल होने पर अपवाद बढ़ाया जा सके।

expr.addParseAction(parse_action_fn) 

और parse_action_fn निम्नलिखित हस्ताक्षर से कोई भी कर सकते हैं:: ये विधि का उपयोग कर से जुड़े होते हैं

def parse_action_fn(parse_string, parse_location, matched_tokens): 
def parse_action_fn(parse_location, matched_tokens): 
def parse_action_fn(matched_tokens): 
def parse_action_fn(): 

(https://pythonhosted.org/pyparsing/pyparsing.ParserElement-class.html#addParseActio)n पर अधिक देखें)

पार्स कार्यों कोई नहीं लौट सकते हैं, नए टोकन वापसी , दिए गए टोकन को संशोधित करें, या अपवाद उठाएं।

यदि सभी पार्स एक्शन इनपुट टोकन के आधार पर कुछ शर्त का मूल्यांकन करता है, तो आप इसे एक साधारण फ़ंक्शन के रूप में लिख सकते हैं जो सही या गलत लौटाता है, और गलत होने पर पाइपर्सिंग अपवाद उठाएगी। आपके मामले में, अपने पहले सत्यापन नियम लागू किया जा सकता है:

def validate_multibit(tokens): 
    return tokens.end_bit > tokens.start_bit 
multibit_access.addCondition(validate_multibit, 
          message="start bit must be less than end bit", 
          fatal=True) 

या यहां तक ​​कि सिर्फ एक अजगर लैम्ब्डा समारोह के रूप में:

multibit_access.parseString("var[3:0]") 

:

multibit_access.addCondition(lambda t: t.end_bit > t.start_bit, 
          message="start bit must be less than end bit", 
          fatal=True) 

अब आप के साथ इस कोशिश कर सकते हैं और आपको यह अपवाद मिलेगा:

pyparsing.ParseFatalException: start bit must be less than end bit (at char 0), (line:1, col:1) 

भाग 1 बी: "var [X: Y] = Z"

में मान्य मान लागू करना आपका दूसरा सत्यापन नियम न केवल विभिन्न सीमाओं के साथ ही मूल्य की तुलना में भी मूल्यवान है। इसके लिए एक पूर्ण कार्रवाई की आवश्यकता होगी जो पूर्ण BoolEqual से जुड़ा हुआ है। हम इसे BoolEqual की __init__ विधि में डाल सकते हैं, लेकिन जब भी संभव हो तो मैं स्वतंत्र कार्यों को अलग करना पसंद करता हूं। और चूंकि हम infixNotation स्तर को जोड़कर हमारे सत्यापन को जोड़ देंगे, और infixNotation केवल पार्स क्रियाएं स्वीकार करता है, हमें आपके दूसरे सत्यापन नियम को एक पार्स एक्शन के रूप में लिखना होगा जो अपवाद उठाता है। (हम एक नई सुविधा का भी उपयोग करेंगे जिसे हाल ही में 2.2.0 में पाइपर्सिंग में रिलीज़ किया गया था, जो infixNotation में एक स्तर पर एकाधिक पार्स क्रियाओं को जोड़ रहा था।)

यहाँ मान्यता है कि हम चाहते हैं जाएगा प्रदर्शन करने के लिए है:

  • अगर एक बिट अभिव्यक्ति, मान होना चाहिए 0 या 1
  • अगर multibit अभिव्यक्ति वर [X: Y], मान होना चाहिए < 2 ** (वाई-X + 1)

    def validate_equality_args(tokens): 
        tokens = tokens[0] 
        z = tokens[-1] 
        if 'bit' in tokens: 
         if z not in (0,1): 
          raise ParseFatalException("invalid equality value - must be 0 or 1") 
        else: 
         x = tokens.start_bit 
         y = tokens.end_bit 
         if not z < 2**(y - x + 1): 
          raise ParseFatalException("invalid equality value")

And we attach this parse action to infixNotation using:

expression = infixNotation(operand, 
    [ 
    ('=', 2, opAssoc.LEFT, (validate_equality_args, BoolEqual)), 
    ('AND', 2, opAssoc.LEFT, BoolAnd), 
    ]) 

भाग 3: 0xf के अलावा अन्य वर के नाम और मान सहायक

विभिन्न नामों की वार्स के साथ सौदा करने के लिए, आप BoolEqual करने के लिए एक वर्ग स्तर के dict जोड़ सकते हैं:

class BoolEqual(): 
    var_names = {} 

और इस समय से आगे सेट:

BoolEqual.var_names['var'] = 0xf 

और फिर अपने __bool__ विधि को लागू के रूप में बस:

return (self.var_names[self.var_name] >> self.bit_offset) & 0x1 == self.value

(यह multibit का समर्थन करने के लिए बढ़ाया जा करने की आवश्यकता होगी, लेकिन सामान्य विचार एक ही है।)

+0

सुंदर 'का प्रयास करें। बिल्कुल मुझे क्या चाहिए, धन्यवाद! –

0

कैसे और 0 है 1 की एक सूची के लिए चर बदलने और बूलियन अभिव्यक्ति का मूल्यांकन करने के eval का उपयोग कर (एक छोटे संशोधन के साथ, बदल रहा है == में =) के बारे में:

def parse(lines, v): 
    var = map(int,list(bin(v)[2:])) 
    result = [] 

    for l in lines: 
     l = l.replace('=','==') 
     result.append(eval(l)) 

    return result 

inp = \ 
""" 
var[3] = 0 and var[2] = 1 
var[0] = 1 and var[2] = 0 and var[3] = 1 
""" 

lines = inp.split('\n')[1:-1] 
v = 0x09 

print parse(lines, v) 

आउटपुट:

[False, True] 

ध्यान दें कि यदि आप इनपुट पर भरोसा करते हैं तो आपको केवल eval का उपयोग करना चाहिए।

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