Last active
May 15, 2018 21:25
-
-
Save McMartin/5c0b3853fd8dddbd78d2adededbd67e9 to your computer and use it in GitHub Desktop.
A CMake script that reads itself and emits tokens
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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