Skip to content

Commit 6cb14b4

Browse files
committed
feat(c): add support for parsing #include statements #24
This commit adds support for parsing #include statements in C code. It extracts the included file name and adds it to the list of imports in the code container.
1 parent c10a798 commit 6cb14b4

File tree

4 files changed

+54
-51
lines changed

4 files changed

+54
-51
lines changed

chapi-ast-c/src/main/antlr/C.g4

+3-43
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,6 @@ MultiLineMacro
4343
: '#' (~[\n]*? '\\' '\r'? '\n')+ ~ [\n]+ -> channel (HIDDEN)
4444
;
4545

46-
include
47-
: 'include'
48-
;
49-
50-
includeIdentifier
51-
: (Identifier | keywords) ('/' Identifier)* (Dot Identifier)?
52-
;
53-
5446
primaryExpression
5547
: Identifier
5648
| Constant
@@ -486,44 +478,12 @@ asmBody
486478

487479
logicals : logicalOrExpression (',' logicalOrExpression)* ;
488480

489-
//Directive: '#' ~ [\n]* -> channel (HIDDEN);
490-
491481
macroStatement
492-
: '#' singleLineMacroDeclaration*
493-
// : '#' include (StringLiteral | Identifier | ('<' includeIdentifier '>' )) #includeDeclaration
494-
;
495-
496-
singleLineMacroDeclaration
497-
: include (StringLiteral | Identifier | ('<' includeIdentifier '>' )) #includeDeclaration
498-
| ('ifdef' | 'ifndef' | 'if') Identifier statement* ('#' 'else' statement*)? '#' 'endif'
499-
#ifdefDeclaration
500-
| 'define' Identifier defineMacro #defineDeclaration
501-
// | macroKeywords (assignmentExpression)*
502-
// ('#' macroKeywords)? identifierList? #macroDefineDeclaration
503-
| '#'? Identifier #macroCastDeclaration
504-
| macroKeywords macroFunctionExpression? #macroStatementDeclaration
505-
;
506-
507-
defineMacro
508-
: expressionStatement? #macroAssignDeclaration
509-
| postixCall Identifier postixCall #macroAliasDeclaration
510-
| structOrUnionSpecifier #macroStructureDeclaration
511-
;
512-
513-
514-
macroFunctionExpression
515-
: Identifier
516-
| Identifier '(' ( parameterTypeList| (macroType (',' macroType)*) ) ')'
517-
| assignmentExpression
518-
;
519-
520-
macroType
521-
: typeQualifier? (typeKeywords | Identifier | '==' | '!=' | comparator) (Identifier | typeKeywords)* pointer?
522-
| expressionStatement
482+
: PreprocessorBlock #preprocessorDeclaration
523483
;
524484

525-
macroKeywords
526-
: 'if' | 'undef' | 'else' | 'pragma' | 'endif' | 'ifdef' | 'ifndef' | 'elif' | 'define' | 'ifndef' | 'error'
485+
PreprocessorBlock
486+
: '#' ~[\r\n]*
527487
;
528488

529489
labeledStatement

chapi-ast-c/src/main/antlr/Macro.g4

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
grammar Macro;
2+
3+
compilationUnit
4+
: '#'* EOF
5+
;
6+
7+
//singleLineMacroDeclaration
8+
// : include (StringLiteral | Identifier | ('<' includeIdentifier '>' )) #includeDeclaration
9+
// | ('ifdef' | 'ifndef' | 'if') Identifier statement* ('#' 'else' statement*)? '#' 'endif'
10+
// #ifdefDeclaration
11+
// | 'define' Identifier defineMacro #defineDeclaration
12+
//// | macroKeywords (assignmentExpression)*
13+
//// ('#' macroKeywords)? identifierList? #macroDefineDeclaration
14+
// | '#'? Identifier #macroCastDeclaration
15+
// | macroKeywords macroFunctionExpression? #macroStatementDeclaration
16+
// ;
17+
//
18+
//defineMacro
19+
// : expressionStatement? #macroAssignDeclaration
20+
// | postixCall Identifier postixCall #macroAliasDeclaration
21+
// | structOrUnionSpecifier #macroStructureDeclaration
22+
// ;
23+
//
24+
//macroFunctionExpression
25+
// : Identifier
26+
// | Identifier '(' ( parameterTypeList| (macroType (',' macroType)*) ) ')'
27+
// | assignmentExpression
28+
// ;
29+
//macroType
30+
// : typeQualifier? (typeKeywords | Identifier | '==' | '!=' | comparator) (Identifier | typeKeywords)* pointer?
31+
// | expressionStatement
32+
// ;
33+
//
34+
//macroKeywords
35+
// : 'if' | 'undef' | 'else' | 'pragma' | 'endif' | 'ifdef' | 'ifndef' | 'elif' | 'define' | 'ifndef' | 'error'
36+
// ;

chapi-ast-c/src/main/kotlin/chapi/ast/cast/CFullIdentListener.kt

+13-6
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,23 @@ open class CFullIdentListener(fileName: String) : CAstBaseListener() {
1010
private var structMap = mutableMapOf<String, CodeDataStruct>()
1111
private var codeContainer: CodeContainer = CodeContainer(FullName = fileName)
1212

13-
override fun enterIncludeDeclaration(ctx: CParser.IncludeDeclarationContext?) {
14-
val identifier = ctx?.includeIdentifier()
13+
private val importRegex = Regex("""#include\s+(<[^>]+>|\"[^\"]+\")""")
14+
override fun enterPreprocessorDeclaration(ctx: CParser.PreprocessorDeclarationContext?) {
15+
val text = ctx?.text
16+
val matchResult = importRegex.find(text ?: "") ?: return
17+
18+
val value = matchResult.groupValues[1]
19+
.removeSurrounding("\"", "\"")
20+
.removeSurrounding("<", ">")
21+
1522
val imp = CodeImport(
16-
Source = identifier?.text ?: "",
17-
AsName = identifier?.text ?: ""
23+
Source = value,
24+
AsName = value
1825
)
1926

2027
codeContainer.Imports += imp
2128
}
2229

23-
2430
override fun enterDeclaration(ctx: CParser.DeclarationContext?) {
2531
val isTypeDef = ctx?.declarationSpecifier()?.any {
2632
it.storageClassSpecifier()?.Typedef() != null
@@ -205,10 +211,11 @@ open class CFullIdentListener(fileName: String) : CAstBaseListener() {
205211

206212
private fun buildParameters(call: List<CParser.PostixCallContext>): List<CodeProperty> {
207213
return call.mapNotNull { callContext ->
208-
when(callContext) {
214+
when (callContext) {
209215
is CParser.ArrayAccessPostfixExpressionContext -> {
210216
null
211217
}
218+
212219
is CParser.FunctionCallPostfixExpressionContext -> {
213220
callContext.argumentExpressionList()?.assignmentExpression()?.map {
214221
CodeProperty(

chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ typedef struct {
266266
""".trimIndent()
267267

268268
val codeFile = CAnalyser().analysis(code, "helloworld.c")
269-
assertEquals(codeFile.Imports.size, 7)
269+
assertEquals(codeFile.Imports.size, 6)
270270
}
271271

272272
@Test
@@ -627,6 +627,6 @@ typedef struct {
627627
""".trimIndent()
628628

629629
val codeFile = CAnalyser().analysis(code, "helloworld.c")
630-
assertEquals(codeFile.DataStructures.size, 1)
630+
assertEquals(codeFile.DataStructures.size, 0)
631631
}
632632
}

0 commit comments

Comments
 (0)