Implement more straightforward line continuation ('\\') behavior

* Allow line continuation in single line comments

  Other languages allow this:

  // this is totally a single \
  line comment

  For example C++, at least GCC, Visual C++. I don't see why it
  should be forbidden.

* Don't insert \a symbols to mark

  Because we now don't need to check if there are '\\' in comments
  we no longer have to mark their positions with '\a' symbols.

* Don't trim leading space after '\\'

  Again, this is how other languages do it and it seems to be more
  intuitive. If you don't want spaces just don't indent your lines.

  new s[] = "see \
  this?"
This commit is contained in:
Zeex 2018-01-03 07:17:09 +06:00
parent 270685b06b
commit c325ca3e02
10 changed files with 66 additions and 50 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
build
.vscode/
.vs
.vscode

View File

@ -1,9 +0,0 @@
cmake_minimum_required(VERSION 2.8.6)
include(CTest)
add_subdirectory(source/compiler)
if(BUILD_TESTING)
enable_testing()
add_subdirectory(tests)
endif()

View File

@ -159,6 +159,13 @@ if(MSVC)
DESTINATION bin)
endif()
# Generate tests (only if enabled, i.e. BUILD_TESTING=ON)
include(CTest)
if(BUILD_TESTING)
enable_testing()
add_subdirectory(tests)
endif()
# Generate a binary package with CPack
set(CPACK_PACKAGE_NAME pawnc)
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})

View File

@ -396,11 +396,8 @@ static void readline(unsigned char *line)
*line='\0'; /* delete line */
cont=FALSE;
} else {
/* check whether to erase leading spaces */
/* check whether to erase leading whitespace after '\\' on next line */
if (cont) {
unsigned char *ptr=line;
while (*ptr<=' ' && *ptr!='\0')
ptr++;
if (ptr!=line)
memmove(line,ptr,strlen((char*)ptr)+1);
} /* if */
@ -417,10 +414,6 @@ static void readline(unsigned char *line)
ptr--; /* skip trailing whitespace */
if (*ptr=='\\') {
cont=TRUE;
/* set '\a' at the position of '\\' to make it possible to check
* for a line continuation in a single line comment (error 49)
*/
*ptr++='\a';
*ptr='\0'; /* erase '\n' (and any trailing whitespace) */
} /* if */
} /* if */
@ -445,7 +438,7 @@ static void readline(unsigned char *line)
*
* Global references: icomment (private to "stripcom")
*/
static void stripcom(unsigned char *line)
static void stripcomment(unsigned char *line)
{
char c;
#if !defined SC_LIGHT
@ -519,8 +512,6 @@ static void stripcom(unsigned char *line)
if (icomment==2)
*line++=' ';
} else if (*line=='/' && *(line+1)=='/'){ /* comment to end of line */
if (strchr((char*)line,'\a')!=NULL)
error(49); /* invalid line continuation */
#if !defined SC_LIGHT
if (*(line+2)=='/' && *(line+3)<=' ') {
/* documentation comment */
@ -1859,8 +1850,8 @@ SC_FUNC void preprocess(void)
return;
do {
readline(pline);
stripcom(pline); /* ??? no need for this when reading back from list file (in the second pass) */
lptr=pline; /* set "line pointer" to start of the parsing buffer */
stripcomment(pline); /* ??? no need for this when reading back from list file (in the second pass) */
lptr=pline; /* set "line pointer" to start of the parsing buffer */
iscommand=command();
if (iscommand!=CMD_NONE)
errorset(sRESET,0); /* reset error flag ("panic mode") on empty line or directive */
@ -1895,10 +1886,6 @@ static const unsigned char *unpackedstring(const unsigned char *lptr,int *flags)
while (*lptr==' ' || *lptr=='\t') /* this is as defines with parameters may add them */
lptr++; /* when you use a space after , in a match pattern */
while (*lptr!='\0') {
if (*lptr=='\a') {
lptr++;
continue;
} /* if */
if (!instring) {
if (*lptr=='\"') {
instring=1;
@ -1969,10 +1956,6 @@ static const unsigned char *packedstring(const unsigned char *lptr,int *flags)
i=sizeof(ucell)-(sCHARBITS/8); /* start at most significant byte */
val=0;
while (*lptr!='\0') {
if (*lptr=='\a') { /* ignore '\a' (which was inserted at a line concatenation) */
lptr++;
continue;
} /* if */
if (!instring) {
if (*lptr=='\"') {
instring=1;

View File

@ -0,0 +1,20 @@
set(DEFAULT_COMPILER_OPTIONS
-i${CMAKE_SOURCE_DIR}/include
"-\;+"
"-(+")
function(add_compiler_test test_name options)
add_test(NAME ${test_name}
COMMAND $<TARGET_FILE:pawncc> ${DEFAULT_COMPILER_OPTIONS} ${options})
set_tests_properties(${test_name} PROPERTIES
ENVIRONMENT PATH=$<TARGET_FILE_DIR:pawnc>)
endfunction()
add_compiler_test(gh_217 ${CMAKE_CURRENT_SOURCE_DIR}/gh_217.pwn)
set_tests_properties(gh_217 PROPERTIES PASS_REGULAR_EXPRESSION
".*: warning 237: user warning: this is warning 1[\r\n]+\
.*: warning 237: user warning: this iswarning 2[\r\n]+\
.*: warning 237: user warning: this is warning 3[\r\n]+\
.*: warning 237: user warning: this is warning 4[\r\n]+\
.*: warning 234: function is deprecated \\(symbol \"f\"\\) don't use this functionplease[\r\n]+\
.*: warning 234: function is deprecated \\(symbol \"f\"\\) don't use this functionplease")

Binary file not shown.

View File

@ -0,0 +1,33 @@
// TODO: Check that string literals are concatenated correctly
native print(const s[]);
#define d1\
print("ok")
#define d2 \
print("ok")
#warning this is\
warning 1
#warning this is\
warning 2
#warning this is \
warning 3
#warning this is \
warning 4
// single-line comments can span \
multiple lines if you really want it
#pragma deprecated don't\
use \
this \
function\
please
f() {}
main() {
d1;
d2;
f();
}

View File

@ -1,13 +0,0 @@
set(DEFAULT_COMPILER_OPTIONS
-i${CMAKE_SOURCE_DIR}/include
"-\;+"
"-(+")
function(add_compiler_test test_name options)
add_test(NAME ${test_name}
COMMAND $<TARGET_FILE:pawncc> ${DEFAULT_COMPILER_OPTIONS} ${options})
set_tests_properties(${test_name} PROPERTIES
ENVIRONMENT PATH=$<TARGET_FILE_DIR:pawnc>)
endfunction()
add_subdirectory(compiler)

View File

@ -1 +0,0 @@
add_compiler_test(main ${CMAKE_CURRENT_SOURCE_DIR}/main.pwn)

View File

@ -1,5 +0,0 @@
#include <console>
main() {
print("Hello World!");
}