2009-08-22 6 views
9

मैं बीएनएफ सीखने और कुछ जेड 80 एएसएम कोड इकट्ठा करने की कोशिश कर रहा हूं। चूंकि मैं दोनों क्षेत्रों में नया हूं, मेरा सवाल है, क्या मैं सही रास्ते पर भी हूं? मैं जेड 80 एएसएम के प्रारूप को ईबीएनएफ के रूप में लिखने की कोशिश कर रहा हूं ताकि मैं समझ सकूं कि स्रोत से मशीन कोड बनाने के लिए वहां से कहां जाना है। फिलहाल मेरे पास निम्न है:जेड 80 एएसएम बीएनएफ संरचना ... क्या मैं सही रास्ते पर हूं?

Assignment = Identifier, ":" ; 

Instruction = Opcode, [ Operand ], [ Operand ] ; 

Operand = Identifier | Something* ; 

Something* = "(" , Identifier, ")" ; 

Identifier = Alpha, { Numeric | Alpha } ; 

Opcode = Alpha, Alpha ; 

Int = [ "-" ], Numeric, { Numeric } ; 

Alpha = "A" | "B" | "C" | "D" | "E" | "F" | 
     "G" | "H" | "I" | "J" | "K" | "L" | 
     "M" | "N" | "O" | "P" | "Q" | "R" | 
     "S" | "T" | "U" | "V" | "W" | "X" | 
     "Y" | "Z" ; 

Numeric = "0" | "1" | "2" | "3"| "4" | 
      "5" | "6" | "7" | "8" | "9" ; 

यदि मैं गलत हो रहा हूं तो कोई दिशात्मक प्रतिक्रिया उत्कृष्ट होगी।

+0

http://stackoverflow.com/questions/1305091/writing-an-z80-assembler-lexi का डुप्पी एनजी-एएसएम-एंड-बिल्डिंग-ए-पार्स-पेड़-उपयोग-कंपोज़िशन एक हीसर –

+3

@ बटरवर्थ: डुप्लिकेट नहीं। दूसरे प्रश्न को किसी भी पेड़ के आस-पास की जानकारी के साथ करना है जो वह व्याकरण का उपयोग कर बना सकता है। इस सवाल के साथ क्या करना चाहिए कि उसे व्याकरण का उपयोग करना चाहिए, और यदि हां, तो यह कैसा दिखता है। इस सवाल का जवाब दिलचस्प है कि दूसरे के लिए एक पूर्व शर्त है। –

उत्तर

16

पुराने स्कूल अस्सेम्ब्लेर्स आम तौर पर कोडांतरक में हैंड-कोड और विधानसभा स्रोत लाइनों पर कार्रवाई करने के वास्तविक कोडांतरक कोड का उत्पादन किया जाता सहारा पार्स तकनीक थे। जब असेंबलर सिंटैक्स सरल होता है (उदाहरण के लिए हमेशा OPCODE REG, OPERAND) यह काफी अच्छा काम करता है।

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

एक बीएनएफ और एक पार्सर जेनरेटर का उपयोग करना एक आधुनिक असेंबलर बनाने के लिए बहुत ही उचित तरीका है, यहां तक ​​कि जेड 80 जैसे विरासत प्रोसेसर के लिए भी। मैंने मोटोरोला 8 बिट मशीनों जैसे 6800/680 9 के लिए ऐसे असेंबलर बनाए हैं, और मैं आधुनिक x86 के लिए ऐसा करने के लिए तैयार हूं। मुझे लगता है कि आप बिल्कुल सही रास्ते की ओर बढ़ रहे हैं।

********** संपादित करें **************** ओपी ने उदाहरण लेक्सर और पार्सर परिभाषाओं के लिए कहा। मैंने यहां दोनों प्रदान किए हैं।

ये एक 6809 asssembler के लिए वास्तविक विशिष्टताओं के अंश हैं। पूर्ण परिभाषाएं नमूने के आकार 2-3x हैं।

स्पेस डाउन रखने के लिए, मैंने अंधेरे कोने की जटिलता संपादित की है जो इन परिभाषाओं का बिंदु है। एक गारंटी जटिलता से निराश हो सकता है; बिंदु यह है कि इस तरह की परिभाषाओं के साथ, आप भाषा का आकार वर्णन करने की कोशिश कर रहे हैं, प्रक्रिया को संसाधित नहीं करते हैं। यदि आप कोड को इस तरह से कोड में रखते हैं तो आप एक बहुत अधिक जटिलता का भुगतान करेंगे, और यह कम रखरखाव योग्य होगा।

यह भी पता चला है कि इन परिभाषाओं एक उच्च अंत कार्यक्रम विश्लेषण प्रणाली उप के रूप में lexing/पार्स उपकरण है कि के साथ उपयोग किया जाता है कुछ मदद की हो जाएगा, The DMS Software Reengineering Toolkit कहा जाता है। डीएमएस स्वचालित रूप से
पार्सर specfication में व्याकरण नियमों से एएसटी का निर्माण करेगा, जो इसे पार्सिंग टूल को खरीदने के लिए बहुत आसान बनाता है। अंत में, पार्सर विनिर्देश में तथाकथित "सुंदरप्रिंटर" घोषणाएं शामिल हैं, जो डीएमएस को एएसटी से स्रोत टेक्स्ट को पुन: उत्पन्न करने की अनुमति देती है। (व्याकरण का वास्तविक उद्देश्य कोडांतरक निर्देश का प्रतिनिधित्व ASTs का निर्माण, और फिर उन्हें थूक से बाहर एक असली कोडांतरक को खिलाया जा करने के लिए हमें अनुमति देने के लिए गया था!) ​​नोट के

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

ओपी के हितों को देखते हुए, वह समान lexer/पारसर्स किसी भी lexer/पार्सर जेनरेटर उपकरण, जैसे, FLEX/YACC, JavaCC, ANTLR, साथ लागू कर सकते हैं ...

******* *** lexer **************

-- M6809.lex: Lexical Description for M6809 
-- Copyright (C) 1989,1999-2002 Ira D. Baxter 

%% 
#mainmode Label 

#macro digit "[0-9]" 
#macro hexadecimaldigit "<digit>|[a-fA-F]" 

#macro comment_body_character "[\u0009 \u0020-\u007E]" -- does not include NEWLINE 

#macro blank "[\u0000 \ \u0009]" 

#macro hblanks "<blank>+" 

#macro newline "\u000d \u000a? \u000c? | \u000a \u000c?" -- form feed allowed only after newline 

#macro bare_semicolon_comment "\; <comment_body_character>* " 

#macro bare_asterisk_comment "\* <comment_body_character>* " 

...[snip] 

#macro hexadecimal_digit "<digit> | [a-fA-F]" 

#macro binary_digit "[01]" 

#macro squoted_character "\' [\u0021-\u007E]" 

#macro string_character "[\u0009 \u0020-\u007E]" 

%%Label -- (First mode) processes left hand side of line: labels, opcodes, etc. 

#skip "(<blank>*<newline>)+" 
#skip "(<blank>*<newline>)*<blank>+" 
    << (GotoOpcodeField ?) >> 

#precomment "<comment_line><newline>" 

#preskip "(<blank>*<newline>)+" 
#preskip "(<blank>*<newline>)*<blank>+" 
    << (GotoOpcodeField ?) >> 

-- Note that an apparant register name is accepted as a label in this mode 
#token LABEL [STRING] "<identifier>" 
    << (local (;; (= [TokenScan natural] 1) ; process all string characters 
     (= [TokenLength natural] ?:TokenCharacterCount)= 
     (= [TokenString (reference TokenBodyT)] (. ?:TokenCharacters)) 
     (= [Result (reference string)] (. ?:Lexeme:Literal:String:Value)) 
     [ThisCharacterCode natural] 
     (define Ordinala #61) 
     (define Ordinalf #66) 
     (define OrdinalA #41) 
     (define OrdinalF #46) 
    );; 
    (;; (= (@ Result) `') ; start with empty string 
    (while (<= TokenScan TokenLength) 
     (;; (= ThisCharacterCode (coerce natural TokenString:TokenScan)) 
     (+= TokenScan) ; bump past character 
     (ifthen (>= ThisCharacterCode Ordinala) 
      (-= ThisCharacterCode #20) ; fold to upper case 
     )ifthen 
     (= (@ Result) (append (@ Result) (coerce character ThisCharacterCode)))= 

     );; 
    )while 
    );; 
)local 
    (= ?:Lexeme:Literal:String:Format (LiteralFormat:MakeCompactStringLiteralFormat 0)) ; nothing interesting in string 
    (GotoLabelList ?) 
    >> 

%%OpcodeField 

#skip "<hblanks>" 
    << (GotoEOLComment ?) >> 
#ifnotoken 
    << (GotoEOLComment ?) >> 

-- Opcode field tokens 
#token 'ABA'  "[aA][bB][aA]" 
    << (GotoEOLComment ?) >> 
#token 'ABX'  "[aA][bB][xX]" 
    << (GotoEOLComment ?) >> 
#token 'ADC'  "[aA][dD][cC]" 
    << (GotoABregister ?) >> 
#token 'ADCA'  "[aA][dD][cC][aA]" 
    << (GotoOperand ?) >> 
#token 'ADCB'  "[aA][dD][cC][bB]" 
    << (GotoOperand ?) >> 
#token 'ADCD'  "[aA][dD][cC][dD]" 
    << (GotoOperand ?) >> 
#token 'ADD'  "[aA][dD][dD]" 
    << (GotoABregister ?) >> 
#token 'ADDA'  "[aA][dD][dD][aA]" 
    << (GotoOperand ?) >> 
#token 'ADDB'  "[aA][dD][dD][bB]" 
    << (GotoOperand ?) >> 
#token 'ADDD'  "[aA][dD][dD][dD]" 
    << (GotoOperand ?) >> 
#token 'AND'  "[aA][nN][dD]" 
    << (GotoABregister ?) >> 
#token 'ANDA'  "[aA][nN][dD][aA]" 
    << (GotoOperand ?) >> 
#token 'ANDB'  "[aA][nN][dD][bB]" 
    << (GotoOperand ?) >> 
#token 'ANDCC'  "[aA][nN][dD][cC][cC]" 
    << (GotoRegister ?) >> 
...[long list of opcodes snipped] 

#token IDENTIFIER [STRING] "<identifier>" 
    << (local (;; (= [TokenScan natural] 1) ; process all string characters 
     (= [TokenLength natural] ?:TokenCharacterCount)= 
     (= [TokenString (reference TokenBodyT)] (. ?:TokenCharacters)) 
     (= [Result (reference string)] (. ?:Lexeme:Literal:String:Value)) 
     [ThisCharacterCode natural] 
     (define Ordinala #61) 
     (define Ordinalf #66) 
     (define OrdinalA #41) 
     (define OrdinalF #46) 
    );; 
    (;; (= (@ Result) `') ; start with empty string 
    (while (<= TokenScan TokenLength) 
     (;; (= ThisCharacterCode (coerce natural TokenString:TokenScan)) 
     (+= TokenScan) ; bump past character 
     (ifthen (>= ThisCharacterCode Ordinala) 
      (-= ThisCharacterCode #20) ; fold to upper case 
     )ifthen 
     (= (@ Result) (append (@ Result) (coerce character ThisCharacterCode)))= 

     );; 
    )while 
    );; 
)local 
    (= ?:Lexeme:Literal:String:Format (LiteralFormat:MakeCompactStringLiteralFormat 0)) ; nothing interesting in string 
    (GotoOperandField ?) 
    >> 

#token '#' "\#" -- special constant introduction (FDB) 
    << (GotoDataField ?) >> 

#token NUMBER [NATURAL] "<decimal_number>" 
    << (local [format LiteralFormat:NaturalLiteralFormat] 
    (;; (= ?:Lexeme:Literal:Natural:Value (ConvertDecimalTokenStringToNatural (. format) ? 0 0)) 
    (= ?:Lexeme:Literal:Natural:Format (LiteralFormat:MakeCompactNaturalLiteralFormat format)) 
    );; 
)local 
(GotoOperandField ?) 
    >> 

#token NUMBER [NATURAL] "\$ <hexadecimal_digit>+" 
    << (local [format LiteralFormat:NaturalLiteralFormat] 
    (;; (= ?:Lexeme:Literal:Natural:Value (ConvertHexadecimalTokenStringToNatural (. format) ? 1 0)) 
    (= ?:Lexeme:Literal:Natural:Format (LiteralFormat:MakeCompactNaturalLiteralFormat format)) 
    );; 
)local 
(GotoOperandField ?) 
    >> 

#token NUMBER [NATURAL] "\% <binary_digit>+" 
    << (local [format LiteralFormat:NaturalLiteralFormat] 
    (;; (= ?:Lexeme:Literal:Natural:Value (ConvertBinaryTokenStringToNatural (. format) ? 1 0)) 
    (= ?:Lexeme:Literal:Natural:Format (LiteralFormat:MakeCompactNaturalLiteralFormat format)) 
    );; 
)local 
(GotoOperandField ?) 
    >> 

#token CHARACTER [CHARACTER] "<squoted_character>" 
    << (= ?:Lexeme:Literal:Character:Value (TokenStringCharacter ? 2)) 
    (= ?:Lexeme:Literal:Character:Format (LiteralFormat:MakeCompactCharacterLiteralFormat 0 0)) ; nothing special about character 
    (GotoOperandField ?) 
    >> 


%%OperandField 

#skip "<hblanks>" 
    << (GotoEOLComment ?) >> 
#ifnotoken 
    << (GotoEOLComment ?) >> 

-- Tokens signalling switch to index register modes 
#token ',' "\," 
    <<(GotoRegisterField ?)>> 
#token '[' "\[" 
    <<(GotoRegisterField ?)>> 

-- Operators for arithmetic syntax 
#token '!!' "\!\!" 
#token '!' "\!" 
#token '##' "\#\#" 
#token '#' "\#" 
#token '&' "\&" 
#token '(' "\(" 
#token ')' "\)" 
#token '*' "\*" 
#token '+' "\+" 
#token '-' "\-" 
#token '/' "\/" 
#token '//' "\/\/" 
#token '<' "\<" 
#token '<' "\<" 
#token '<<' "\<\<" 
#token '<=' "\<\=" 
#token '</' "\<\/" 
#token '=' "\=" 
#token '>' "\>" 
#token '>' "\>" 
#token '>=' "\>\=" 
#token '>>' "\>\>" 
#token '>/' "\>\/" 
#token '\\' "\\" 
#token '|' "\|" 
#token '||' "\|\|" 

#token NUMBER [NATURAL] "<decimal_number>" 
    << (local [format LiteralFormat:NaturalLiteralFormat] 
    (;; (= ?:Lexeme:Literal:Natural:Value (ConvertDecimalTokenStringToNatural (. format) ? 0 0)) 
    (= ?:Lexeme:Literal:Natural:Format (LiteralFormat:MakeCompactNaturalLiteralFormat format)) 
    );; 
)local 
    >> 

#token NUMBER [NATURAL] "\$ <hexadecimal_digit>+" 
    << (local [format LiteralFormat:NaturalLiteralFormat] 
    (;; (= ?:Lexeme:Literal:Natural:Value (ConvertHexadecimalTokenStringToNatural (. format) ? 1 0)) 
    (= ?:Lexeme:Literal:Natural:Format (LiteralFormat:MakeCompactNaturalLiteralFormat format)) 
    );; 
)local 
    >> 

#token NUMBER [NATURAL] "\% <binary_digit>+" 
    << (local [format LiteralFormat:NaturalLiteralFormat] 
    (;; (= ?:Lexeme:Literal:Natural:Value (ConvertBinaryTokenStringToNatural (. format) ? 1 0)) 
    (= ?:Lexeme:Literal:Natural:Format (LiteralFormat:MakeCompactNaturalLiteralFormat format)) 
    );; 
)local 
    >> 

-- Notice that an apparent register is accepted as a label in this mode 
#token IDENTIFIER [STRING] "<identifier>" 
    << (local (;; (= [TokenScan natural] 1) ; process all string characters 
     (= [TokenLength natural] ?:TokenCharacterCount)= 
     (= [TokenString (reference TokenBodyT)] (. ?:TokenCharacters)) 
     (= [Result (reference string)] (. ?:Lexeme:Literal:String:Value)) 
     [ThisCharacterCode natural] 
     (define Ordinala #61) 
     (define Ordinalf #66) 
     (define OrdinalA #41) 
     (define OrdinalF #46) 
    );; 
    (;; (= (@ Result) `') ; start with empty string 
    (while (<= TokenScan TokenLength) 
     (;; (= ThisCharacterCode (coerce natural TokenString:TokenScan)) 
     (+= TokenScan) ; bump past character 
     (ifthen (>= ThisCharacterCode Ordinala) 
      (-= ThisCharacterCode #20) ; fold to upper case 
     )ifthen 
     (= (@ Result) (append (@ Result) (coerce character ThisCharacterCode)))= 

     );; 
    )while 
    );; 
)local 
    (= ?:Lexeme:Literal:String:Format (LiteralFormat:MakeCompactStringLiteralFormat 0)) ; nothing interesting in string 
    >> 

%%Register -- operand field for TFR, ANDCC, ORCC, EXG opcodes 

#skip "<hblanks>" 
#ifnotoken << (GotoRegisterField ?) >> 

%%RegisterField -- handles registers and indexing mode syntax 
-- In this mode, names that look like registers are recognized as registers 

#skip "<hblanks>" 
    << (GotoEOLComment ?) >> 
#ifnotoken 
    << (GotoEOLComment ?) >> 

#token '[' "\[" 
#token ']' "\]" 
#token '--' "\-\-" 
#token '++' "\+\+" 

#token 'A'  "[aA]" 
#token 'B'  "[bB]" 
#token 'CC'  "[cC][cC]" 
#token 'DP'  "[dD][pP] | [dD][pP][rR]" -- DPR shouldnt be needed, but found one instance 
#token 'D'  "[dD]" 
#token 'Z'  "[zZ]" 

-- Index register designations 
#token 'X'  "[xX]" 
#token 'Y'  "[yY]" 
#token 'U'  "[uU]" 
#token 'S'  "[sS]" 
#token 'PCR' "[pP][cC][rR]" 
#token 'PC'  "[pP][cC]" 

#token ',' "\," 

-- Operators for arithmetic syntax 
#token '!!' "\!\!" 
#token '!' "\!" 
#token '##' "\#\#" 
#token '#' "\#" 
#token '&' "\&" 
#token '(' "\(" 
#token ')' "\)" 
#token '*' "\*" 
#token '+' "\+" 
#token '-' "\-" 
#token '/' "\/" 
#token '<' "\<" 
#token '<' "\<" 
#token '<<' "\<\<" 
#token '<=' "\<\=" 
#token '<|' "\<\|" 
#token '=' "\=" 
#token '>' "\>" 
#token '>' "\>" 
#token '>=' "\>\=" 
#token '>>' "\>\>" 
#token '>|' "\>\|" 
#token '\\' "\\" 
#token '|' "\|" 
#token '||' "\|\|" 

#token NUMBER [NATURAL] "<decimal_number>" 
    << (local [format LiteralFormat:NaturalLiteralFormat] 
    (;; (= ?:Lexeme:Literal:Natural:Value (ConvertDecimalTokenStringToNatural (. format) ? 0 0)) 
    (= ?:Lexeme:Literal:Natural:Format (LiteralFormat:MakeCompactNaturalLiteralFormat format)) 
    );; 
)local 
    >> 

... [snip] 

%% -- end M6809.lex 

**************** पार्सर ******** ******

-- M6809.ATG: Motorola 6809 assembly code parser 
-- (C) Copyright 1989;1999-2002 Ira D. Baxter; All Rights Reserved 

m6809 = sourcelines ; 

sourcelines = ; 
sourcelines = sourcelines sourceline EOL ; 
    <<PrettyPrinter>>: { V(CV(sourcelines[1]),H(sourceline,A<eol>(EOL))); } 

-- leading opcode field symbol should be treated as keyword. 

sourceline = ; 
sourceline = labels ; 
sourceline = optional_labels 'EQU' expression ; 
    <<PrettyPrinter>>: { H(optional_labels,A<opcode>('EQU'),A<operand>(expression)); } 
sourceline = LABEL 'SET' expression ; 
    <<PrettyPrinter>>: { H(A<firstlabel>(LABEL),A<opcode>('SET'),A<operand>(expression)); } 
sourceline = optional_label instruction ; 
    <<PrettyPrinter>>: { H(optional_label,instruction); } 
sourceline = optional_label optlabelleddirective ; 
    <<PrettyPrinter>>: { H(optional_label,optlabelleddirective); } 
sourceline = optional_label implicitdatadirective ; 
    <<PrettyPrinter>>: { H(optional_label,implicitdatadirective); } 
sourceline = unlabelleddirective ; 
sourceline = '?ERROR' ; 
    <<PrettyPrinter>>: { A<opcode>('?ERROR'); } 

optional_label = labels ; 
optional_label = LABEL ':' ; 
    <<PrettyPrinter>>: { H(A<firstlabel>(LABEL),':'); } 
optional_label = ; 

optional_labels = ; 
optional_labels = labels ; 
labels = LABEL ; 
    <<PrettyPrinter>>: { A<firstlabel>(LABEL); } 
labels = labels ',' LABEL ; 
    <<PrettyPrinter>>: { H(labels[1],',',A<otherlabels>(LABEL)); } 

unlabelleddirective = 'END' ; 
    <<PrettyPrinter>>: { A<opcode>('END'); } 
unlabelleddirective = 'END' expression ; 
    <<PrettyPrinter>>: { H(A<opcode>('END'),A<operand>(expression)); } 
unlabelleddirective = 'IF' expression EOL conditional ; 
    <<PrettyPrinter>>: { V(H(A<opcode>('IF'),H(A<operand>(expression),A<eol>(EOL))),CV(conditional)); } 
unlabelleddirective = 'IFDEF' IDENTIFIER EOL conditional ; 
    <<PrettyPrinter>>: { V(H(A<opcode>('IFDEF'),H(A<operand>(IDENTIFIER),A<eol>(EOL))),CV(conditional)); } 
unlabelleddirective = 'IFUND' IDENTIFIER EOL conditional ; 
    <<PrettyPrinter>>: { V(H(A<opcode>('IFUND'),H(A<operand>(IDENTIFIER),A<eol>(EOL))),CV(conditional)); } 
unlabelleddirective = 'INCLUDE' FILENAME ; 
    <<PrettyPrinter>>: { H(A<opcode>('INCLUDE'),A<operand>(FILENAME)); } 
unlabelleddirective = 'LIST' expression ; 
    <<PrettyPrinter>>: { H(A<opcode>('LIST'),A<operand>(expression)); } 
unlabelleddirective = 'NAME' IDENTIFIER ; 
    <<PrettyPrinter>>: { H(A<opcode>('NAME'),A<operand>(IDENTIFIER)); } 
unlabelleddirective = 'ORG' expression ; 
    <<PrettyPrinter>>: { H(A<opcode>('ORG'),A<operand>(expression)); } 
unlabelleddirective = 'PAGE' ; 
    <<PrettyPrinter>>: { A<opcode>('PAGE'); } 
unlabelleddirective = 'PAGE' HEADING ; 
    <<PrettyPrinter>>: { H(A<opcode>('PAGE'),A<operand>(HEADING)); } 
unlabelleddirective = 'PCA' expression ; 
    <<PrettyPrinter>>: { H(A<opcode>('PCA'),A<operand>(expression)); } 
unlabelleddirective = 'PCC' expression ; 
    <<PrettyPrinter>>: { H(A<opcode>('PCC'),A<operand>(expression)); } 
unlabelleddirective = 'PSR' expression ; 
    <<PrettyPrinter>>: { H(A<opcode>('PSR'),A<operand>(expression)); } 
unlabelleddirective = 'TABS' numberlist ; 
    <<PrettyPrinter>>: { H(A<opcode>('TABS'),A<operand>(numberlist)); } 
unlabelleddirective = 'TITLE' HEADING ; 
    <<PrettyPrinter>>: { H(A<opcode>('TITLE'),A<operand>(HEADING)); } 
unlabelleddirective = 'WITH' settings ; 
    <<PrettyPrinter>>: { H(A<opcode>('WITH'),A<operand>(settings)); } 

settings = setting ; 
settings = settings ',' setting ; 
    <<PrettyPrinter>>: { H*; } 
setting = 'WI' '=' NUMBER ; 
    <<PrettyPrinter>>: { H*; } 
setting = 'DE' '=' NUMBER ; 
    <<PrettyPrinter>>: { H*; } 
setting = 'M6800' ; 
setting = 'M6801' ; 
setting = 'M6809' ; 
setting = 'M6811' ; 

-- collects lines of conditional code into blocks 
conditional = 'ELSEIF' expression EOL conditional ; 
    <<PrettyPrinter>>: { V(H(A<opcode>('ELSEIF'),H(A<operand>(expression),A<eol>(EOL))),CV(conditional[1])); } 
conditional = 'ELSE' EOL else ; 
    <<PrettyPrinter>>: { V(H(A<opcode>('ELSE'),A<eol>(EOL)),CV(else)); } 
conditional = 'FIN' ; 
    <<PrettyPrinter>>: { A<opcode>('FIN'); } 
conditional = sourceline EOL conditional ; 
    <<PrettyPrinter>>: { V(H(sourceline,A<eol>(EOL)),CV(conditional[1])); } 

else = 'FIN' ; 
    <<PrettyPrinter>>: { A<opcode>('FIN'); } 
else = sourceline EOL else ; 
    <<PrettyPrinter>>: { V(H(sourceline,A<eol>(EOL)),CV(else[1])); } 

-- keyword-less directive, generates data tables 

implicitdatadirective = implicitdatadirective ',' implicitdataitem ; 
    <<PrettyPrinter>>: { H*; } 
implicitdatadirective = implicitdataitem ; 

implicitdataitem = '#' expression ; 
    <<PrettyPrinter>>: { A<operand>(H('#',expression)); } 
implicitdataitem = '+' expression ; 
    <<PrettyPrinter>>: { A<operand>(H('+',expression)); } 
implicitdataitem = '-' expression ; 
    <<PrettyPrinter>>: { A<operand>(H('-',expression)); } 
implicitdataitem = expression ; 
    <<PrettyPrinter>>: { A<operand>(expression); } 
implicitdataitem = STRING ; 
    <<PrettyPrinter>>: { A<operand>(STRING); } 

-- instructions valid for m680C (see Software Dynamics ASM manual) 
instruction = 'ABA' ; 
    <<PrettyPrinter>>: { A<opcode>('ABA'); } 
instruction = 'ABX' ; 
    <<PrettyPrinter>>: { A<opcode>('ABX'); } 

instruction = 'ADC' 'A' operandfetch ; 
    <<PrettyPrinter>>: { H(A<opcode>(H('ADC','A')),A<operand>(operandfetch)); } 
instruction = 'ADC' 'B' operandfetch ; 
    <<PrettyPrinter>>: { H(A<opcode>(H('ADC','B')),A<operand>(operandfetch)); } 
instruction = 'ADCA' operandfetch ; 
    <<PrettyPrinter>>: { H(A<opcode>('ADCA'),A<operand>(operandfetch)); } 
instruction = 'ADCB' operandfetch ; 
    <<PrettyPrinter>>: { H(A<opcode>('ADCB'),A<operand>(operandfetch)); } 
instruction = 'ADCD' operandfetch ; 
    <<PrettyPrinter>>: { H(A<opcode>('ADCD'),A<operand>(operandfetch)); } 

instruction = 'ADD' 'A' operandfetch ; 
    <<PrettyPrinter>>: { H(A<opcode>(H('ADD','A')),A<operand>(operandfetch)); } 
instruction = 'ADD' 'B' operandfetch ; 
    <<PrettyPrinter>>: { H(A<opcode>(H('ADD','B')),A<operand>(operandfetch)); } 
instruction = 'ADDA' operandfetch ; 
    <<PrettyPrinter>>: { H(A<opcode>('ADDA'),A<operand>(operandfetch)); } 

[..snip...] 

-- condition code mask for ANDCC and ORCC 
conditionmask = '#' expression ; 
    <<PrettyPrinter>>: { H*; } 
conditionmask = expression ; 

target = expression ; 

operandfetch = '#' expression ; --immediate 
    <<PrettyPrinter>>: { H*; } 

operandfetch = memoryreference ; 

operandstore = memoryreference ; 

memoryreference = '[' indexedreference ']' ; 
    <<PrettyPrinter>>: { H*; } 
memoryreference = indexedreference ; 

indexedreference = offset ; 
indexedreference = offset ',' indexregister ; 
    <<PrettyPrinter>>: { H*; } 
indexedreference = ',' indexregister ; 
    <<PrettyPrinter>>: { H*; } 
indexedreference = ',' '--' indexregister ; 
    <<PrettyPrinter>>: { H*; } 
indexedreference = ',' '-' indexregister ; 
    <<PrettyPrinter>>: { H*; } 
indexedreference = ',' indexregister '++' ; 
    <<PrettyPrinter>>: { H*; } 
indexedreference = ',' indexregister '+' ; 
    <<PrettyPrinter>>: { H*; } 

offset = '>' expression ; -- page zero ref 
    <<PrettyPrinter>>: { H*; } 
offset = '<' expression ; -- long reference 
    <<PrettyPrinter>>: { H*; } 
offset = expression ; 
offset = 'A' ; 
offset = 'B' ; 
offset = 'D' ; 

registerlist = registername ; 
registerlist = registerlist ',' registername ; 
    <<PrettyPrinter>>: { H*; } 

registername = 'A' ; 
registername = 'B' ; 
registername = 'CC' ; 
registername = 'DP' ; 
registername = 'D' ; 
registername = 'Z' ; 
registername = indexregister ; 

indexregister = 'X' ; 
indexregister = 'Y' ; 
indexregister = 'U' ; -- not legal on M6811 
indexregister = 'S' ; 
indexregister = 'PCR' ; 
indexregister = 'PC' ; 

expression = sum '=' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '<<' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '</' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '<=' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '<' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '>>' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '>/' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '>=' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '>' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum '#' sum ; 
    <<PrettyPrinter>>: { H*; } 
expression = sum ; 

sum = product ; 
sum = sum '+' product ; 
    <<PrettyPrinter>>: { H*; } 
sum = sum '-' product ; 
    <<PrettyPrinter>>: { H*; } 
sum = sum '!' product ; 
    <<PrettyPrinter>>: { H*; } 
sum = sum '!!' product ; 
    <<PrettyPrinter>>: { H*; } 

product = term '*' product ; 
    <<PrettyPrinter>>: { H*; } 
product = term '||' product ; -- wrong? 
    <<PrettyPrinter>>: { H*; } 
product = term '/' product ; 
    <<PrettyPrinter>>: { H*; } 
product = term '//' product ; 
    <<PrettyPrinter>>: { H*; } 
product = term '&' product ; 
    <<PrettyPrinter>>: { H*; } 
product = term '##' product ; 
    <<PrettyPrinter>>: { H*; } 
product = term ; 

term = '+' term ; 
    <<PrettyPrinter>>: { H*; } 
term = '-' term ; 
    <<PrettyPrinter>>: { H*; } 
term = '\\' term ; -- complement 
    <<PrettyPrinter>>: { H*; } 
term = '&' term ; -- not 

term = IDENTIFIER ; 
term = NUMBER ; 
term = CHARACTER ; 
term = '*' ; 
term = '(' expression ')' ; 
    <<PrettyPrinter>>: { H*; } 

numberlist = NUMBER ; 
numberlist = numberlist ',' NUMBER ; 
    <<PrettyPrinter>>: { H*; } 
+0

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

+1

@ गैरी: आप जो पूछते हैं उससे सावधान रहें:} मेरे छोटे उत्तर में संपादन को एक विशालकाय में बदलना देखें। –

+0

@ गैरी: पीएस, "इसे रैंक करें" करने के लिए, उत्तर की शुरुआत के बगल में स्कोर के ऊपर ऊपर की ओर वाला त्रिकोण क्लिक करें। : -} –

3

बीएनएफ आमतौर पर संरचित, घोंसला वाली भाषाओं जैसे पास्कल, सी ++, या वास्तव में अल्गोल परिवार से व्युत्पन्न कुछ भी उपयोग किया जाता है (जिसमें सी # जैसी आधुनिक भाषाएं शामिल हैं)। अगर मैं एक असेंबलर को कार्यान्वित कर रहा था, तो मैं opcode और operands से पैटर्न-मिलान के लिए कुछ सरल नियमित अभिव्यक्तियों का उपयोग कर सकता हूं। थोड़ा समय के बाद से मैं का उपयोग किया है Z80 विधानसभा भाषा हो गया है, लेकिन आप की तरह कुछ का उपयोग हो सकता है:

/\s*(\w{2,3})\s+((\w+)(,\w+)?)?/ 

यह किसी भी लाइन एक दो या तीन अक्षर opcode एक या दो ऑपरेंड अलग द्वारा पीछा के होते हैं जो मेल खाएगा एक अल्पविराम से। इस तरह एक असेंबलर लाइन निकालने के बाद, आप ओपोड को देखेंगे और निर्देश के लिए सही बाइट उत्पन्न करेंगे, जिसमें लागू होने पर ऑपरेटरों के मान शामिल हैं।

नियमित अभिव्यक्तियों का उपयोग करके ऊपर वर्णित पार्सर का प्रकार "विज्ञापन" पार्सर कहा जाएगा, जिसका अनिवार्य रूप से मतलब है कि आप किसी प्रकार के ब्लॉक आधार पर इनपुट को विभाजित और जांचते हैं (असेंबली भाषा के मामले में, द्वारा पाठ रेखा)।

2

मैं तुम्हें इसके overthink की जरूरत नहीं लगता। कोई एक पार्सर कि एक लोड आपरेशन, गंतव्य और स्रोत रजिस्टर में अलग "एलडी ए, ए 'लेता है, जब तुम सिर्फ स्ट्रिंग पूरी बात (सापेक्ष मामले और रिक्त स्थान को) एक opcode में सीधे मिलान कर सकते हैं बनाने बिंदु नहीं है।

वहाँ है कि कई opcodes नहीं हैं, और वे इस तरह से कि तुम सच में पार्स करने और IMO कोडांतरक समझने से ज्यादा लाभ मिलेगा में व्यवस्थित नहीं कर रहे हैं। जाहिर है आपको बाइट/एड्रेस/इंडेक्सिंग तर्कों के लिए एक पार्सर की आवश्यकता होगी, लेकिन इसके अलावा मेरे पास सिर्फ एक-एक-एक लुकअप होगा।

+1

आपकी प्रतिक्रिया के लिए धन्यवाद ... मैं मानता हूं कि एक और अधिक सरल पथ नीचे जा रहा हूं, लेकिन मैं इसे एक और जटिल भाषा में विस्तारित करने में दिलचस्पी लेता हूं और आंकड़ा मैं शुरुआत से सुविधाओं का उपयोग करना चाहता हूं ... इसके अलावा एएसएम के कुछ अन्य हिस्सों में अंतर हैं जैसे कि इक्विटी,। डीबी, .ds, .dw, #include,() और फिर हम सामान्य केस स्टेटमेंट्स IF ELSE में शामिल होना शुरू करते हैं। इसके अलावा, यह बीएनएफ की अवधारणाओं को सीखने में भी एक व्यायाम है और इसे और अधिक सरल कार्यान्वयन के लिए उपयोग करें। –

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