There are many programming languages that have their own unique characteristics. But in order for a program written in any of them to work, you need to broadcast it. Sometimes programming languages are developed for their own needs (for example, support for automation in large applications) and then it becomes necessary to write a translator.
Necessary
- - natural grammar or BNF of the source language;
- - development tools.
Instructions
Step 1
Prepare the data for lexical analysis of the text in the source language. List all the tokens in the language. Break them down into categories (keywords, numeric and string literals, identifiers, whitespace, punctuation, etc.).
Step 2
Implement a module or lexer. At the input, it should receive a "raw" data stream, and at the output form a list of elements containing tokens and their type identifiers in the sequence in which they occur in the source text. The parsing program can be a fairly simple "single-level" scanner. Implementing error recovery doesn't make sense. Invalid characters should be treated as errors.
Step 3
Prepare the data for parsing. Based on the natural grammar or BNF of the source language, compose its LL1 grammar. Based on this type of grammar, draw up a parsing scheme in terms of the categories of valid tokens and semantic constructs of the language.
Step 4
Implement a module or parser. At the input, it should receive a list of tokens prepared at the stage of lexical parsing. Develop recursive syntax checking algorithms using the schema you created in step three. If necessary, implement error recovery mechanisms. Add functionality to the parsing algorithms to build a tree for calculating functions, class methods. With the correct structure of parsing algorithms, this functionality can be implemented without any problems. This avoids the need to implement it as a separate module. The created data structures must contain lists of instructions in the form of "flat" sequences (arithmetic expressions expanded into postfix form suitable for calculation on a stack machine, loops converted into combinations of sequences of computational instructions and conditional or unconditional jumps, etc.).
Step 5
Create an optimization module if needed. It should process and transform the data structures prepared in the previous step. Optimization algorithms and methods are very diverse.
Step 6
Develop a code generator. When processing the structures prepared in the fourth or fifth steps, it should simply transform the sequences of abstract instructions into instructions for execution on a specific platform.
Step 7
Create a binder program (linker) if needed. It should generate the resulting executable module by choosing the location of the code segments, calculating the addresses of the labels, etc.