Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LuaType.js not correctly parsing some complex values #133

Open
ghost opened this issue Aug 28, 2023 · 3 comments
Open

LuaType.js not correctly parsing some complex values #133

ghost opened this issue Aug 28, 2023 · 3 comments
Labels
bug Something isn't working docusaurus plugin

Comments

@ghost
Copy link

ghost commented Aug 28, 2023

I was using LuaType.js for a personal project, and in my testing I found that there were some parsing errors, luckily I was able to make a fix, but note that some of the variables are changed.

const print = console.log

const isPunc = (char) => !!char.match(/[\{\}<>\-\|&<>()\[\]]/)
const isAtom = (char) => !isPunc(char)

function _tokenize(code, isGroup) {
    print("reading", code)
    
    let position = 0
    const tokens = []
    
    const next = () => code[position++]
    const peek = () => code[position]

    const read = (condition) => {
        let buffer = ""
        while (peek() && condition(peek())) {buffer += next()}
        return buffer
    }

    const readBalanced = (left, right) => {
        let buffer = ""
        let depth = 0
        while (peek()) {
            if (peek() === left) {
                depth++
            } else if (peek() === right) {
                if (depth === 0) {
                    break
                } else {
                    depth--
                }
            }
            buffer += next()
        }
        return buffer
    }
    
    while (position < code.length) {
        if (peek() === "(") {
            position++
            tokens.push({
                type: "tuple",
                within: _tokenize(readBalanced("(", ")"), true)
            })
            next()
            continue
        }
        
        if (peek() === "[") {
            next()
            tokens.push({
                type: "indexer",
                within: _tokenize(readBalanced("[", "]")),
            })
            next()
            continue
        }
      
        if (peek() === "{") {
            next()
            tokens.push({
                type: "table",
                within: _tokenize(readBalanced("{", "}"), true),
            })
            next()
            continue
        }
        
        if (isGroup && peek() === ",") {
            next()
            tokens.push({
              type: "separator",
            })
            continue
          }
        
        if (isPunc(peek())) {
            const punc = next()
            
            if (punc === "-" && peek() === ">") {
                tokens.push({
                    type: "arrow",
                })
                next()
                continue
            }
      
            if (punc === "|") {
                tokens.push({ type: "union" })
                continue
            }
            
            if (punc === "&") {
                tokens.push({ type: "intersection" })
                continue
            }
      
            tokens.push({
                type: "punc",
                punc,
            })
            continue
        }
        
        const atom = read((char) =>
            isGroup ? char !== "," && isAtom(char) : isAtom(char)
        )

        if (atom) {
            if (atom.endsWith(":")) {
                tokens.push({ type: "identifier", identifier: atom.slice(0, -1) })
            } else {
                tokens.push({
                    type: "luaType",
                    luaType: atom,
                })
            }
            continue
        }
    }
    
    return tokens
}

function getTokens(code) {
    const noWhitespace = code.replace(/\s/g, '')
    return _tokenize(noWhitespace)
}

var advanced_test = "(callback:<T>(internal:(k:{string&number})->T)->string)->{string|number}"

print(JSON.stringify(getTokens(advanced_test), null, 4))

I believe the only parts I changed are adding support for intersection type, and expanding the isPunc function to correctly catch all punctuation, otherwise it can fail on sub-types, of course in my test I removed whitespace before parsing, but adding these modifications it should still work with whitespace.

@evaera
Copy link
Owner

evaera commented Aug 28, 2023

This isn't the correct way to contribute to an open source project. Pull Requests are for submitting changes, not issues. And it's a good idea to include the cases that are failing in your issue to justify why the change needs to be made, rather than just saying that it does. I can't do anything with this code you've given me.

@ghost
Copy link
Author

ghost commented Aug 28, 2023

Sorry, never created a pull request before, but I created one now and the dif is only 7 characters and includes the use case where it broke too, hope this is ok!

@YetAnotherClown
Copy link
Collaborator

@probablytukars I noticed that you deleted your Pull Request. If you would be interested in opening it again, I'll look into it and merge it if approved.

@YetAnotherClown YetAnotherClown added bug Something isn't working docusaurus plugin labels Jul 13, 2024
YetAnotherClown added a commit that referenced this issue Oct 1, 2024
Fixes an issue in #133 with intersection types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working docusaurus plugin
Projects
None yet
Development

No branches or pull requests

2 participants