Lexer for SQL statements

hi,

First of, I prefer functions over everything else. But I am in a situation in which I only know the correct argument AFTER the SQL statement is tokenized. I won’t bother you with the details but just know that I can’t see another solution to this problem then metaprogramming.

this is the example SQL statement:

a ="select column_2, column_3 from Table_X"

This is the Lexer

function Lexer(a::String) 
   G        =  Tokenize(split_up(replace_all(a,cleaning_up)))
   End_List = esc(copy(G))
   for i in G
      eval(Meta.parse(i[2]))
   end   
   return End_List
end

this is the error statement:

ERROR: UndefVarError: End_List not defined
Stacktrace:
 [1] top-level scope
   @ none:1

now the End_List does not refer to End_List in the function Lexer (as far as I can tell) but to the function that I want to evaluatie which is a string in a Token (which is a Struct).

Token("SELECT", "SELECT","select(@@,^^,##)")

this is what it actually lookslike once I want to evaluate it in the for loop for the first element:

"select(End_List,G,1)"

This is the function to which it refers to:

function select(End_List,G, num)
   if End_List[num+1][2]== "Nothing" && occursin("comma", G[num+2][2]) 
      End_List[num+1][2] = "COLUMN"
      End_List[num][2]   = "SELECT"
   end
end

my Question:
How do I let the eval function know that there is indeed a Vector called End_List just outside the for-loop it is currenlty in?

I have though long about rewriting my whole code but:

  1. I am unsure if this is possible.
  2. as far as I can tell eval is specifically made to deal with these types of situations. So I now kinda want to know what I am doing wrong.

Thanks in advance.

eval works at global scope: Essentials · The Julia Language

so what does that mean for my specific usecase? I don’t want to declare Global variable because its not a clean solution. Is there another type of evaluation I can do that I can use in my specific case?

It is often better to not use eval, but instead generate the code that has the desired effect when being executed as a whole.
Must admit that I do not really understand your use case/example, but maybe something like this could work:

julia> a = 10
10

julia> function foo(s)
           x = split(s, " ")
           y = :([1, 2])
           for e in x
               code = :(let end_of_it = $y; $(Meta.parse(e)) end)
               @show eval(code)
           end
       end
foo (generic function with 1 method)

julia> foo("a end_of_it")
eval(code) = 10
eval(code) = [1, 2]