9696 -- Preprocessor inline block. (Expression that returns a value.)
9797 local text = !("The dog said: "..getDogText())
9898
99- -- Preprocessor inline block variant. (Expression that returns a Lua string.)
99+ -- Preprocessor inline block variant. (Expression that returns a Lua code string.)
100100 _G.!!("myRandomGlobal"..math.random(5)) = 99
101101
102102 -- Dual code (both preprocessor line and final output).
@@ -420,7 +420,9 @@ local NUM_DEC_FRAC = ("^( %d* %.%d+
420420local NUM_DEC_EXP = (" ^( %d+ %.? [Ee][-+]?%d+ )" ):gsub (" +" , " " )
421421local NUM_DEC = (" ^( %d+ %.? )" ):gsub (" +" , " " )
422422
423- function _tokenize (s , path , allowMetaTokens , allowBacktickStrings , allowJitSyntax )
423+ -- tokens = _tokenize( luaString, path, allowPreprocessorTokens, allowBacktickStrings, allowJitSyntax )
424+ -- Returns nil and a message on error.
425+ function _tokenize (s , path , allowPpTokens , allowBacktickStrings , allowJitSyntax )
424426 local tokens = {}
425427 local ptr = 1
426428 local ln = 1
@@ -636,14 +638,16 @@ function _tokenize(s, path, allowMetaTokens, allowBacktickStrings, allowJitSynta
636638 tok .value = v
637639
638640 -- Backtick string.
639- elseif allowBacktickStrings and s :find (" ^`" , ptr ) then
640- local i1 , i2 , v = s :find (" ^`([^`]*)`" , ptr )
641+ elseif s :find (" ^`" , ptr ) then
642+ if not allowBacktickStrings then
643+ return nil , errorInFile (s , path , ptr , " Tokenizer" , " Encountered backtick string. (Feature not enabled.)" )
644+ end
645+
646+ local i1 , i2 , repr , v = s :find (" ^(`([^`]*)`)" , ptr )
641647 if not i2 then
642648 return nil , errorInFile (s , path , ptr , " Tokenizer" , " Unfinished backtick string." )
643649 end
644650
645- local repr = F (" %q" , v )
646-
647651 ptr = i2 + 1
648652 tok = {type = " string" , representation = repr , value = v , long = false }
649653
@@ -661,15 +665,24 @@ function _tokenize(s, path, allowMetaTokens, allowBacktickStrings, allowJitSynta
661665 tok = {type = " punctuation" , representation = repr , value = repr }
662666 ptr = ptr +# repr
663667
664- -- Preprocessor: Entry.
665- elseif allowMetaTokens and s :find (" ^!" , ptr ) then
668+ -- Preprocessor entry.
669+ elseif s :find (" ^!" , ptr ) then
670+ if not allowPpTokens then
671+ return nil , errorInFile (s , path , ptr , " Tokenizer" , " Encountered preprocessor entry. (Feature not enabled.)" )
672+ end
673+
666674 local double = s :find (" ^!" , ptr + 1 ) ~= nil
667675 local repr = s :sub (ptr , ptr + (double and 1 or 0 ))
676+
668677 tok = {type = " pp_entry" , representation = repr , value = repr , double = double }
669678 ptr = ptr +# repr
670679
671- -- Preprocessor: Keyword.
672- elseif allowMetaTokens and s :find (" ^@" , ptr ) then
680+ -- Preprocessor keyword.
681+ elseif s :find (" ^@" , ptr ) then
682+ if not allowPpTokens then
683+ return nil , errorInFile (s , path , ptr , " Tokenizer" , " Encountered preprocessor keyword. (Feature not enabled.)" )
684+ end
685+
673686 if s :find (" ^@@" , ptr ) then
674687 ptr = ptr + 2
675688 tok = {type = " pp_keyword" , representation = " @@" , value = " insert" }
@@ -1282,15 +1295,15 @@ end
12821295
12831296-- tokenize()
12841297-- Convert Lua code to tokens. Returns nil and a message on error. (See newToken() for token types.)
1285- -- tokens, error = tokenize( luaString [, allowPreprocessorTokens =false ] )
1298+ -- tokens, error = tokenize( luaString [, allowPreprocessorCode =false ] )
12861299-- token = {
12871300-- type=tokenType, representation=representation, value=value,
12881301-- line=lineNumber, lineEnd=lineNumber, position=bytePosition, file=filePath,
12891302-- ...
12901303-- }
1291- function metaFuncs .tokenize (lua , allowMetaTokens )
1304+ function metaFuncs .tokenize (lua , allowPpCode )
12921305 pushErrorHandler (NOOP )
1293- local tokens , err = _tokenize (lua , " <string>" , allowMetaTokens , allowMetaTokens , true ) -- @Incomplete: Make allowJitSyntax a parameter to tokenize()?
1306+ local tokens , err = _tokenize (lua , " <string>" , allowPpCode , allowPpCode , true ) -- @Incomplete: Make allowJitSyntax a parameter to tokenize()?
12941307 popErrorHandler ()
12951308 return tokens , err
12961309end
@@ -1591,7 +1604,7 @@ local function newTokenAt(tok, locationTok)
15911604 return tok
15921605end
15931606
1594- local function processKeywords (tokensRaw , fileBuffers , params , stats )
1607+ local function doExpansions (tokensRaw , fileBuffers , params , stats )
15951608 if not stats .hasPreprocessorCode then
15961609 return tokensRaw
15971610 end
@@ -1607,6 +1620,7 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
16071620 while tokenStack [1 ] do
16081621 local tok = tokenStack [# tokenStack ]
16091622
1623+ -- Keyword.
16101624 if isToken (tok , " pp_keyword" ) then
16111625 local ppKeywordTok = tok
16121626
@@ -1922,6 +1936,14 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
19221936 errorAtToken (fileBuffers , ppKeywordTok , ppKeywordTok .position + 1 , " Parser" , " Unknown preprocessor keyword '%s'." , ppKeywordTok .value )
19231937 end
19241938
1939+ -- Backtick string.
1940+ elseif isToken (tok , " string" ) and tok .representation :find " ^`" then
1941+ tok .representation = F (" %q" , tok .value )
1942+
1943+ table.insert (tokens , tok )
1944+ table.remove (tokenStack )
1945+
1946+ -- Anything else.
19251947 else
19261948 table.insert (tokens , tok )
19271949 table.remove (tokenStack )
@@ -1981,17 +2003,22 @@ local function _processFileOrString(params, isFile)
19812003 lineCountCode = getLineCountWithCode (tokensRaw ),
19822004 tokenCount = 0 , -- Set later.
19832005 hasPreprocessorCode = false ,
2006+ hasMetaprogram = false ,
19842007 insertedNames = {},
19852008 }
19862009
19872010 for _ , tok in ipairs (tokensRaw ) do
1988- if isToken (tok , " pp_entry" ) or isToken (tok , " pp_keyword" ) then
2011+ if isToken (tok , " pp_entry" ) or isToken (tok , " pp_keyword" , " insert " ) then
19892012 stats .hasPreprocessorCode = true
2013+ stats .hasMetaprogram = true
19902014 break
2015+ elseif isToken (tok , " pp_keyword" ) or (isToken (tok , " string" ) and tok .representation :find " ^`" ) then
2016+ stats .hasPreprocessorCode = true
2017+ -- Keep going as there may be metaprogram.
19912018 end
19922019 end
19932020
1994- local tokens = processKeywords (tokensRaw , fileBuffers , params , stats ) -- Tokens for constructing the metaprogram.
2021+ local tokens = doExpansions (tokensRaw , fileBuffers , params , stats ) -- Tokens for constructing the metaprogram.
19952022 stats .tokenCount = # tokens
19962023
19972024 -- Generate metaprogram.
@@ -2413,6 +2440,7 @@ local function _processFileOrString(params, isFile)
24132440 linesOfCode = stats .lineCountCode ,
24142441 tokenCount = stats .tokenCount ,
24152442 hasPreprocessorCode = stats .hasPreprocessorCode ,
2443+ hasMetaprogram = stats .hasMetaprogram ,
24162444 insertedFiles = stats .insertedNames ,
24172445 }
24182446
@@ -2531,7 +2559,7 @@ local pp = {
25312559 -- jitSyntax = boolean -- [Optional] Allow LuaJIT-specific syntax. (Default: false)
25322560 -- validate = boolean -- [Optional] Validate output. (Default: true)
25332561 --
2534- -- onInsert = function( name ) -- [Optional] Called for each @insert"name" statement. It's expected to return a Lua string. By default 'name' is a path to a file to be inserted.
2562+ -- onInsert = function( name ) -- [Optional] Called for each @insert"name" statement. It's expected to return a Lua code string. By default 'name' is a path to a file to be inserted.
25352563 -- onBeforeMeta = function( ) -- [Optional] Called before the metaprogram runs.
25362564 -- onAfterMeta = function( luaString ) -- [Optional] Here you can modify and return the Lua code before it's written to 'pathOut'.
25372565 -- onError = function( error ) -- [Optional] You can use this to get traceback information. 'error' is the same value as what is returned from processFile().
@@ -2556,7 +2584,7 @@ local pp = {
25562584 -- jitSyntax = boolean -- [Optional] Allow LuaJIT-specific syntax. (Default: false)
25572585 -- validate = boolean -- [Optional] Validate output. (Default: true)
25582586 --
2559- -- onInsert = function( name ) -- [Optional] Called for each @insert"name" statement. It's expected to return a Lua string. By default 'name' is a path to a file to be inserted.
2587+ -- onInsert = function( name ) -- [Optional] Called for each @insert"name" statement. It's expected to return a Lua code string. By default 'name' is a path to a file to be inserted.
25602588 -- onBeforeMeta = function( ) -- [Optional] Called before the metaprogram runs.
25612589 -- onError = function( error ) -- [Optional] You can use this to get traceback information. 'error' is the same value as the second returned value from processString().
25622590 --
0 commit comments