From 9510ba70ac3aeb295279456963958ccab9dd642e Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Tue, 30 Jan 2024 20:29:30 +0800 Subject: [PATCH] feat(c): add support for single-line macro declarations #24 This commit adds support for single-line macro declarations in the C grammar. It modifies the `singleLineMacroDeclaration` rule to allow for multiple expressions separated by commas. It also adds the `macroIdDeclaration` rule to handle macro identifiers. Additionally, the commit includes changes to the `CFullIdentListenerTest.kt` file to test the new functionality. --- chapi-ast-c/src/main/antlr/C.g4 | 9 ++++--- .../chapi/ast/cast/CFullIdentListenerTest.kt | 26 +++++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/chapi-ast-c/src/main/antlr/C.g4 b/chapi-ast-c/src/main/antlr/C.g4 index fefd7d29..141535dc 100644 --- a/chapi-ast-c/src/main/antlr/C.g4 +++ b/chapi-ast-c/src/main/antlr/C.g4 @@ -39,15 +39,15 @@ compilationUnit singleLineMacroDeclaration : '#' include (StringLiteral | ('<' includeIdentifier '>' )) #includeDeclaration - | '#' 'define' expression* #defineDeclaration - | '#' macroKeywords expression* #conditionalDeclaration + | '#' macroKeywords expression* (',' (expression | singleLineMacroDeclaration))* #defineDeclaration | Identifier postixCall? ('{' blockItem* '}')? #macroCallBlockDeclaration | Identifier postixCall ';'? #macroFuncCallDeclaration | Identifier #macroDeclaration + | '#' Identifier #macroIdDeclaration ; macroKeywords - : 'if' | 'undef' | 'else' | 'pragma' | 'endif' | 'ifdef' | 'ifndef' | 'elif' + : 'if' | 'undef' | 'else' | 'pragma' | 'endif' | 'ifdef' | 'ifndef' | 'elif' | 'define' ; MultiLineMacro @@ -270,6 +270,7 @@ structDeclarationList structDeclaration // The first two rules have priority order and cannot be simplified to one expression. : specifierQualifierList structDeclaratorList? ';' | staticAssertDeclaration + | singleLineMacroDeclaration ; specifierQualifierList @@ -548,6 +549,8 @@ typeKeywords | 'double' | 'signed' | 'unsigned' + | 'void' + | 'static' ; keywords diff --git a/chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt b/chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt index 346e80c0..1f845776 100644 --- a/chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt +++ b/chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt @@ -8,8 +8,8 @@ internal class CFullIdentListenerTest { @Test fun allGrammarUnderResources() { - val content = this::class.java.getResource("/grammar")!!.toURI() -// val content = "/Users/phodal/Downloads/redis-unstable" +// val content = this::class.java.getResource("/grammar")!!.toURI() + val content = "/Users/phodal/Downloads/redis-unstable" File(content).walkTopDown().forEach { if (it.isFile && (it.extension == "c" || it.extension == "h")) { println("Analyse ${it.path}") @@ -377,6 +377,28 @@ typedef struct { void hello() { va_arg(ap, char *); } + + #include "test/jemalloc_test.h" + #include "jemalloc/internal/mpsc_queue.h" + + mpsc_queue_proto(static); + + #define ERR(e) e, #e + """.trimIndent() + + val codeFile = CAnalyser().analysis(code, "helloworld.c") + assertEquals(codeFile.DataStructures.size, 1) + } + + @Test + fun shouldHandleMacroInStructure() { + val code = """ + struct node_s { + #define NODE_MAGIC 0x9823af7e + uint32_t magic; + heap_link_t link; + uint64_t key; + }; """.trimIndent() val codeFile = CAnalyser().analysis(code, "helloworld.c")