@@ -213,6 +213,7 @@ local F, tryToFormatError
213213local getFileContents , fileExists
214214local getLineNumber
215215local getNextUsableToken
216+ local getRelativeLocationText
216217local insertTokenRepresentations
217218local isAny
218219local isToken , isTokenAndNotNil
@@ -535,9 +536,9 @@ function _tokenize(s, path, allowMetaTokens, allowBacktickStrings, allowJitSynta
535536
536537 if tok .long then
537538 -- Check for nesting of [[...]], which is depricated in Lua.
538- local mainChunk , err = loadLuaString (" --" .. tok .representation , " " )
539+ local mainChunk , err = loadLuaString (" --" .. tok .representation , " @ " )
539540 if not mainChunk then
540- local lnInString , _err = err :match ' ^%[string ""%] :(%d+): (.*)'
541+ local lnInString , _err = err :match ' ^:(%d+): (.*)'
541542 if not _err then
542543 return nil , errorInFile (s , path , reprStart , " Tokenizer" , " Malformed long comment." )
543544 end
@@ -619,9 +620,9 @@ function _tokenize(s, path, allowMetaTokens, allowBacktickStrings, allowJitSynta
619620 end
620621
621622 -- Check for nesting of [[...]], which is depricated in Lua.
622- local valueChunk , err = loadLuaString (" return" .. tok .representation , " " )
623+ local valueChunk , err = loadLuaString (" return" .. tok .representation , " @ " )
623624 if not valueChunk then
624- local lnInString , _err = err :match ' ^%[string ""%] :(%d+): (.*)'
625+ local lnInString , _err = err :match ' ^:(%d+): (.*)'
625626 if not _err then
626627 return nil , errorInFile (s , path , reprStart , " Tokenizer" , " Malformed long string." )
627628 end
@@ -1092,6 +1093,20 @@ end
10921093
10931094
10941095
1096+ -- getRelativeLocationText( tokenOfInterest, otherToken )
1097+ -- getRelativeLocationText( tokenOfInterest, otherFilename, otherLineNumber )
1098+ function getRelativeLocationText (tokOfInterest , otherFilename , otherLn )
1099+ if type (otherFilename ) == " table" then
1100+ return getRelativeLocationText (tokOfInterest , otherFilename .file , otherFilename .line )
1101+ end
1102+
1103+ if tokOfInterest .file ~= otherFilename then return F (" at %s:%d" , tokOfInterest .file , tokOfInterest .line ) end
1104+ if tokOfInterest .line ~= otherLn then return F (" on line %d" , tokOfInterest .line ) end
1105+ return " on the same line"
1106+ end
1107+
1108+
1109+
10951110-- ==============================================================
10961111-- = Preprocessor Functions =====================================
10971112-- ==============================================================
@@ -1712,28 +1727,30 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
17121727 local bracketDepth = 1
17131728
17141729 while true do
1715- if not tokenStack [1 ] then
1730+ tok = tokenStack [# tokenStack ]
1731+
1732+ if not tok then
17161733 errorAtToken (fileBuffers , tableStartTok , nil , " Macro" , " Syntax error: Could not find end of table constructor before EOF." )
17171734
17181735 -- @Copypaste from above. @Cleanup
1719- elseif isLastToken ( tokenStack , " pp_keyword" , " file" ) then
1736+ elseif isToken ( tok , " pp_keyword" , " file" ) then
17201737 local ppKwTokInner = table.remove (tokenStack ) -- "@file"
17211738 table.insert (argTokens , newTokenAt ({type = " string" , value = ppKwTokInner .file , representation = F (" %q" ,ppKwTokInner .file )}, ppKwTokInner ))
1722- elseif isLastToken ( tokenStack , " pp_keyword" , " line" ) then
1739+ elseif isToken ( tok , " pp_keyword" , " line" ) then
17231740 local ppKwTokInner = table.remove (tokenStack ) -- "@line"
17241741 table.insert (argTokens , newTokenAt ({type = " number" , value = ppKwTokInner .line , representation = F (" %d" ,ppKwTokInner .line )}, ppKwTokInner ))
17251742
1726- elseif tokenStack [ # tokenStack ] .type :find " ^pp_" then
1727- errorAtToken (fileBuffers , tokenStack [ # tokenStack ] , nil , " Macro" , " Preprocessor code not supported in macros." )
1743+ elseif tok .type :find " ^pp_" then
1744+ errorAtToken (fileBuffers , tok , nil , " Macro" , " Preprocessor code not supported in macros. (Macro starting %s) " , getRelativeLocationText ( ppKeywordTok , tok ) )
17281745
1729- elseif bracketDepth == 1 and isLastToken ( tokenStack , " punctuation" , " }" ) then
1746+ elseif bracketDepth == 1 and isToken ( tok , " punctuation" , " }" ) then
17301747 table.insert (argTokens , table.remove (tokenStack ))
17311748 break
17321749
17331750 else
1734- if isLastToken ( tokenStack , " punctuation" , " {" ) then
1751+ if isToken ( tok , " punctuation" , " {" ) then
17351752 bracketDepth = bracketDepth + 1
1736- elseif isLastToken ( tokenStack , " punctuation" , " }" ) then
1753+ elseif isToken ( tok , " punctuation" , " }" ) then
17371754 bracketDepth = bracketDepth - 1
17381755 end
17391756 table.insert (argTokens , table.remove (tokenStack ))
@@ -1791,37 +1808,62 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
17911808 for argNum = 1 , 1 / 0 do
17921809 local argStartTok = tokenStack [# tokenStack ]
17931810 local argTokens = {}
1794- local parensDepth = 0
1811+ local depthStack = {}
17951812 popUseless (tokenStack )
17961813
17971814 -- Collect tokens for this arg.
17981815 while true do
1799- if not tokenStack [1 ] then
1816+ tok = tokenStack [# tokenStack ]
1817+
1818+ if not tok then
18001819 errorAtToken (fileBuffers , parensStartTok , nil , " Macro" , " Syntax error: Could not find end of argument list before EOF." )
18011820
18021821 -- @Copypaste from above. @Cleanup
1803- elseif isLastToken ( tokenStack , " pp_keyword" , " file" ) then
1822+ elseif isToken ( tok , " pp_keyword" , " file" ) then
18041823 local ppKwTokInner = table.remove (tokenStack ) -- "@file"
18051824 table.insert (argTokens , newTokenAt ({type = " string" , value = ppKwTokInner .file , representation = F (" %q" ,ppKwTokInner .file )}, ppKwTokInner ))
1806- elseif isLastToken ( tokenStack , " pp_keyword" , " line" ) then
1825+ elseif isToken ( tok , " pp_keyword" , " line" ) then
18071826 local ppKwTokInner = table.remove (tokenStack ) -- "@line"
18081827 table.insert (argTokens , newTokenAt ({type = " number" , value = ppKwTokInner .line , representation = F (" %d" ,ppKwTokInner .line )}, ppKwTokInner ))
18091828
1810- elseif tokenStack [ # tokenStack ] .type :find " ^pp_" then
1811- errorAtToken (fileBuffers , tokenStack [ # tokenStack ] , nil , " Macro" , " Preprocessor code not supported in macros." )
1829+ elseif tok .type :find " ^pp_" then
1830+ errorAtToken (fileBuffers , tok , nil , " Macro" , " Preprocessor code not supported in macros. (Macro starting %s) " , getRelativeLocationText ( ppKeywordTok , tok ) )
18121831
1813- elseif parensDepth == 0 and isLastToken (tokenStack , " punctuation" , " ," ) then
1814- break
1815-
1816- elseif parensDepth == 0 and isLastToken (tokenStack , " punctuation" , " )" ) then
1832+ elseif not depthStack [1 ] and (isToken (tok , " punctuation" , " ," ) or isToken (tok , " punctuation" , " )" )) then
18171833 break
18181834
18191835 else
1820- if isLastToken (tokenStack , " punctuation" , " (" ) then
1821- parensDepth = parensDepth + 1
1822- elseif isLastToken (tokenStack , " punctuation" , " )" ) then
1823- parensDepth = parensDepth - 1
1836+ if isToken (tok , " punctuation" , " (" ) then
1837+ table.insert (depthStack , {startToken = tok , [1 ]= " punctuation" , [2 ]= " )" })
1838+ elseif isToken (tok , " punctuation" , " [" ) then
1839+ table.insert (depthStack , {startToken = tok , [1 ]= " punctuation" , [2 ]= " ]" })
1840+ elseif isToken (tok , " punctuation" , " {" ) then
1841+ table.insert (depthStack , {startToken = tok , [1 ]= " punctuation" , [2 ]= " }" })
1842+ elseif isToken (tok , " keyword" , " function" ) or isToken (tok , " keyword" , " if" ) or isToken (tok , " keyword" , " do" ) then
1843+ table.insert (depthStack , {startToken = tok , [1 ]= " keyword" , [2 ]= " end" })
1844+ elseif isToken (tok , " keyword" , " repeat" ) then
1845+ table.insert (depthStack , {startToken = tok , [1 ]= " keyword" , [2 ]= " until" })
1846+
1847+ elseif
1848+ isToken (tok , " punctuation" , " )" ) or
1849+ isToken (tok , " punctuation" , " ]" ) or
1850+ isToken (tok , " punctuation" , " }" ) or
1851+ isToken (tok , " keyword" , " end" ) or
1852+ isToken (tok , " keyword" , " until" )
1853+ then
1854+ if not depthStack [1 ] then
1855+ errorAtToken (fileBuffers , tok , nil , " Macro" , " Unexpected '%s'." , tok .value )
1856+ elseif not isToken (tok , unpack (depthStack [# depthStack ])) then
1857+ local startTok = depthStack [# depthStack ].startToken
1858+ errorAtToken (
1859+ fileBuffers , tok , nil , " Macro" ,
1860+ " Expected '%s' (to end '%s' %s) but got '%s'." ,
1861+ depthStack [# depthStack ][2 ], startTok .value , getRelativeLocationText (startTok , tok ), tok .value
1862+ )
1863+ end
1864+ table.remove (depthStack )
18241865 end
1866+
18251867 table.insert (argTokens , table.remove (tokenStack ))
18261868 end
18271869 end
@@ -1837,7 +1879,7 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
18371879 end
18381880 local argStr = table.concat (parts )
18391881
1840- local chunk , err = loadLuaString (" return " .. argStr , " @" )
1882+ local chunk , err = loadLuaString (" return ( " .. argStr .. " ) " , " @" )
18411883 if not chunk then
18421884 errorAtToken (fileBuffers , argTokens [1 ], nil , " Macro" , " Syntax error: Invalid expression for argument #%d." , argNum )
18431885 -- err = err:gsub("^:%d+: ", "")
@@ -2106,7 +2148,7 @@ local function _processFileOrString(params, isFile)
21062148 end -- outputFinalDualValueStatement()
21072149
21082150 -- Note: Can be multiple lines if extended.
2109- local function processMetaLine (isDual , metaStartFile , metaStartLine )
2151+ local function processMetaLine (isDual , metaStartTok )
21102152 local metaLineIndexStart = tokenIndex
21112153 local bracketBalance = 0
21122154
@@ -2115,20 +2157,11 @@ local function _processFileOrString(params, isFile)
21152157
21162158 if not tok then
21172159 if bracketBalance ~= 0 then
2118- errorAtToken (
2119- fileBuffers , tokens [tokenIndex - 1 ], # fileBuffers [tokens [tokenIndex - 1 ].file ], " Parser" ,
2120- " Unexpected end-of-data. Preprocessor line" .. (
2121- tokens [tokenIndex - 1 ].file == metaStartFile and tokens [tokenIndex - 1 ].line == metaStartLine
2122- and " "
2123- or " (starting at %s:%d)"
2124- ).. " has unbalanced brackets." ,
2125- metaStartFile , metaStartLine
2126- )
2127-
2128- elseif isDual then
2160+ errorAtToken (fileBuffers , metaStartTok , nil , " Parser" , " Preprocessor line has unbalanced brackets. (Reached EOF.)" )
2161+ end
2162+ if isDual then
21292163 outputFinalDualValueStatement (metaLineIndexStart , tokenIndex - 1 )
21302164 end
2131-
21322165 return
21332166 end
21342167
@@ -2169,28 +2202,20 @@ local function _processFileOrString(params, isFile)
21692202 return
21702203
21712204 elseif tokType == " pp_entry" then
2172- errorAtToken (
2173- fileBuffers , tok , nil , " Parser" ,
2174- " Preprocessor token inside metaprogram"
2175- .. (tok .file == metaStartFile and tok .line == metaStartLine and " ." or " (starting at %s:%d)." ),
2176- metaStartFile , metaStartLine
2177- )
2205+ errorAtToken (fileBuffers , tok , nil , " Parser" , " Preprocessor token inside metaprogram (starting %s)." , getRelativeLocationText (metaStartTok , tok ))
21782206
21792207 else
21802208 table.insert (metaParts , tok .representation )
21812209
21822210 if tokType == " punctuation" and isAny (tok .value , " (" ," {" ," [" ) then
2183- bracketBalance = bracketBalance + 1
2211+ bracketBalance = bracketBalance + 1
21842212 elseif tokType == " punctuation" and isAny (tok .value , " )" ," }" ," ]" ) then
2185- bracketBalance = bracketBalance - 1
2186-
2213+ bracketBalance = bracketBalance - 1
21872214 if bracketBalance < 0 then
21882215 errorAtToken (
21892216 fileBuffers , tok , nil , " Parser" ,
2190- " Unexpected '%s'. Preprocessor line"
2191- .. (tok .file == metaStartFile and tok .line == metaStartLine and " " or " (starting at %s:%d)" )
2192- .. " has unbalanced brackets." ,
2193- tok .value , metaStartFile , metaStartLine
2217+ " Unexpected '%s'. Preprocessor line (starting %s) has unbalanced brackets." ,
2218+ tok .value , getRelativeLocationText (metaStartTok , tok )
21942219 )
21952220 end
21962221 end
@@ -2239,16 +2264,7 @@ local function _processFileOrString(params, isFile)
22392264 if depth == 0 then break end
22402265
22412266 elseif tokType == " pp_entry" then
2242- errorAtToken (
2243- fileBuffers , tok , nil , " Parser" ,
2244- " Preprocessor token inside metaprogram" .. (
2245- tok .file == startToken .file and tok .line == startToken .line
2246- and " ."
2247- or " (starting at %s:%d)."
2248- ),
2249- startToken .file ,
2250- startToken .line
2251- )
2267+ errorAtToken (fileBuffers , tok , nil , " Parser" , " Preprocessor token inside metaprogram (starting %s)." , getRelativeLocationText (startToken , tok ))
22522268 end
22532269
22542270 table.insert (tokensInBlock , tok )
@@ -2293,7 +2309,7 @@ local function _processFileOrString(params, isFile)
22932309 flushTokensToProcess ()
22942310
22952311 tokenIndex = tokenIndex + 1
2296- processMetaLine (tok .double , tok . file , tok . line )
2312+ processMetaLine (tok .double , tok )
22972313
22982314 -- Non-meta.
22992315 ---- ----------------------------
0 commit comments