xaizek / zograscope (License: AGPLv3 only) (since 2018-12-07)
Mainly a syntax-aware diff that also provides a number of additional tools.
Commit 29290ec532fa6e1272e5cd3be45664e381a09acd

Don't highlight $$ as a variable in Make
Because it's an escape sequence.
Author: xaizek
Author date (UTC): 2022-11-22 19:16
Committer name: xaizek
Committer date (UTC): 2022-11-29 19:05
Parent(s): bf77cfd807b87c61cb1cc2c08c1f6587649eee34
Signing key: 99DC5E4DB05F6BE2
Tree: ed0ca9b1539354b176844dbd9926b8fb93afcb13
File Lines added Lines deleted
src/make/MakeLexerData.hpp 4 3
src/make/make-lexer.flex 18 4
tests/make/make-parser.cpp 2 1
File src/make/MakeLexerData.hpp changed (mode: 100644) (index bfd30e2..d7c710f)
... ... struct MakeLexerData : LexerData
31 31 { {
32 32 // Type of nesting. // Type of nesting.
33 33 enum { enum {
34 FunctionNesting, // Function nesting.
35 ArgumentNesting, // Function argument nesting.
34 FunctionNesting, // Function nesting.
35 ArgumentNesting, // Function argument nesting.
36 EvalArgumentNesting, // `$$(...)` inside a call.
36 37 }; };
37 38
38 39 std::size_t offset = 0U; // Byte offset in the input. std::size_t offset = 0U; // Byte offset in the input.
 
... ... struct MakeLexerData : LexerData
51 52 // Whether whitespace token might be needed before the next token. // Whether whitespace token might be needed before the next token.
52 53 bool fakeWSIsNeeded = false; bool fakeWSIsNeeded = false;
53 54 // Keeps track of function nesting (where keywords stop being keywords). // Keeps track of function nesting (where keywords stop being keywords).
54 std::vector<bool> nesting;
55 std::vector<unsigned char> nesting;
55 56
56 57 MakeParseData *pd; // Link to Make-specific state of the parser. MakeParseData *pd; // Link to Make-specific state of the parser.
57 58
File src/make/make-lexer.flex changed (mode: 100644) (index 5e1928a..bf02ee3)
82 82
83 83 using namespace makestypes; using namespace makestypes;
84 84
85 // Convenience definition for token() funciton's argument.
85 // Convenience definition for token() function's argument.
86 86 enum { NeedFakeWS = 1 }; enum { NeedFakeWS = 1 };
87 87
88 88 // Performs additional operations on returning a token. // Performs additional operations on returning a token.
 
... ... NL \n|\r|\r\n
257 257 yyextra->nesting.push_back(MakeLexerData::FunctionNesting); yyextra->nesting.push_back(MakeLexerData::FunctionNesting);
258 258 return token(CALL_PREFIX, yylval, yyextra); return token(CALL_PREFIX, yylval, yyextra);
259 259 } }
260 "$$(" {
261 if (shouldInsertFakeWS(yylval, yyextra)) {
262 return FAKE_TOKEN(WS);
263 }
264 if (!yyextra->nesting.empty()) {
265 yyextra->nesting.push_back(MakeLexerData::EvalArgumentNesting);
266 }
267 return token(CHARS, yylval, yyextra, NeedFakeWS);
268 }
260 269 $. return token(VAR, yylval, yyextra); $. return token(VAR, yylval, yyextra);
261 270 "(" { "(" {
262 271 if (shouldInsertFakeWS(yylval, yyextra)) { if (shouldInsertFakeWS(yylval, yyextra)) {
 
... ... $. return token(VAR, yylval, yyextra);
271 280 if (yyextra->nesting.empty()) { if (yyextra->nesting.empty()) {
272 281 return token(')', yylval, yyextra); return token(')', yylval, yyextra);
273 282 } }
274 if (yyextra->nesting.back() == MakeLexerData::ArgumentNesting) {
275 yyextra->nesting.pop_back();
283
284 int what = yyextra->nesting.back();
285 yyextra->nesting.pop_back();
286
287 if (what == MakeLexerData::ArgumentNesting) {
276 288 return token(')', yylval, yyextra, NeedFakeWS); return token(')', yylval, yyextra, NeedFakeWS);
277 289 } }
278 yyextra->nesting.pop_back();
290 if (what == MakeLexerData::EvalArgumentNesting) {
291 return token(CHARS, yylval, yyextra, NeedFakeWS);
292 }
279 293 return token(CALL_SUFFIX, yylval, yyextra, NeedFakeWS); return token(CALL_SUFFIX, yylval, yyextra, NeedFakeWS);
280 294 } }
281 295 "}" { "}" {
File tests/make/make-parser.cpp changed (mode: 100644) (index e0fdc82..9fe7b1f)
... ... TEST_CASE("Variables are parsed in a Makefile", "[make][parser]")
169 169 CHECK(makeIsParsed("target: )()(")); CHECK(makeIsParsed("target: )()("));
170 170
171 171 Tree tree = parseMake("target: $$($1.name)"); Tree tree = parseMake("target: $$($1.name)");
172 CHECK(findNode(tree, Type::UserTypes, "$$") != nullptr);
173 172 CHECK(findNode(tree, Type::UserTypes, "$1") != nullptr); CHECK(findNode(tree, Type::UserTypes, "$1") != nullptr);
173 // This isn't a variable, it's an escape sequence.
174 CHECK(findNode(tree, Type::UserTypes, "$$") == nullptr);
174 175 } }
175 176
176 177 TEST_CASE("Functions are parsed in a Makefile", "[make][parser]") TEST_CASE("Functions are parsed in a Makefile", "[make][parser]")
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/zograscope

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/zograscope

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master