2011-02-03 5 views
9

में लिखित गणित वाक्यविन्यास परीक्षक, यदि कोई स्ट्रिंग मान्य गणित अभिव्यक्ति है या नहीं, तो मुझे केवल पाइथन का उपयोग करके जांचना है।पाथथन

सादगी के लिए मान लें कि मुझे केवल + - * / ऑपरेटर (+ - यूनरी के रूप में भी) की आवश्यकता है और संख्याओं और घोंसले वाले कोष्ठक के साथ। मैं पूर्णता के लिए भी सरल परिवर्तनीय नाम जोड़ता हूं।

test("-3 * (2 + 1)") #valid 
test("-3 * ")  #NOT valid 

test("v1 + v2")  #valid 
test("v2 - 2v")  #NOT valid ("2v" not a valid variable name) 

मैंने कोशिश की pyparsing लेकिन उदाहरण सिर्फ कोशिश कर रहा:

तो मैं इस तरह से परीक्षण कर सकते हैं "simple algebraic expression parser, that performs +,-,*,/ and ^ arithmetic operations" मैं अमान्य कोड पारित कर दिया हो और यह भी इसे ठीक करने मैं हमेशा गलत वाक्यविन्यास अपवाद को ऊपर उठाने के बिना पार्स किया जाता हो कोशिश कर

सिर्फ कोशिश:

>>>test('9', 9) 
9 qwerty = 9.0 ['9'] => ['9'] 
>>>test('9 qwerty', 9) 
9 qwerty = 9.0 ['9'] => ['9'] 

दोनों परीक्षण पास ... ओ _O

कोई सलाह?

उत्तर

3

ऐसा इसलिए है क्योंकि पाइपर्सिंग कोड कार्यों की अनुमति देता है। (और वैसे, यह तुम क्या जरूरत है, यानी एक ढेर बना सकते हैं और है कि मूल्यांकन की तुलना में बहुत अधिक है।)

शुरुआत के लिए, आप और pi और ident (और संभवतः कुछ मैं सही याद कर रहा हूँ को दूर कर सकता है अब) कोड से पात्रों को अस्वीकार करने के लिए।

कारण अलग है: PyParsing पार्सर्स डिफ़ॉल्ट रूप से पूरे इनपुट का उपभोग करने की कोशिश नहीं करेंगे। आपको (और इसे निश्चित रूप से आयात करें) expr के अंत में इसे असफल बनाने के लिए जोड़ना होगा यदि यह पूरे इनपुट को पार्स नहीं कर सकता है। उस स्थिति में, pyparsing.ParseException उठाया जाएगा। (स्रोत: http://pyparsing-public.wikispaces.com/FAQs)

आप पार्स का एक सा जानने के लिए परवाह है, तो आप क्या जरूरत है propably किसी भी सभ्य पार्स पुस्तकालय के साथ कम से कम तीस लाइनों में बनाया जा सकता है (मैं LEPL की तरह)।

+0

'pi' से सत्य नहीं है ...' pi' है और 'querty' नहीं है और पहचान केवल ब्रांड्स के बाद आता है ... बेशक अगर मैं वैध वाक्यविन्यास परीक्षक के रूप में काम करने के लिए पाइपर्सिंग प्राप्त कर सकता हूं तो मुझे यह पसंद आएगा । मैं एलईपीएल को भी मौका दूंगा। – neurino

+0

@neuriono: फिर या तो स्रोत कोड भ्रामक है और व्याकरण वास्तव में अलग है, या पाइपर्सिंग टूटा हुआ है (संपादित करें: एक स्पष्टीकरण जिसे मैं सोच सकता हूं, जो श्रेणी में होगा "पाइपर्सिंग टूटा हुआ है": यह उपभोग नहीं करता है पूरी स्ट्रिंग लेकिन इसके अलावा बाहर निकलती है और यह तब तक लौटती है जब शेष इनपुट पार्स करने में विफल रहता है)। – delnan

+0

अच्छी तरह से यह काफी स्पष्ट है, लेकिन यदि आप पार्सर (डीफ़ बीएनएफ()) बनाने वाले कोड के हिस्से को देखते हैं तो यह काफी सरल है और यहां तक ​​कि _exponentiation_ भाग जैसी चीज़ों को भी हटा देना इसे आसान बनाता है, फिर भी मुझे लगता है कि पाइपर्सिंग अच्छा नहीं है वाक्यविन्यास की जांच में। – neurino

1

क्यों इसका मूल्यांकन न करें और वाक्यविन्यास त्रुटि को पकड़ें?

> print validSyntax('a+b-1') # a, b are undefined, so a NameError arises. 
> False 

> print validSyntax('1 + 2') 
> True 

> print validSyntax('1 - 2') 
> True 

> print validSyntax('1/2') 
> True 

> print validSyntax('1 * 2') 
> True 

> print validSyntax('1 +/ 2') 
> False 

> print validSyntax('1 + (2') 
> False 

> print validSyntax('import os') 
> False 

> print validSyntax('print "asd"') 
> False 

> print validSyntax('import os; os.delete("~\test.txt")') 
> False # And the file was not removed 

यह केवल गणितीय क्रियाओं के लिए प्रतिबंधित है तो यह थोड़ा एक कच्चे eval की तुलना में बेहतर काम करना चाहिए:

from math import * 

def validateSyntax(expression): 
    functions = {'__builtins__': None} 
    variables = {'__builtins__': None} 

    functions = {'acos': acos, 
       'asin': asin, 
       'atan': atan, 
       'atan2': atan2, 
       'ceil': ceil, 
       'cos': cos, 
       'cosh': cosh, 
       'degrees': degrees, 
       'exp': exp, 
       'fabs':fabs, 
       'floor': floor, 
       'fmod': fmod, 
       'frexp': frexp, 
       'hypot': hypot, 
       'ldexp': ldexp, 
       'log': log, 
       'log10': log10, 
       'modf': modf, 
       'pow': pow, 
       'radians': radians, 
       'sin': sin, 
       'sinh': sinh, 
       'sqrt': sqrt, 
       'tan': tan, 
       'tanh': tanh} 

    variables = {'e': e, 'pi': pi} 

    try: 
    eval(expression, variables, functions) 
    except (SyntaxError, NameError, ZeroDivisionError): 
    return False 
    else: 
    return True 

यहाँ कुछ नमूने हैं।

+2

यह पहले (अब हटाए गए) उत्तर से बहुत खराब है, जो कि कम से कम जांच की जाती है अगर उत्तर में केवल संख्याएं और ऑपरेटर होते हैं। आपकी नीलामी कोड की अनुमति देता है :( – delnan

+0

मेरा अपडेट देखें। – Blender

+0

'literal_eval' उत्तर नहीं है, क्योंकि आप गणित ऑपरेटरों और माता-पिता को अनुमति देना चाहते हैं। – delnan

1

आप अंकगणितीय अभिव्यक्ति की स्ट्रिंग को टोकन करने के लिए एक सरल पार्सर बनाने का प्रयास कर सकते हैं और फिर पेड़ मान्य होने पर अभिव्यक्ति वृक्ष का निर्माण कर सकते हैं (पत्तियां सभी ऑपरेंड हैं और आंतरिक नोड्स सभी ऑपरेटर हैं) तो आप कह सकते हैं कि अभिव्यक्ति वैध है।

मूल अवधारणा अपने पार्सर बनाने के लिए कुछ सहायक कार्यों को बनाना है।अगर वहाँ
get_expression()
get_next_token()

वैकल्पिक रूप से अगले वर्ण की जाँच करने के लिए यदि आप वर्णों के बीच खाली स्थान के गारंटी ले सकते हैं कोई खाली स्थान के है

def extract() अभिव्यक्ति
def peek() निकालने के लिए समान है, लेकिन इस्तेमाल किया से अगले वर्ण मिल जाएगा आप सभी टोकनिंग करने के लिए split() का उपयोग कर सकते हैं।

तो फिर आप अपने पेड़ का निर्माण और अगर इसकी सही ढंग से

संरचित और अधिक जानकारी के लिए यह प्रयास का मूल्यांकन: http://effbot.org/zone/simple-top-down-parsing.htm

+0

यह सब स्वयं बिल्डिंग पिछले शताब्दी में है ... इन दिनों, आप एक पार्सिंग लाइब्रेरी का उपयोग करते हैं जो सभी ग़लत नौकरशाही का ख्याल रखता है। – delnan

+0

@ डेलनान मैंने इस तथ्य को जोड़ा कि यदि व्हाइटस्पेस है तो आप केवल विभाजन() का उपयोग कर सकते हैं, अगर वहां ऐसी कोई लाइब्रेरी नहीं है जो आपकी आवश्यकताओं को पूरा करती है (कार्यात्मक लेकिन बहुत बड़ी आदि ...) तो क्या? – Jordan

+0

@ योएल: फिर आप भाग्य से बाहर हैं और संभवतः बहुत अधिक मानक हैं। – delnan

1

parseString करने के लिए कॉल करने के लिए जोड़ा जा रहा है parseAll=True एक सत्यापनकर्ता में इस पार्सर परिवर्तित कर देंगे।

+1

ठीक है, थोड़ा देर हो चुकी है ... (चयनित उत्तर पर मेरी आखिरी टिप्पणी देखें), वैसे भी धन्यवाद। – neurino

0

आप एक कस्टम गणित मूल्यांकनकर्ता इंजन पायथन में लिखा संशोधित करने में रुचि रखते हैं इतना है कि यह एक सत्यापनकर्ता बजाय है, तो आप Evaluator 2.0 (अजगर 3.x) और Math_Evaluator (पायथन 2.x) के साथ बाहर शुरू कर सकता है। वे तैयार किए गए समाधान नहीं हैं, लेकिन आप जो कुछ भी कर रहे हैं उसे पूरी तरह से अनुकूलित करने की अनुमति देंगे (उम्मीद है कि) आसानी से पढ़ने के लिए पाइथन कोड का उपयोग कर रहे हैं। ध्यान दें कि "और" & "या" ऑपरेटर के रूप में माना जाता है।