Skip to content

Commit ee4e5f3

Browse files
committed
refactor(c): try for jcpp
1 parent cd59c58 commit ee4e5f3

File tree

7 files changed

+79
-26
lines changed

7 files changed

+79
-26
lines changed

chapi-ast-c/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ dependencies {
2525
// Kotlin reflection.
2626
testImplementation(kotlin("test"))
2727

28+
// https://mvnrepository.com/artifact/org.anarres/jcpp
29+
2830
// JUnit 5
2931
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
3032
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
@@ -35,6 +37,7 @@ dependencies {
3537

3638
// coroutines
3739
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0-RC2")
40+
testImplementation("org.anarres:jcpp:1.4.14")
3841
}
3942

4043
sourceSets.main {

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

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ DELIMITED_COMMENT: '/*' .*? '*/' -> channel(COMMENTS_CHANNEL);
1212
WHITESPACES: (Whitespace | Newline)+ -> channel(HIDDEN);
1313
SHARP: '#' -> mode(DIRECTIVE_MODE);
1414

15-
//MultiLineMacro: '#' (~[\n]*? '\\' '\r'? '\n')+ ~ [\n]+ -> channel (HIDDEN);
16-
//
15+
//Directive: '#' ~ [\n]* -> channel (HIDDEN);
16+
MultiLineMacro: '#' (~[\n]*? '\\' '\r'? '\n')+ ~ [\n]+ -> channel (HIDDEN);
17+
1718
Auto : 'auto' ;
1819
Break : 'break' ;
1920
Case : 'case' ;
@@ -143,12 +144,6 @@ DigitSequence
143144
: Digit+
144145
;
145146

146-
IncludeText
147-
: '<' SChar* ('.' | '/' | SChar)* '>'
148-
| DIRECTIVE_STRING
149-
| CONDITIONAL_SYMBOL
150-
;
151-
152147
STRING
153148
: EncodingPrefix? '"' SCharSequence? '"'
154149
;
@@ -239,7 +234,7 @@ DIRECTIVE_STRING: '"' ~('"' | [\r\n\u0085\u2028\u2029])* '"' -> cha
239234
CONDITIONAL_SYMBOL: Identifier -> channel(DIRECTIVE);
240235
DIRECTIVE_SINGLE_LINE_COMMENT: '//' ~[\r\n\u0085\u2028\u2029]* -> channel(COMMENTS_CHANNEL), type(SINGLE_LINE_COMMENT);
241236
DIRECTIVE_NEW_LINE: Newline -> channel(DIRECTIVE), mode(DEFAULT_MODE);
242-
INCLUDE_TEXT: IncludeText -> channel(DIRECTIVE), type(IncludeText);
237+
INCLUDE_TEXT: ('<' SChar* ('.' | '/' | SChar)* '>' | DIRECTIVE_STRING | CONDITIONAL_SYMBOL) -> channel(DIRECTIVE);
243238

244239
mode DIRECTIVE_TEXT;
245240

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ extensionExpression : Extenion? OPEN_PARENS typeName CLOSE_PARENS LeftBrace init
7272
postixCall
7373
:LeftBracket expression RightBracket #arrayAccessPostfixExpression
7474
// for macro support: ph_gen(, hpdata_age_heap, hpdata_t, age_link, hpdata_age_comp)
75-
| OPEN_PARENS Comma? argumentExpressionList? CLOSE_PARENS #functionCallPostfixExpression
76-
| (Dot | Arrow) Identifier #memberAccessPostfixExpression
75+
| OPEN_PARENS Comma? argumentExpressionList? CLOSE_PARENS #functionCallPostfixExpression
76+
| (Dot | Arrow) Identifier #memberAccessPostfixExpression
7777
;
7878

7979
//macroPostixCall

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ options { tokenVocab=CLexer; superClass=chapi.ast.antlr.CPreprocessorParserBase;
88

99
preprocessor_directive returns [Boolean value]
1010
: DEFINE CONDITIONAL_SYMBOL (Identifier | DIGITS | preprocessor_directive)? directive_new_line_or_sharp { this.OnPreprocessorDirectiveDefine(); } #preprocessorDeclaration
11-
| INCLUDE IncludeText directive_new_line_or_sharp { this.OnPreprocessorDirectiveInclude(); } #preprocessorIncludeDeclaration
11+
| INCLUDE INCLUDE_TEXT directive_new_line_or_sharp { this.OnPreprocessorDirectiveInclude(); } #preprocessorIncludeDeclaration
1212
| UNDEF CONDITIONAL_SYMBOL directive_new_line_or_sharp { this.OnPreprocessorDirectiveUndef(); } #preprocessorDeclaration
1313
| Ifdef CONDITIONAL_SYMBOL directive_new_line_or_sharp { this.OnPreprocessorDirectiveIfdef(); } #preprocessorIfdefConditional
1414
| Ifndef CONDITIONAL_SYMBOL directive_new_line_or_sharp { this.OnPreprocessorDirectiveIfndef(); } #preprocessorIfndefConditional

chapi-ast-c/src/main/java/chapi/ast/antlr/CPreprocessorParserBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ protected Boolean AllConditions() {
2929
protected void OnPreprocessorDirectiveInclude() {
3030
ParserRuleContext c = this._ctx;
3131
CPreprocessorParser.PreprocessorIncludeDeclarationContext d = (CPreprocessorParser.PreprocessorIncludeDeclarationContext) c;
32-
IncludeSymbols.add(d.IncludeText().getText());
32+
IncludeSymbols.add(d.INCLUDE_TEXT().getText());
3333
d.value = AllConditions();
3434
}
3535

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

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import kotlinx.coroutines.flow.asFlow
44
import kotlinx.coroutines.flow.collect
55
import kotlinx.coroutines.flow.mapNotNull
66
import kotlinx.coroutines.runBlocking
7+
import org.anarres.cpp.*
78
import org.junit.jupiter.api.Test
89
import java.io.File
9-
import kotlin.test.Ignore
1010
import kotlin.test.assertEquals
1111

12+
1213
internal class CFullIdentListenerTest {
1314

1415
@Test
@@ -338,7 +339,7 @@ typedef struct {
338339
""".trimIndent()
339340

340341
val codeFile = CAnalyser().analysis(code, "helloworld.c")
341-
assertEquals(codeFile.DataStructures.size, 2)
342+
assertEquals(codeFile.DataStructures.size, 1)
342343
assertEquals(codeFile.DataStructures[0].Functions.size, 1)
343344
}
344345

@@ -392,7 +393,7 @@ typedef struct {
392393
""".trimIndent()
393394

394395
val codeFile = CAnalyser().analysis(code, "helloworld.c")
395-
assertEquals(codeFile.DataStructures.size, 0)
396+
assertEquals(codeFile.DataStructures.size, 1)
396397
}
397398

398399
@Test
@@ -664,4 +665,58 @@ typedef struct {
664665
val codeFile = CAnalyser().analysis(code, "helloworld.c")
665666
assertEquals(codeFile.DataStructures.size, 0)
666667
}
668+
669+
670+
@Test
671+
fun shouldPreprocessorHandleMacroCall() {
672+
val code = """
673+
#ifndef HDR_TESTS_H
674+
#define HDR_TESTS_H
675+
676+
/* These are functions used in tests and are not intended for normal usage. */
677+
678+
#include "hdr_histogram.h"
679+
680+
#ifdef __cplusplus
681+
extern "C" {
682+
#endif
683+
684+
int32_t counts_index_for(const struct hdr_histogram* h, int64_t value);
685+
int hdr_encode_compressed(struct hdr_histogram* h, uint8_t** compressed_histogram, size_t* compressed_len);
686+
int hdr_decode_compressed(uint8_t* buffer, size_t length, struct hdr_histogram** histogram);
687+
void hdr_base64_decode_block(const char* input, uint8_t* output);
688+
void hdr_base64_encode_block(const uint8_t* input, char* output);
689+
690+
#ifdef __cplusplus
691+
}
692+
#endif
693+
694+
#endif
695+
""".trimIndent()
696+
697+
val pp = Preprocessor()
698+
pp.addInput(StringLexerSource(code))
699+
pp.addFeature(Feature.DIGRAPHS);
700+
pp.addFeature(Feature.TRIGRAPHS);
701+
pp.addFeature(Feature.LINEMARKERS);
702+
pp.addWarning(Warning.IMPORT);
703+
704+
pp.listener = DefaultPreprocessorListener()
705+
706+
try {
707+
while (true) {
708+
val tok = pp.token()
709+
println(tok.type)
710+
if (tok.type == Token.EOF) break
711+
print(tok.text)
712+
}
713+
} catch (e: Exception) {
714+
val buf = StringBuilder("Preprocessor failed:\n")
715+
println(e)
716+
}
717+
718+
719+
}
720+
667721
}
722+
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
int main()
2-
{
3-
int i, sum = 0;
4-
5-
for ( i = 1; i <= LAST; i++ ) {
6-
sum += i;
7-
} /*-for-*/
8-
printf("sum = %d\n", sum);
1+
int main()
2+
{
3+
int i, sum = 0;
94

10-
return 0;
11-
}
5+
for ( i = 1; i <= LAST; i++ ) {
6+
sum += i;
7+
} /*-for-*/
8+
printf("sum = %d\n", sum);
9+
10+
return 0;
11+
}
1212

0 commit comments

Comments
 (0)