ERROR: LoadError: type DataType has no field Let

Hello! I have a problem which I don’t know how to solve. I am making a lexer for my programming language and there is this problem: ERROR: LoadError: type DataType has no field Let Stacktrace: [1] getproperty(x::Type, f::Symbol) @ Base .\Base.jl:32 [2] top-level scope @ C:\Users\jakub\Documents\julia\myopl\lexer.jl:15 [3] include(fname::String) @ Base.MainInclude .\client.jl:489 [4] top-level scope @ C:\Users\jakub\Documents\julia\myopl\main.jl:1 in expression starting at C:\Users\jakub\Documents\julia\myopl\lexer.jl:1 in expression starting at C:\Users\jakub\Documents\julia\myopl\main.jl:1
Here is the full code:


export Token, TokenType, tokenize

@enum TokenType begin
    Number = 1
    Identifier = 2
    Equals = 3
    OpenParen = 4
    CloseParen = 5
    BinaryOperator = 6
    Let = 7
end

KEYWORDS = Dict(
    "let" => TokenType.Let
)

struct Token 
    value::String
    type::TokenType
end

function token(value, type)
    return Token(value, type)
end

function isalpha(src)
    return uppercase(src) != lowercase(src)
end

function isint(str)
    c = Int(codepoint(str[1]))
    bounds = [Int('0'), Int('9')]
    return c >= bounds[1] && c <= bounds[2]
end

function isskippable(str)
    return str == " " || str == "\n" || str == "\t"
end

function tokenize(sourceCode) 
    tokens = Token[]
    src = split(sourceCode, "")

    while length(src) > 0
        if first(src) == "("
            push!(tokens, token("(", TokenType.OpenParen))
            popfirst!(src)
        elseif first(src) == ")"
            push!(tokens, token(")", TokenType.CloseParen))
            popfirst!(src)
        elseif first(src) == '+' || first(src) == '-' || first(src) == '/' || first(src) == '*'
            push!(tokens, token(first(src), TokenType.BinaryOperator))
            popfirst!(src)
        elseif first(src) == '='
            push!(tokens, token("=", TokenType.Equals))
            popfirst!(src)
        else
            if isint(first(src))
                num = ""
                while length(src) > 0 && isint(first(src))
                    num *= popfirst!(src)
                end

                push!(tokens, token(num, TokenType.Number))
            elseif isalpha(first(src))
                ident = ""
                while length(src) > 0 && (isalpha(first(src)) || isint(first(src)))
                    ident *= popfirst!(src)
                end

                if haskey(KEYWORDS, ident)
                    reserved = KEYWORDS[ident]
                    push!(tokens, token(ident, reserved))
                else
                    push!(tokens, token(ident, TokenType.Identifier))
                end
            elseif isskippable(first(src))
                popfirst!(src)
            else
                println("Unrecognized character found in source: ", first(src))
                exit(1)
            end
        end
    end

    return tokens
end

end

Thank you.

TokenType.Let is not the correct syntax.

You refer to the enum member values just with their names:

KEYWORDS = Dict(
    "let" => Let
)

The style guide here is that the member values are lower case, let in this case. But let is a reserved key word, so you couldn’t use this in lowercase.

See Essentials · The Julia Language for some documentation.

1 Like

You can also use EnumX.jl for scoped enums, which would allow TokenType.Let to work