Skip to content

Instantly share code, notes, and snippets.

@McMartin
Last active May 15, 2018 21:25
Show Gist options
  • Save McMartin/5c0b3853fd8dddbd78d2adededbd67e9 to your computer and use it in GitHub Desktop.
Save McMartin/5c0b3853fd8dddbd78d2adededbd67e9 to your computer and use it in GitHub Desktop.
A CMake script that reads itself and emits tokens
cmake_policy(VERSION ${CMAKE_VERSION})
function(print_token type text line column)
if(column LESS 10)
set(column "0${column}")
endif()
string(REGEX REPLACE "\n" "\\\\n" text "${text}")
string(LENGTH "${type}" type_len)
set(padded_type "${type}")
foreach(i RANGE ${type_len} 18)
string(APPEND padded_type " ")
endforeach()
message(STATUS "${line},${column}: ${padded_type}'${text}'")
endfunction()
function(tokenize filename)
set(line 1)
set(column 1)
macro(emit_token_and_advance type)
set(text "${CMAKE_MATCH_0}")
print_token("${type}" "${text}" "${line}" "${column}")
string(LENGTH "${text}" length)
string(FIND "${text}" "\n" newline_index)
if(newline_index EQUAL -1)
math(EXPR column "${column} + ${length}")
else()
math(EXPR column "${length} - ${newline_index}")
math(EXPR line "${line} + 1")
endif()
string(SUBSTRING "${content}" ${length} -1 content)
endmacro()
file(READ "${filename}" content)
while(NOT content STREQUAL "")
if(content MATCHES "^[ ]+")
emit_token_and_advance(SPACE)
endif()
if(content MATCHES "^[a-z_]+")
emit_token_and_advance(IDENTIFIER)
if(NOT content MATCHES "^\\(")
message(FATAL_ERROR "(${line},${column}) Expected '('.")
endif()
emit_token_and_advance(LPAREN)
while(1)
if(content MATCHES "^[ ]+")
emit_token_and_advance(SPACE)
elseif(content MATCHES "^\"([\\].|[^\n\"\\])*\"")
emit_token_and_advance(QUOTED_ARGUMENT)
elseif(content MATCHES "^[^ \n()\"]+")
emit_token_and_advance(UNQUOTED_ARGUMENT)
else()
break()
endif()
endwhile()
if(NOT content MATCHES "^\\)")
message(FATAL_ERROR "(${line},${column}) Expected ')'.")
endif()
emit_token_and_advance(RPAREN)
endif()
if(NOT content MATCHES "^\n")
message(FATAL_ERROR "(${line},${column}) Expected newline.")
endif()
emit_token_and_advance(NEWLINE)
endwhile()
endfunction()
if(CMAKE_SCRIPT_MODE_FILE STREQUAL CMAKE_CURRENT_LIST_FILE)
tokenize("${CMAKE_CURRENT_LIST_FILE}")
endif()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment