yacc

2009-02-05 11 views
19

में लिस्प व्याकरण मैं एक लिस्प व्याकरण बनाने की कोशिश कर रहा हूं। आसान, सही? जाहिरा तौर पर नहीं।yacc

मैं के रूप में पास के रूप में मैं बता सकता हूँ इन इनपुट प्रस्तुत करते हैं और त्रुटियों का सामना करना ...

(1 1) 
23 23 23 
ui ui 

यह व्याकरण है ...

%% 
sexpr: atom     {printf("matched sexpr\n");} 
    | list 
    ; 
list: '(' members ')'  {printf("matched list\n");} 
    | '('')'    {printf("matched empty list\n");} 
    ; 
members: sexpr    {printf("members 1\n");} 
    | sexpr members   {printf("members 2\n");} 
    ; 
atom: ID     {printf("ID\n");} 
    | NUM     {printf("NUM\n");} 
    | STR     {printf("STR\n");} 
    ; 
%% 

, मैं एक गैर टर्मिनल परिभाषित की जरूरत है एक कार्यक्रम के रूप में, जिस पर पूरा पार्स पेड़ लटका सकता है। लेकिन मैंने कोशिश की और यह काम नहीं कर रहा था। -

संपादित करें यह मेरी "शीर्ष टर्मिनल" दृष्टिकोण था:

program: slist; 

slist: slist sexpr | sexpr; 

लेकिन यह इस तरह के रूप समस्याओं अनुमति देता है:

(1 1 

EDIT2: FLEX कोड है ...

%{ 
    #include <stdio.h> 
    #include "a.yacc.tab.h" 
    int linenumber; 
    extern int yylval; 
%} 
%% 
\n       { linenumber++; } 
[0-9]+      { yylval = atoi(yytext); return NUM; } 
\"[^\"\n]*\"    { return STR; } 
[a-zA-Z][a-zA-Z0-9]*  { return ID; } 
. 
%% 

से अधिक मिलान का एक उदाहरण ...

(1 1 1) 
NUM 
matched sexpr 
NUM 
matched sexpr 
NUM 
matched sexpr 
(1 1 
NUM 
matched sexpr 
NUM 
matched sexpr 

यहां क्या त्रुटि है?

संपादित करें: त्रुटि lexer में थी।

+0

क्या अपने उत्पादन जब यह पार्स करता है (1 1 कैसा दिखता है मैं कैसे इसके बारे में एक बात करने के लिए हो जाता है नहीं देख सकते हैं? बंद होने की उम्मीद नहीं है)। – Bearddo

+1

क्या आप अपनी लेक्स/फ्लेक्स फ़ाइल भी पोस्ट कर सकते हैं? शायद एक त्रुटि है। साथ ही, आपको वर्णों का उपयोग नहीं करना चाहिए ('व्याकरण में यदि आप लेक्सर का उपयोग करते हैं, तो मुझे सच में यकीन नहीं है कि ये कैसे साथ आते हैं। – jpalecek

+0

क्या अजीब बात यह है कि वैध सूची (1 1 1) भी नहीं आती है एक सूची के लिए एक मैच। मैं दो चीजों की कोशिश करता हूं, पहले सदस्यों को रिकर्सिव छोड़ देता है: सदस्य: सदस्य sexpr | sexpr; दूसरा, sexpr में सूची का क्रम स्वैप करें: सूची | परमाणु; देखें कि यह काम करता है। – Bearddo

उत्तर

11

त्रुटि वास्तव में लेक्सर में है। आपके कोष्ठक आखिरी "।" के रूप में समाप्त होते हैं। लेक्सर में, और पार्सर में कोष्ठक के रूप में दिखाई नहीं देते हैं।

नियम की तरह

\)  { return RPAREN; } 
\( { return LPAREN; } 
lexer को

और पार्सर में क्रमशः LPAREN और RPAREN करने के सभी आवृत्तियां '(', ')' को बदलने के जोड़ें। (साथ ही, आपको # टोकन और रेफर करें जहां आप अपनी टोकन सूची को परिभाषित करते हैं)

नोट: मुझे वाक्यविन्यास के बारे में निश्चित नहीं है, बैकस्लैश गलत हो सकता है।

4

आपको लगता है कि आप एक गैर टर्मिनल परिभाषित करने की जरूरत में सही हैं। यह sexpr के एक सेट के रूप में परिभाषित किया जाएगा। मुझे इसके लिए वाईएसीसी वाक्यविन्यास का यकीन नहीं है। मैं पार्सर जनरेटर के लिए ANTLR को आंशिक हूँ और वाक्य रचना होगा:

program: sexpr* 

0 या अधिक sexpr का संकेत है।

YACC वाक्य रचना के साथ अद्यतन:

program : /* empty */ 
     | program sexpr 
     ; 
नहीं YACC में

, लेकिन वैसे भी उपयोगी हो सकता है, यहाँ ANTLR v3 में एक पूर्ण व्याकरण कि मामलों आप वर्णित (lexer में शामिल नहीं स्ट्रिंग्स के लिए काम करता है, क्योंकि यह महत्वपूर्ण नहीं है इस उदाहरण के लिए, यह भी सी # कंसोल उत्पादन का उपयोग करता है, क्योंकि जो मैं इसके साथ परीक्षण किया है कि):

program: (sexpr)*; 

sexpr: list 
    | atom   {Console.WriteLine("matched sexpr");} 
    ; 

list:  
    '('')'    {Console.WriteLine("matched empty list");} 
    | '(' members ')' {Console.WriteLine("matched list");} 

    ; 

members: (sexpr)+  {Console.WriteLine("members 1");}; 

atom: Id    {Console.WriteLine("ID");} 
    | Num    {Console.WriteLine("NUM");} 
    ; 


Num: ('0' .. '9')+; 
Id: ('a' .. 'z' | 'A' .. 'Z')+; 
Whitespace : (' ' | '\r' '\n' | '\n' | '\t') {Skip();}; 

यह ठीक से काम नहीं करेगा के रूप में YACC में है क्योंकि YACC उत्पन्न करता है और LALR पार्सर जबकि ANTLR एक संशोधित पुनरावर्ती वंश है। यदि आप उस तरह से जाना चाहते हैं तो एएनटीएलआर के लिए सी/सी ++ आउटपुट लक्ष्य है।

+0

मेरे शीर्ष-स्तरीय टर्मिनल ओवरमैचिंग के बारे में जानकारी के साथ अपडेट किया गया। –

1

यह एक लंबे समय के बाद से मैं YACC के साथ काम किया गया है, लेकिन आप एक उच्च-स्तरीय गैर टर्मिनल की आवश्यकता है। क्या आप "कोशिश की" और "यह काम नहीं कर रहा" के बारे में अधिक विशिष्ट हो सकता है? या, उस मामले के लिए, त्रुटियां क्या हैं?

मैं भी संदेह होता है कि YACC इस तरह के एक वाक्य रचना की रोशनी भाषा के लिए overkill हो सकता है। कुछ आसान (रिकर्सिव वंश की तरह) बेहतर काम कर सकता है।

+0

अपडेट किया गया। इसके अलावा, मैंने पहले फ्लेक्स/बाइसन टूल का उपयोग किया है, इसलिए यह मेरी जिंदगी को आसान बनाता है। –

+0

मैं निश्चित रूप से लिसप के लिए रिकर्सिव डेसेंट पार्सर से सहमत हूं - या यहां तक ​​कि एक पुश-डाउन automaton – Eclipse

+0

ठीक है, मैं स्टंप हो गया हूं, इसे असंतुलित कोष्ठक स्वीकार नहीं करना चाहिए। मुझे लगता है कि आप लेक्स/फ्लेक्स का उपयोग कर रहे हैं; लेक्स/फ्लेक्स आईडी कैसे परिभाषित करता है? आपने मेरे लिए क्या अच्छा लगा है, इसलिए मैं आप जो कुछ कर रहा हूं उससे अधिक देखना चाहता हूं। –

11

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

यदि लक्ष्य lisp के उप-समूह को पार्स करना है, तो प्रोग्राम टेक्स्ट sexprs का अनुक्रम है।

+3

दरअसल, यह लिस्प के संस्करण पर निर्भर करता है। यदि आप सामान्य लिस्प को लक्षित नहीं कर रहे हैं, या आप बूटस्ट्रैप करने की कोशिश कर रहे हैं, तो एक सीएफजी शुरू करने के लिए एक अच्छी जगह हो सकती है। –

2

क्या आपको वाकई एक yacc/bison पार्सर की आवश्यकता है? ए "लिस्प सिंटैक्स का सबसेट पढ़ता है" पाठक सी में लागू करना मुश्किल नहीं है (read_sexpr फ़ंक्शन के साथ शुरू करें, जब आप '(' देखते हैं, तो एक read_list पर प्रेषित करें, जो बदले में ') 'देखा जाता है; अन्यथा, एक read_atom को कॉल करें जो परमाणु एकत्र करता है और इसे तब लौटाता है जब यह अब परमाणु-घटक वर्ण नहीं पढ़ सकता)।

हालांकि, अगर आप आर्बिटरी कॉमन लिस्प को पढ़ने में सक्षम होना चाहते हैं, तो आपको एक सामान्य लिस्प को लागू करने के लिए (सबसे खराब) की आवश्यकता होगी, क्योंकि सीएल पाठक रन-टाइम को संशोधित कर सकता है (और यहां तक ​​कि विभिन्न पढ़ने- प्रोग्राम नियंत्रण के तहत तालिकाओं का समय; काफी आसान जब आप किसी अन्य भाषा या लिस्प की बोली में लिखे गए कोड को लोड करना चाहते हैं)।

+0

मैं आम लिस्प के लिए शूटिंग नहीं कर रहा हूं। मेरी इच्छा यह है कि आखिर में मैं इसे एक एम्बेडेड डिवाइस पर लोड कर सकता हूं और फ्लाई पर नियंत्रण कार्यों को लिख/लिख सकता/लिख सकता हूं। मैं फ्लेक्स/बाइसन का उपयोग कर रहा हूं क्योंकि मुझे पता है कि उनका उपयोग कैसे किया जाए। ऐसा नहीं है क्योंकि वे सबसे अच्छा विकल्प हैं, प्रति से। –

1

मैं सिर्फ यह कोशिश की, मेरी "याक तुतलाना व्याकरण" ठीक काम करता है:

%start exprs 

exprs: 
    | exprs expr 
    /// if you prefer right recursion : 
    /// | expr exprs 
    ; 

list: 
    '(' exprs ')' 
    ; 

expr: 
    atom 
    | list 
    ; 

atom: 
    IDENTIFIER 
    | CONSTANT 
    | NIL 
    | '+' 
    | '-' 
    | '*' 
    | '^' 
    | '/' 
    ; 
संबंधित मुद्दे