Foreword: For the development language, we are mostly users, is it hot one day, we also become a creator, design a new language for others to use? In this article, you will learn how to create a new language and its facilities.

background

I just finished a course on principles of compilation. I happened to encounter a problem in writing a questionnaire system (as shown below).

Use an external DSL to change the logical expression of a form, which is difficult to implement, into a coded expression.

First, bold and beautiful ideas

A bold and beautiful idea: Let the product write the code!

How many steps does it take to get a product to write code? A: Three steps, tell the product what programming language to use, then let the product write code, and finally run.

Let’s take a look at the final result

Beautiful idea disassembly

1.1. Step 1: Choose a programming language

Programmers mainly use Java, C++, Javascript, etc., which are collectively referred to as: The General Purpose Language (GPL) has a long learning cycle and requires a programming background, making it impractical for non-developers to write code in GPL. The corresponding Domain Specific Language (DSL), as the name suggests, is a logical Language designed to solve problems in a single Domain in the future. The most common DSLS include HTML & CSS, Markdown, Regex (regular expression), and so on.

1.2, step 2: how to make the product without programming foundation write code

We’re going to develop a DSL compiler that works as well as the MarkDown editor. Preferably with syntax highlighting, syntax hint completion, complete examples, etc.

1.3. Step 3: How to run the code (optional)

It is best not to compile actively, or to compile automatically. It’s best to write code as you see it, just like the Markdown compiler. (Do not run actively, that is, this step can be ignored)

Two, to implement

2.1. Design a new language

It takes a lot of work to design a language. In order to save trouble, the author directly gives a new language that has been designed (HJ).

2.2 Development of HJ editor

Provides an editor friendly to people with no programming experience.

  • Writing code: Develop an Editor based on the Monaco Editor that provides syntax highlighting and input suggestions and completions;
  • Effect display: real-time monitor code input, willHJintoJSAfter execution, real-time display page effect;

2.2.1 Compilation Principle

Here we will use some knowledge of the principles of compilation, which consist of four basic steps:

2.2.2 Syntax highlighting

  • Implementation principle, based on the compilation principle of the first step of lexical analysis, the use of regular matching string, and color matching.

  • The specific code is as follows:
monaco.languages.register({ id: LangId })
      monaco.languages.setMonarchTokensProvider(LangId, {
        tokenizer: {
          root: [ // Token resolution rule
            [/ # (. *)? /.'noUseSign'],
            [/\s*(Q[0-9]*(S[0-9]*)? (A[0-9]*)?) |END\s*/.'Question'],
            [/\s*(if|then)\s*/.'IfStatement'],
            [/\s*(limit|of)\s*/.'LimitStatement'],
            [/\s*(from|to)\s*/.'BranchStatement'],
            [/\s*(show|hide|replace|title|branch|shuffle)\s*/.'action'],
            [/\s*(> |== |>= |<= |<)\s*/.'compareSign'],
            [/\s*(and|or|not|\(|\))\s*/.'linkSign'],
            [/\s*([0-9]\d*)\s*/.'Number'],
            [/\s*(,)\s*/.'Gap']],},keywords: [
          'if'.'then'.'show'.'hide'.'replace'.'title'.'branch'.'shuffle'.'in'.'with'.'to',].operators: ['>'.'= ='.'> ='.'< ='.'<'.'and'.'or'.'not'.'('.') '].whitespace: [[/[ \t\r\n]+/.'white'],
          [/ / # (. *).'comment'.'@comment'],
        ],
      })
      
      monaco.editor.defineTheme(LangId, {
        base: 'vs'.inherit: true.rules: [ / / color
          { token: 'Gap'.foreground: '01DFA5' },
          { token: 'Number'.foreground: 'FA5858' },
          { token: 'Question'.foreground: '0082FF' },
          { token: 'noUseSign'.foreground: 'BDBDBD' },
          { token: 'linkSign'.foreground: '840095' },
          { token: 'compareSign'.foreground: 'AEB404' },
          { token: 'IfStatement'.foreground: '840095' },
          { token: 'LimitStatement'.foreground: '840095' },
          { token: 'BranchStatement'.foreground: '840095' },
          { token: 'action'.foreground: '840095'},].colors: {
          'editorLineNumber.foreground': '# 999999',}})Copy the code

2.2.3 Input suggestions and complement

The effect is as follows:

Use of Monaco. Languages. RegisterCompletionItemProvider interface to implement

monaco.languages.registerCompletionItemProvider(LangId, {
    provideCompletionItems: (model, position) = > {
       return { 
          // suggestions 
          {
            label: '[Question] Q1 Which of the following communication products is most commonly used? `.kind: monaco.languages.CompletionItemKind.Keyword,
            insertText: `Q1`}, {label: Q2 Why do you use QQ most often? `.kind: monaco.languages.CompletionItemKind.Keyword,
            insertText: `Q2`,}// More hints}}})Copy the code

2.2.4 Real-time effect display

To compile JavaScript from [2.2.1], run eval or new Function

Preview code implementation:

// Equip two classes ahead of time, analogous to the browser window object
class Quetion{
 show(key){} / / show
 hide(key){} / / hide
 / /... There are other ways
}
class Answer{
 fn(key){} // Logical comparison
 / /... There are other ways
}

const Q = new Quetion()
const A = new Answer()

// Generate the render function
const render = new Function('Q'.'A'.`Q.hide("Q2", "Q3", "Q4"); if(A.fn("Q1A1")){Q.show("Q2")}; if(A.fn("Q1A2")){Q.show("Q3")}; if(A.fn("Q1A3")){Q.show("Q4")}; `
)
/ / execution
render(Q,A)
Copy the code

conclusion

At this point, we have created a new language, HJ, and developed a Web edition editor around it. This way, the product can be coded with the syntax we set at a very low learning cost.




[Follow the author and explore the frontier of the front end]