Skip to content
Draft
699 changes: 699 additions & 0 deletions c/CLexer.g4

Large diffs are not rendered by default.

699 changes: 73 additions & 626 deletions c/C.g4 → c/CParser.g4

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions c/CSharp/CParserBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using Antlr4.Runtime;
using System.IO;
using System.Linq;
using static System.Net.Mime.MediaTypeNames;

public abstract class CParserBase : Parser
{
SymbolTable _st;
private bool debug = false;
protected CParserBase(ITokenStream input, TextWriter output, TextWriter errorOutput)
: base(input, output, errorOutput)
{
_st = new SymbolTable();
}

public bool IsType()
{
var text = (this.InputStream as CommonTokenStream).LT(1).Text;
if (this.debug) System.Console.Write(text);
var resolved = _st.Resolve(text);
bool result = false;
if (resolved == null)
{
//// C can reference unresolved types if it's a
// pointer.
//var la2 = (this.InputStream as CommonTokenStream).LT(2).Text;
//if (la2 != null && la2 == "*")
// result = true;
//else
result = false;
}
else if (resolved.Classification != TypeClassification.Variable_)
result = true;
else
result = false;
if (this.debug) System.Console.WriteLine(result);
return result;
}

public bool IsNotType()
{
return ! IsType();
}

public void EnterDeclaration()
{
ParserRuleContext context = this.Context;
CParser.DeclarationContext declaration_context = (CParser.DeclarationContext)context;
CParser.DeclarationSpecifiersContext declaration_specifiers = declaration_context.declarationSpecifiers();
CParser.DeclarationSpecifierContext[] declaration_specifier = declaration_specifiers?.declarationSpecifier();
bool is_typedef = declaration_specifier.Where(ds =>
{
return ds.storageClassSpecifier()?.Typedef() != null;
}).Any();

// Declare any typeSpecifiers that declare something.
foreach (var ds in declaration_specifier)
{
var sous = ds.typeSpecifier()?.structOrUnionSpecifier();
if (sous != null)
{
var id = sous.Identifier()?.GetText();
if (id != null)
_st.Define(new Symbol() { Name = id, Classification = TypeClassification.Type_ });
}
}

CParser.InitDeclaratorListContext init_declaration_list = declaration_context.initDeclaratorList();
CParser.InitDeclaratorContext[] x = init_declaration_list?.initDeclarator();
if (x != null)
{
foreach (var id in x)
{
CParser.DeclaratorContext y = id?.declarator();
var identifier = y.directDeclarator()?.Identifier();
if (identifier != null)
{
// If a typedef is used in the declaration, the declarator
// itself is a type, not a variable.
var text = identifier.GetText();
if (is_typedef)
_st.Define(new Symbol() { Name = text, Classification = TypeClassification.Type_ });
else
_st.Define(new Symbol() { Name = text, Classification = TypeClassification.Variable_ });
}
}
}
}

// Define to return "true" because "gcc -c -std=c2x" accepts an empty
// struct-declaration-list.
public bool NullStructDeclarationListExtension()
{
return true;
}
}

18 changes: 18 additions & 0 deletions c/CSharp/Symbol.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Collections.Generic;

public class Symbol {
public string Name { get; set; }
public TypeClassification Classification { get; set; }
public Dictionary<string, Symbol> Members { get; } = new();
public Symbol Parent { get; set; }

public override string ToString()
{
var result = Name;
var classification = Classification.ToString();
result += " (with classification " + classification;
result += ")";
if (Parent != null) result += " of " + Parent.ToString();
return result;
}
}
117 changes: 117 additions & 0 deletions c/CSharp/SymbolTable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Text;

public class SymbolTable {
private Stack<Symbol> scopeStack = new Stack<Symbol>();

public SymbolTable() {
var globalScope = new Symbol() { Name = "global", Classification = TypeClassification.Global_ };
scopeStack.Push(globalScope);

Define(new Symbol() { Name = "typedef", Classification = TypeClassification.StorageClassSpecifier_ });
Define(new Symbol() { Name = "extern", Classification = TypeClassification.StorageClassSpecifier_ });
Define(new Symbol() { Name = "static", Classification = TypeClassification.StorageClassSpecifier_ });
Define(new Symbol() { Name = "_Thread_local", Classification = TypeClassification.StorageClassSpecifier_ });
Define(new Symbol() { Name = "auto", Classification = TypeClassification.StorageClassSpecifier_ });
Define(new Symbol() { Name = "register", Classification = TypeClassification.StorageClassSpecifier_ });

Define(new Symbol() { Name = "struct", Classification = TypeClassification.StorageClassSpecifier_ });
Define(new Symbol() { Name = "union", Classification = TypeClassification.StorageClassSpecifier_ });

Define(new Symbol() { Name = "const", Classification = TypeClassification.TypeQualifier_ });
Define(new Symbol() { Name = "restrict", Classification = TypeClassification.TypeQualifier_ });
Define(new Symbol() { Name = "volatile", Classification = TypeClassification.TypeQualifier_ });
Define(new Symbol() { Name = "_Atomic", Classification = TypeClassification.TypeQualifier_ });

// Init basic types.
Define(new Symbol() { Name = "void", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "char", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "short", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "int", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "long", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "float", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "double", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "signed", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "unsigned", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "_Bool", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "_Complex", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "__m128", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "__m128d", Classification = TypeClassification.Type_ });
Define(new Symbol() { Name = "__m128i", Classification = TypeClassification.Type_ });


}

public void EnterScope(Symbol newScope) {
var current = scopeStack.Peek();
if (newScope == current) return;
scopeStack.Push(newScope);
}

public void ExitScope() {
var current = scopeStack.Peek();
scopeStack.Pop();
if (scopeStack.Count == 0)
throw new Exception();
}

public Symbol CurrentScope()
{
if (scopeStack.Count == 0) return null;
var current_scope = scopeStack.Peek();
return current_scope;
}

public bool Define(Symbol symbol) {
var currentScope = CurrentScope();
return this.DefineInScope(currentScope, symbol);
}

public bool DefineInScope(Symbol currentScope, Symbol symbol) {
if (currentScope.Members.ContainsKey(symbol.Name)) {
return false; // Symbol already defined in the current scope
}
symbol.Parent = currentScope;
currentScope.Members[symbol.Name] = symbol;
return true;
}

public Symbol Resolve(string name, Symbol start_scope = null)
{
if (start_scope == null)
{
foreach (Symbol scope in scopeStack)
{
if (scope.Members.TryGetValue(name, out Symbol symbol))
{
return symbol;
}
}

return null; // Symbol not found
}
else
{
if (start_scope.Members.TryGetValue(name, out Symbol symbol))
{
return symbol;
}

return null; // Symbol not found
}
}

public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (var scope in scopeStack)
{
foreach (var member in scope.Members)
{
sb.AppendLine(member.ToString());
}
}
return sb.ToString();
}
}
10 changes: 10 additions & 0 deletions c/CSharp/TypeClassification.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

public enum TypeClassification {
Global_,
Function_,
Variable_,
Type_,
StorageClassSpecifier_,
TypeQualifier_,
}
4 changes: 4 additions & 0 deletions c/decls/1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
struct {
int a;
int b;
}; // unnamed.
8 changes: 8 additions & 0 deletions c/decls/2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
struct {
int a;
int b;
} x;

void foo() {
x.a = 1;
}
4 changes: 4 additions & 0 deletions c/decls/3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
struct z {
int a;
int b;
} x;
11 changes: 11 additions & 0 deletions c/decls/4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
int a;
int * b;
extern int c;
extern int *d;

void foo() {
a = 1;
*b = 2;
c = 3;
*d = 4;
}
4 changes: 4 additions & 0 deletions c/decls/5.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
typedef struct z {
int a;
int b;
} x;
5 changes: 4 additions & 1 deletion c/desc.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<desc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../_scripts/desc.xsd">
<targets>;Antlr4ng;Cpp;CSharp;Dart;Go;Java;JavaScript;PHP;Python3;Rust;TypeScript</targets>
<targets>CSharp</targets>
<!--
<targets>Antlr4ng;Cpp;CSharp;Dart;Go;Java;JavaScript;PHP;Python3;Rust;TypeScript</targets>
-->
</desc>
3 changes: 3 additions & 0 deletions c/examples/1065.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
typedef int UINTN;
void * __cdecl LibPcdGetPtr (UINTN TokenNumber);
void __cdecl LibPcdGetPtr (UINTN TokenNumber);
11 changes: 11 additions & 0 deletions c/examples/1066.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
typedef int UINTN;
typedef long GUID;

typedef
void
(__cdecl *PCD_CALLBACK)(
const GUID *CallBackGuid,
UINTN CallBackToken,
void *TokenData,
UINTN TokenDataSize
);
10 changes: 10 additions & 0 deletions c/examples/1130.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
static unsigned long diff_filespec_size(struct diff_filespec *one){

if (!DIFF_FILE_VALID(one))

return 0;

diff_populate_filespec(one, CHECK_SIZE_ONLY);

return one->size;
}
1 change: 1 addition & 0 deletions c/examples/1130.c.trq
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
assert count(//functionDefinition/declarator/directDeclarator/directDeclarator/Identifier[text() = "diff_filespec_size"]) = 1, "Declaration for diff_filespec_size is not being parsed correctly.";
3 changes: 3 additions & 0 deletions c/examples/1979.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
struct X {
int val1;
};
12 changes: 12 additions & 0 deletions c/examples/4380.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This example illustrates ambiguity in the chose of a statement vs.
// declaration in blockItem. The parse cannot be a statement if it
// begins with a type.
// ../examples/4380.c.d=116.a=1: (compilationUnit (translationUnit (externalDeclaration (declaration (declarationSpecifiers (declarationSpecifier (typeSpecifier (structOrUnionSpecifier (structOrUnion (Struct "struct")) (Identifier "nginx") (LeftBrace "{") (RightBrace "}"))))) (Semi ";"))) (externalDeclaration (functionDefinition (declarationSpecifiers (declarationSpecifier (typeSpecifier (Int "int")))) (declarator (directDeclarator (directDeclarator (Identifier "main")) (LeftParen "(") (RightParen ")"))) (compoundStatement (LeftBrace "{") (blockItemList (blockItem (statement (expressionStatement (expression (assignmentExpression (conditionalExpression (logicalOrExpression (logicalAndExpression (inclusiveOrExpression (exclusiveOrExpression (andExpression (equalityExpression (relationalExpression (shiftExpression (additiveExpression (multiplicativeExpression (castExpression (unaryExpression (postfixExpression (primaryExpression (Identifier "nginx"))))) (Star "*") (castExpression (unaryExpression (postfixExpression (primaryExpression (Identifier "d")))))))))))))))))) (Semi ";"))))) (RightBrace "}"))))) (EOF ""))
// ../examples/4380.c.d=116.a=2: (compilationUnit (translationUnit (externalDeclaration (declaration (declarationSpecifiers (declarationSpecifier (typeSpecifier (structOrUnionSpecifier (structOrUnion (Struct "struct")) (Identifier "nginx") (LeftBrace "{") (RightBrace "}"))))) (Semi ";"))) (externalDeclaration (functionDefinition (declarationSpecifiers (declarationSpecifier (typeSpecifier (Int "int")))) (declarator (directDeclarator (directDeclarator (Identifier "main")) (LeftParen "(") (RightParen ")"))) (compoundStatement (LeftBrace "{") (blockItemList (blockItem (declaration (declarationSpecifiers (declarationSpecifier (typeSpecifier (typedefName (Identifier "nginx"))))) (initDeclaratorList (initDeclarator (declarator (pointer (Star "*")) (directDeclarator (Identifier "d"))))) (Semi ";")))) (RightBrace "}"))))) (EOF ""))
// See https://groups.google.com/g/antlr-discussion/c/nGvUxmnOxsI

struct nginx {};

int main() {
nginx *d;
}
2 changes: 2 additions & 0 deletions c/examples/4380.c.trq
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
assert count(//declaration/declarationSpecifiers/declarationSpecifier/typeSpecifier/typedefName/Identifier[text() = "nginx"]) = 1, "Declaration 'nginx *d;' is not being parsed correctly.";
assert count(//declaration/initDeclaratorList/initDeclarator/declarator[./pointer][./directDeclarator/Identifier[text() = "d"]]) = 1, "Declaration 'nginx *d;' is not being parsed correctly.";
4 changes: 4 additions & 0 deletions c/examples/4380b.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// See https://groups.google.com/g/antlr-discussion/c/nGvUxmnOxsI
int main() {
int *b;
}
3 changes: 3 additions & 0 deletions c/examples/4380b.c.trq
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
assert count(//declaration/declarationSpecifiers/declarationSpecifier/typeSpecifier/Int[text() = "int"]) = 1, "Declaration 'int *b;' is not being parsed correctly.";
assert count(//declaration/initDeclaratorList/initDeclarator/declarator[./pointer][./directDeclarator/Identifier[text() = "b"]]) = 1, "Declaration 'nginx *d;' is not being parsed correctly.";

2 changes: 2 additions & 0 deletions c/examples/4676.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extern int* x;
extern int y;
4 changes: 4 additions & 0 deletions c/examples/4676.c.trq
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(: Check whether x and y are both . :)

assert count(//externalDeclaration//initDeclaratorList//Identifier[text() = "x"]) = 1, "Declaration 'extern int *x;' is not being parsed correctly.";
assert count(//externalDeclaration//initDeclaratorList//Identifier[text() = "y"]) = 1, "Declaration 'extern int y;' is not being parsed correctly.";
6 changes: 3 additions & 3 deletions c/examples/FuncCallAsFuncArgument.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ And func call as func call argument.

void aX(void);
int a1(int param1);
int a2(int param1, param2);
int a2(int param1, int param2);
void a3();
void a3(void);

Expand All @@ -15,8 +15,8 @@ int f(int arg1, char arg2)
a1(arg1);
a2(arg1, arg2);
a3();
a1(a1());
a1(a1(), a2(a1(), x1));
a1(a1(1));
a1(a2(a1(1), 1));
}


Loading
Loading