mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-22 06:29:23 +00:00
Improved handling of spacesfor preprocessor stringize (#). #721
This commit is contained in:
parent
55061923d7
commit
144bdd45f4
@ -349,7 +349,7 @@ public class CPreprocessor implements TokenSource {
|
||||
}
|
||||
if(macro != null) {
|
||||
// Handle parameters
|
||||
List<List<Token>> paramValues = new ArrayList<>();
|
||||
List<LinkedList<Token>> paramValues = new ArrayList<>();
|
||||
if(macro.hasParameters()) {
|
||||
// Parse parameter value list
|
||||
{
|
||||
@ -364,10 +364,9 @@ public class CPreprocessor implements TokenSource {
|
||||
cTokenSource.nextToken();
|
||||
}
|
||||
// Read parameter values
|
||||
List<Token> paramValue = new ArrayList<>();
|
||||
LinkedList<Token> paramValue = new LinkedList<>();
|
||||
int nesting = 1;
|
||||
while(true) {
|
||||
//skipWhitespace(cTokenSource);
|
||||
final Token paramToken = cTokenSource.nextToken();
|
||||
if(paramToken.getType() == KickCLexer.PAR_END && nesting == 1) {
|
||||
// We reached the end of the parameters - add the current param unless it is an empty parameter alone in the list
|
||||
@ -377,7 +376,7 @@ public class CPreprocessor implements TokenSource {
|
||||
} else if(paramToken.getType() == KickCLexer.COMMA && nesting == 1) {
|
||||
// We have reached the next parameter value
|
||||
paramValues.add(paramValue);
|
||||
paramValue = new ArrayList<>();
|
||||
paramValue = new LinkedList<>();
|
||||
} else {
|
||||
// We are reading a parameter value - handle nesting and store it
|
||||
if(paramToken.getType() == KickCLexer.PAR_BEGIN)
|
||||
@ -393,9 +392,9 @@ public class CPreprocessor implements TokenSource {
|
||||
throw new CompileError("Error! Wrong number of macro parameters. Expected " + macro.parameters.size() + " was " + paramValues.size(), macroNameToken);
|
||||
}
|
||||
// Expand parameter values
|
||||
List<List<Token>> expandedParamValues = new ArrayList<>();
|
||||
List<LinkedList<Token>> expandedParamValues = new ArrayList<>();
|
||||
for(List<Token> paramTokens : paramValues) {
|
||||
List<Token> expandedParamValue = new ArrayList<>();
|
||||
LinkedList<Token> expandedParamValue = new LinkedList<>();
|
||||
CPreprocessor subPreprocessor = new CPreprocessor(cParser, new ListTokenSource(paramTokens), new HashMap<>(defines));
|
||||
while(true) {
|
||||
final Token expandedToken = subPreprocessor.nextToken();
|
||||
@ -404,6 +403,11 @@ public class CPreprocessor implements TokenSource {
|
||||
else
|
||||
expandedParamValue.add(expandedToken);
|
||||
}
|
||||
// Remove leading and trailing whitespace in each paramValue
|
||||
if(expandedParamValue.peekFirst().getType() == KickCLexer.WS)
|
||||
expandedParamValue.pollFirst();
|
||||
if(expandedParamValue.peekLast().getType() == KickCLexer.WS)
|
||||
expandedParamValue.pollLast();
|
||||
expandedParamValues.add(expandedParamValue);
|
||||
paramValues = expandedParamValues;
|
||||
}
|
||||
@ -422,21 +426,21 @@ public class CPreprocessor implements TokenSource {
|
||||
}
|
||||
} else if(macroBodyToken.getType() == KickCLexer.TOKEN_STRINGIZE) {
|
||||
final String paramName = macroBodyToken.getText().substring(1);
|
||||
if(!macro.hasParameter(paramName)) throw new CompileError("Expected macro parameter name after '#'", macroBodyToken);
|
||||
if(!macro.hasParameter(paramName))
|
||||
throw new CompileError("Expected macro parameter name after '#'", macroBodyToken);
|
||||
// body token is a parameter name - replace with stringized expanded parameter value
|
||||
final int paramIndex = macro.getParameterIndex(paramName);
|
||||
final List<Token> expandedParamValue = paramValues.get(paramIndex);
|
||||
StringBuilder stringized = new StringBuilder();
|
||||
for(Token expandedParamValueToken : expandedParamValue) {
|
||||
//if(stringized.length()>0) stringized.append(" ");
|
||||
stringized.append(expandedParamValueToken.getText());
|
||||
}
|
||||
CommonToken stringToken = new CommonToken(KickCLexer.STRING);
|
||||
stringToken.setText("\""+stringized.toString()+"\"");
|
||||
stringToken.setText("\"" + stringized.toString() + "\"");
|
||||
stringToken.setChannel(macroBodyToken.getChannel());
|
||||
addTokenToExpandedBody(stringToken, macroNameToken, expandedBody);
|
||||
} else {
|
||||
// body token is a normal token
|
||||
// body token is a normal token
|
||||
addTokenToExpandedBody(macroBodyToken, macroNameToken, expandedBody);
|
||||
}
|
||||
}
|
||||
|
@ -223,14 +223,16 @@ public class TestPreprocessor {
|
||||
public void testStringize() {
|
||||
// A simple define with one stringized parameter
|
||||
assertEquals("str:\"b\";", parse("#define A(a) #a \nA(b);"));
|
||||
// A simple define with one stringized parameter
|
||||
// A spaced stringized parameter
|
||||
assertEquals("str:\"two words\";", parse("#define A(a) #a \nA(two words);"));
|
||||
// A simple define with one spaced stringized parameter
|
||||
assertEquals("str:\" two words \";", parse("#define A(a) #a \nA( two words );"));
|
||||
// A spaced stringized parameter - leading/trailing spaces removed
|
||||
assertEquals("str:\"two words\";", parse("#define A(a) #a \nA( two words );"));
|
||||
// Concatenating string with stringized macro
|
||||
assertEquals("str:\"qwe\"\"asd\";", parse("#define A(a) #a \n \"qwe\" A(asd);"));
|
||||
assertEquals("str:\"qwe\"\"asd\";", parse("#define A(a) #a \n A(qwe) A(asd);"));
|
||||
// Complex concat with a path - from Kernighan&Ritchie
|
||||
assertEquals("str:\"/usr/tmp\"\"%s\";", parse("#define tempfile(dir) #dir \"%s\" \n tempfile(/usr/tmp);"));
|
||||
// Complex stringize example - from https://gcc.gnu.org/onlinedocs/gcc-3.4.6/cpp/Stringification.html
|
||||
assertEquals("str:\"4\";", parse("#define str(s) #s \n #define foo 4 \n str (foo);"));
|
||||
}
|
||||
|
||||
private void assertError(String program, String expectError, boolean expectLineNumber) {
|
||||
|
Loading…
Reference in New Issue
Block a user