This is a creation in Article, where the information may have evolved or changed.
Original Http://www.oschina.net/translate/build-an-interpreted-language-in-go
English Original: Part 1:let ' s build a interpreted language in go!
I am currently involved in one of our major projects, Alloy. Alloy is a compiler-based programming language. One of my favorite hobbies in the field of computer and programming is language. In fact, I think every programmer should have a basic understanding of how programming languages work, and that's why I write this series. This is the first article in a series of articles. The series will describe the code I've written to show you how to make your own programming language. Note here that this article assumes that you have little or no past experience with the compiler/interpreter theory/practice. Also note that this series of articles is not about programming or go programming. |
Garfielt Translated 1 weeks ago 1 Person top top translation of good Oh! |
what is the solution Release (interpreter)? The Interpreter directly executes or displays instructions written in a particular scripting language. This can be a scripting language that already exists, like Python or Ruby. It can also be a scripting language that you create yourself, and that's what we're going to do here. This series will guide you through the basics of go to implement your own scripting language/interpreter "Toys" . Why is the "toy" scripting language/interpreter? The Interpreter can be extremely complex. Modern interpreters, such as Ruby or Python, are very large, including hundreds of lines, or even up to millions of code volumes. This is not easy for a novice to understand. Toy language is a much simpler version, and they often skip or omit some phrases (we will not consider optimization here). Making a toy language is an effective way to understand how they work, and when you start using them, they will actually help you understand, even if you're not working on an already existing interpreter (like rust). |
ANN_MF Translated 7 days ago 1 Human Top top Good translation! |
programming language You can build an interpreter in any language you like. In this case, I will use go. I haven't written a lot of go before, so it's also a learning experience for me! However, if you are not accustomed to go writing, you can make your interpreter in any of the following languages, either C,java, or even JavaScript. summary Because there are so many interpreters and compilers in the world today, there are many tools to help you make them. You need to decide whether to consider using an external tool secretly, or you want to write all the code yourself. I prefer the latter because I think if I use an external tool to do this, I will not learn how it works. But it all depends on you. In an interpreter environment, whether you use these tools can cause a very strong controversy in the compiler/interpreter community. Some people will tell you that if you don't use Antlr,bison or some other tool then you will go wrong. Others will say that the only way to do it is to write your own Vocabulary Analyzer (lexer) and parser (parser). Finally, this is your choice, but in this series of articles, I will at least cover how to build the lexical analyzer (Lexer) and the parser (Parser). |
ANN_MF Translated 7 days ago 1 Human Top top Good translation! |
Theory Before we go any further, we need to explain the theory. What are lexical analyzers and parsers If you see this paragraph and are confused by what I mean by the lexical analyzer and parser, then don't worry. The typical practice is to divide the analysis process into different stages. Some stages are optional, and in other words it is called the optimization phase. But most modern parsers handle almost all stages. Let's go deeper and look at these stages. Lexical analysis The first stage is the syntax analysis, basically is a word breaker. Lexical analysis, parser, or syntactic parsing divides characters or input streams into tokens. These tokens are stored as a marker stream in a data structure such as a list or container. The parser classifies these words (the string of symbols in the input stream), giving a certain meaning to a particular tag. For example, words such as *,=,+ can be classified as operators, and tost and bacon can be classified as string literals, while ' a ' and ' B ' are characters. |
Happy 613 Translated 7 days ago 2 Person top top translation of good Oh! |
Analytical A parser is a translation component that is used to receive input from data, a lexical parser produces a list of tokens, and produces an expression, usually an abstract syntax tree, or other structure. The rules that the interpreter follows are called grammars, which are the way you define a language, such as extended backus-naur form (EBNF) and BNF (Backus-naur form), which are used to describe the syntax of a language. Here is an example of a EBNF syntax: letter = "A" | "A" | ... "Z" | "Z" | "_";d igit = {"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"};identifier = letter {letter | digit};
This may not mean anything to you. You may recognize these symbols in programming languages, such as pipe |, curly braces {}. All symbols have a special meaning: {}-denotes repetition | -Denotes an option, similar to or[...]-optional terminal/nonterminal; -termination =-Definition ...-sequence "..."-terminal string
|
No if Translated 7 days ago 1 Person top top translation of good Oh! |
| We'll look at some more symbols in the back. The example above defines a "production rule". A production rule may consist of two lexical elements: non-terminal and terminal. A terminal is a text that cannot be changed by using a grammar rule. A non-terminal is a symbol that can be replaced, which can be seen as a placeholder or a variable. They are sometimes referred to as "syntactic variables". In the example above, identifiers, letters, and numbers are non-terminal symbols. The "Z", "0", "1" are examples of terminal symbols, which are constant characters, meaning that they cannot be changed. Now, what does all the symbols in the above syntax mean? The definition of a letter is: letter = "A" | "a" | ... "z" | "z" | "_"; To be able to understand, read it like reading English, for example, the syntax above is read as "a" or "a" to "Z" or "Z" or "_". So a letter can be anything from a A-Z or an underscore. |
Leoxu Translated 6 days ago 1 Human top top Good translation! |
| We define a number like this: digit = { "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" }; This means that a number can be either "0" or "1" or "2" ... You understand the point. However, be aware of the curly braces here. If you remember the list we provided above, the parentheses represent the repetition, specifying 0 to n repetitions, where n can be any number. This means that a number can be 0-9 repetitions of n multiple times, so 123 is right and 5123 is right. The is finally the identifier: identifier = letter { letter | digit }; At the moment we understand the meaning of letters and numbers (digit), and we can now understand this small production rule. Basically, an identifier must begin with a single character, followed by a repetition of 0 or more different letters or numbers. For example, A_, A_a, A_1, a__, and so on are all the correct identifiers. |
Leoxu Translated 6 days ago 1 Human top top Good translation! |
The lexical and syntactic parsing of these two phases usually refers to the compiler and interpreter as the front end. Now, let's start writing some code, and I'll use go to write. All the source code will be posted on my GitHub page. If you are going to use go to write, first create a new directory for your project and set up your main go file. Just then, I wrote a simple hello World file to test. Go has a magical workspace system, so in the beginning you need to create your workspace, I've been using Linux as my workspace, so I use go to set $HOME/GO environment variables 。 For the sake of convenience, go recommends us to add this setting to reach our path: mkdir $HOME/go Export path= $PATH: $GOPATH/bin The basic path of my project is in Github.com/felixangell. You can find what you're looking for, or your GitHub username: Mkdir-p $GOPATH/src/github.com/yourusername |
He Shunyu Translated 7 days ago 1 Person top top translation of good Oh! |
Now start setting up our interpreter program, we create a folder in the personal directory, the name can be any name you give this interpreter, I call it vident. We enter this directory. ?
| 12 |
mkdir$GOPATH/src/github.com/felixangell/videntcd$GOPATH/src/github.com/felixangell/vident |
Then we create a simple file for testing purposes and can copy this part directly: ?
| 1234567 |
package mainimport "fmt"func main() { fmt.Printf("hello, world\n");} |
Save him to the folder we just created Vident, named Main.go. Now we compile and run it: ?
Because we are using the Engineering directory structure system, we need to add the bin directory to our directory and then simply run the above code. When you run, you should be able to see the output "Hello, World". |
Astringent Wolf Translated 6 days ago 1 Person top top translation of good Oh! |
So then we're going to define our language. Vident is a simple language, we start with a few small features, and then we move on to complex examples. Here is a code example for vident: Let x = 5 + 5print:x, "Hello", X
I need to change to:, otherwise familiar with the TUMBLR format, many people complain about it, sorry! The EBNF syntax of our language: letter = "A" | "a" | ... "z" | "z" | "_";d igit = { "0" | "1" | "2" | "3" | "4" | "5" | " 6 " | " 7 " | " 8 " | " 9 " };identifier = letter { letter | digit }; number_literal = digit | [ "." digit ];string_literal = "" " letter { letter } " ""; char_literal = "'" letter "'"; literal = number_literal | string_literal | char_literal;binaryOp = "+" | "-" | "/" | "*"; binary_expr = expression binaryop expression;expression = binary_expr | function_call | identifier | literal;let_stat = "let" identifier [ "=" Expression ];arguments = { expression "," };function_call = identifier [ ":" arguments ];statement = let_stat | function_call;Now we have introduced some things to this language, most notably square brackets. The square brackets represent an optional value, for example: Let_stat = "let" identifier ["=" expression];
This means that let x and let X = 5 + 5 are all valid, the first one is a definition, such as defining the variable, and the second is the variable declaration that is displayed, which defines the variable and declares the value. |
Garfielt Translated 5 days ago 1 Person top top translation of good Oh! |
Now look at the syntax above may be a little complicated, but if you are a little closer to understand it, it will be more simple than you think. Note that we do not implement it all at once, but instead focus on each part of the syntax and implement it as part of a phase.
No matter what, as above is the first part! Stay tuned for the next chapters, we'll write the lexical analyzer, and we'll discuss more about the interpreter backend.