Start trying to decode tokens

Yes, the work of parser has not been completed at least. Why two parsers are classified is mainly because orz is written twice

As we all know, code execution is done through the AST. So this step is to convert the tokens into the AST. First, find a website and see what the AST looks like

Well, a random website: https://astexplorer.net/ (I think a lot of people look familiar, um…

If it is JS, the code executed should look like this

The AST it transforms is a little bit complicated, but that’s ok. For now, we just need to refer to some simple formats to avoid some possible errors. In fact, it is not impossible to design the AST completely by ourselves. The feeling of

Well, this is the partial result of the rotation

Well, it’s a billion things, well, just a billion things, well…

Then you need to convert the former tokens into simple versions of this. Therefore, you need to plan the types of AST first

PS: As an aside, the original idea was to design a script that could be used to dynamically load libs of different languages via import, such as the all-purpose JS, so there were some problems, either having a dynamic interpreter that supported all languages, which is, I know, silly, or compiling scripts locally, Unified output of the target platform’s code, HMM.. Well, it doesn’t sound so stupid, but it’s also stupid, and the purpose of scripting language is lost. Well, it’s stupid, so consider script + lib compilation, which means that things imported into it are executed by default on the current platform. Well, it doesn’t matter, it’s too early to consider that

Let’s get back to the topic and program the types, which looks something like this

If it is not enough or if there is a problem, you can change it again. After referring to some other code, I feel that it should probably be enough to use ORZ

Js player victim T T (plan is strongly typed, you have to dream a little bit)

OK, ready, began to copy the algorithm, bah, is to write algorithm, bah bah, write code, how can call copy ~

The goal is to parse two lines of code, and so far it looks like we’re halfway there

(Feels like there’s nothing to annotate (whisper orz

Then I parse the AST of the second line of code (I feel that I need a MemberExpression, so I add a type ORz

All right! This completes the poorly written AST parser (there must be a lot of problems, though… When you encounter a problem, it’s good to solve it

The first two lines of code look something like this

Finally, I’ll fill in some of the utility functions I pulled out

B: well… I regret using literals as token types alone, but it doesn’t affect orz

Finally, attach this source file ~ (this is equivalent to a backup


const astTypes = [
    'Identifier'./ / variable names
    'ImportDeclaration'.'StringLiteral'.'IntegerLiteral'.'CallExperssion'.'MemberExpression',]function isLiteral(type) {
    return ['string'.'integer'].includes(type)
}
function isKeyword(token, value) {
    return token.type === 'keyword' && token.value === value
}
function isOperator(token, value) {
    return token.type === 'operator' && token.value === value
}
function parseLiteralType(type) {
    return type.slice(0.1).toUpperCase() + type.slice(1) + 'Literal'
}


function parseAST(input) {
    let cur = 0
    let ast = {
        type: 'Program'.body: [],}function whileForImport() {
        const node = {
            type: 'ImportDeclaration',}let token = input[cur]
        while(! isOperator(token,'\n') && cur < input.length) {
            cur++
            token = input[cur]
            if(isLiteral(token.type) && ! node.alias) {const type = parseLiteralType(token.type)
                node.source = { type, value: token.value }
            } else if (token.type === 'name' && node.alias) {
                node.alias = { type: 'Identifier'.value: token.value }
            } else if (isKeyword(token, 'as')) {
                node.alias = true
            }
        }
        cur++
        return node
    }

    function whileForCallee() {
        const node = {
            type: 'CallExperssion',}let token = input[cur]
        let parendeep = 0
        while(! isOperator(token,'\n') && cur < input.length) {
            if (token.type === 'name') {
                node.property = { type: 'Identifier'.value: token.value }
            } else if (isOperator(token, '. ') && node.property) {
                constobject = node.object node.object = { ... node.property,type: 'MemberExpression' }
                // The structure of the call chain refers to the AST of js
                if (object) {
                    node.object.object = object
                }
                node.property = null
            } else if (token.type === 'paren') {
                parendeep += ['('].includes(token.value) ? 1 : -1  
            } else if (parendeep && isLiteral(token.type)) {
                node.arguments = node.arguments || []
                const type = parseLiteralType(token.type)
                node.arguments.push({ type, value: token.value })
            }
            cur++
            token = input[cur]
        }
        cur++
        return node
    }

    function walk() {
        let token = input[cur]
        if (isKeyword(token, 'import')) {
            return whileForImport()
        }
        if (token.type === 'name') {
            return whileForCallee()
        }
        cur++
    }
    while (cur < input.length) {
        ast.body.push(walk());
    }
    return ast
}

module.exports = { parseAST }
Copy the code