@@ -44,12 +44,8 @@ Tokenizer.EOF_TOKEN = {
4444 source = " <EOF>" ,
4545}
4646
47- local function getPosition (source , i )
48- return source :sub (1 , i ):gsub (" [^\n ]" , " " ):len () + 1 , i - source :sub (1 , i ):gsub (" [^\r ]" , " " ):len () + 1 ;
49- end
50-
5147local function token (self , startPos , kind , value )
52- local line , linePos = getPosition (self . source , self .index );
48+ local line , linePos = self : getPosition (self .index );
5349 local annotations = self .annotations
5450 self .annotations = {};
5551 return {
@@ -65,14 +61,45 @@ local function token(self, startPos, kind, value)
6561end
6662
6763local function generateError (self , message )
68- local line , linePos = getPosition (self . source , self .index );
64+ local line , linePos = self : getPosition (self .index );
6965 return " Lexing Error at Position " .. tostring (line ) .. " :" .. tostring (linePos ) .. " , " .. message ;
7066end
7167
7268local function generateWarning (token , message )
7369 return " Warning at Position " .. tostring (token .line ) .. " :" .. tostring (token .linePos ) .. " , " .. message ;
7470end
7571
72+ function Tokenizer :getPosition (i )
73+ local column = self .columnMap [i ]
74+
75+ if not column then -- // `i` is bigger than self.length, this shouldnt happen, but it did. (Theres probably some error in the tokenizer, cant find it.)
76+ column = self .columnMap [# self .columnMap ]
77+ end
78+
79+ return column .id , column .charMap [i ]
80+ end
81+
82+ -- // Prepare columnMap for getPosition
83+ function Tokenizer :prepareGetPosition ()
84+ local columnMap , column = {}, { charMap = {}, id = 1 , length = 0 }
85+
86+ for index = 1 , self .length do
87+ local character = string.sub (self .source , index , index ) -- NOTE_1: this could use table.clone to reduce amount of NEWTABLE (if that causes any performance issues)
88+
89+ local columnLength = column .length + 1
90+ column .length = columnLength
91+ column .charMap [index ] = columnLength
92+
93+ if character == " \n " then
94+ column = { charMap = {}, id = column .id + 1 , length = 0 } -- NOTE_1
95+ end
96+
97+ columnMap [index ] = column
98+ end
99+
100+ self .columnMap = columnMap
101+ end
102+
76103-- Constructor for Tokenizer
77104function Tokenizer :new (settings )
78105 local luaVersion = (settings and (settings .luaVersion or settings .LuaVersion )) or LuaVersion .LuaU ;
@@ -132,12 +159,14 @@ function Tokenizer:reset()
132159 self .length = 0 ;
133160 self .source = " " ;
134161 self .annotations = {};
162+ self .columnMap = {};
135163end
136164
137165-- Append String to this Tokenizer
138166function Tokenizer :append (code )
139167 self .source = self .source .. code
140168 self .length = self .length + code :len ();
169+ self :prepareGetPosition ();
141170end
142171
143172-- Function to peek the n'th char in the source of the tokenizer
0 commit comments