diff --git a/c/CLexer.g4 b/c/CLexer.g4 new file mode 100644 index 0000000000..edce433726 --- /dev/null +++ b/c/CLexer.g4 @@ -0,0 +1,699 @@ +/* + [The "BSD licence"] + Copyright (c) 2013 Sam Harwell + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** C 2011 grammar built from the C11 Spec */ + +// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false +// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging + +lexer grammar CLexer; + +KW__asm: '__asm'; +KW__asm__: '__asm__'; +KW__attribute__: '__attribute__'; +KW__builtin_offsetof: '__builtin_offsetof'; +KW__builtin_va_arg: '__builtin_va_arg'; +KW__cdecl: '__cdecl'; +KW__clrcall: '__clrcall'; +KW__declspec: '__declspec'; +KW__extension__: '__extension__'; +KW__fastcall: '__fastcall'; +KW__inline__: '__inline__'; +KW__m128: '__m128'; +KW__m128d: '__m128d'; +KW__m128i: '__m128i'; +KW__stdcall: '__stdcall'; +KW__thiscall: '__thiscall'; +KW__typeof__: '__typeof__'; +KW__vectorcall: '__vectorcall'; +KW__volatile__: '__volatile__'; + +Alignas + : 'alignas' + | '_Alignas' + ; + +Alignof + : 'alignof' + | '_Alignof' + ; + +Auto + : 'auto' + ; + +Bool + : 'bool' + | '_Bool' + ; + +Break + : 'break' + ; + +Case + : 'case' + ; + +Char + : 'char' + ; + +Const + : 'const' + ; + +Constexpr + : 'constexpr' + ; + +Continue + : 'continue' + ; + +Default + : 'default' + ; + +Do + : 'do' + ; + +Double + : 'double' + ; + +Else + : 'else' + ; + +Enum + : 'enum' + ; + +Extern + : 'extern' + ; + +False + : 'false' + ; + +Float + : 'float' + ; + +For + : 'for' + ; + +Goto + : 'goto' + ; + +If + : 'if' + ; + +Inline + : 'inline' + ; + +Int + : 'int' + ; + +Long + : 'long' + ; + +Nulptr + : 'nullptr' + ; + +Register + : 'register' + ; + +Restrict + : 'restrict' + ; + +Return + : 'return' + ; + +Short + : 'short' + ; + +Signed + : 'signed' + ; + +Sizeof + : 'sizeof' + ; + +Static + : 'static' + ; + +Static_assert + : 'static_assert' + ; + +Struct + : 'struct' + ; + +Switch + : 'switch' + ; + +Thread_local + : 'thread_local' + ; + +Typedef + : 'typedef' + ; + +Typeof + : 'typeof' + ; + +Typeof_unequal + : 'typeof_unequal' + ; + +Union + : 'union' + ; + +Unsigned + : 'unsigned' + ; + +Void + : 'void' + ; + +Volatile + : 'volatile' + ; + +While + : 'while' + ; + +Atomic + : '_Atomic' + ; + +BitInt + : '_BitInt' + ; + +Complex + : '_Complex' + ; + +Decimal128 + : '_Decimal128' + ; + +Decimal32 + : '_Decimal32' + ; + +Decimal64 + : '_Decimal64' + ; + +Generic + : '_Generic' + ; + +Imaginary + : '_Imaginary' + ; + +Noreturn + : '_Noreturn' + ; + +StaticAssert + : '_Static_assert' + ; + +ThreadLocal + : '_Thread_local' + ; + +LeftParen + : '(' + ; + +RightParen + : ')' + ; + +LeftBracket + : '[' + ; + +RightBracket + : ']' + ; + +LeftBrace + : '{' + ; + +RightBrace + : '}' + ; + +Less + : '<' + ; + +LessEqual + : '<=' + ; + +Greater + : '>' + ; + +GreaterEqual + : '>=' + ; + +LeftShift + : '<<' + ; + +RightShift + : '>>' + ; + +Plus + : '+' + ; + +PlusPlus + : '++' + ; + +Minus + : '-' + ; + +MinusMinus + : '--' + ; + +Star + : '*' + ; + +Div + : '/' + ; + +Mod + : '%' + ; + +And + : '&' + ; + +Or + : '|' + ; + +AndAnd + : '&&' + ; + +OrOr + : '||' + ; + +Caret + : '^' + ; + +Not + : '!' + ; + +Tilde + : '~' + ; + +Question + : '?' + ; + +Colon + : ':' + ; + +ColonColon + : '::' + ; + +Semi + : ';' + ; + +Comma + : ',' + ; + +Assign + : '=' + ; + +// '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '&=' | '^=' | '|=' +StarAssign + : '*=' + ; + +DivAssign + : '/=' + ; + +ModAssign + : '%=' + ; + +PlusAssign + : '+=' + ; + +MinusAssign + : '-=' + ; + +LeftShiftAssign + : '<<=' + ; + +RightShiftAssign + : '>>=' + ; + +AndAssign + : '&=' + ; + +XorAssign + : '^=' + ; + +OrAssign + : '|=' + ; + +Equal + : '==' + ; + +NotEqual + : '!=' + ; + +Arrow + : '->' + ; + +Dot + : '.' + ; + +Ellipsis + : '...' + ; + +Identifier + : IdentifierNondigit (IdentifierNondigit | Digit)* + ; + +fragment IdentifierNondigit + : Nondigit + | UniversalCharacterName + //| // other implementation-defined characters... + ; + +fragment Nondigit + : [a-zA-Z_] + ; + +fragment Digit + : [0-9] + ; + +fragment UniversalCharacterName + : '\\u' HexQuad + | '\\U' HexQuad HexQuad + ; + +fragment HexQuad + : HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit + ; + +Constant + : IntegerConstant + | FloatingConstant + //| EnumerationConstant + | CharacterConstant + ; + +fragment IntegerConstant + : DecimalConstant IntegerSuffix? + | OctalConstant IntegerSuffix? + | HexadecimalConstant IntegerSuffix? + | BinaryConstant + ; + +fragment BinaryConstant + : '0' [bB] [0-1]+ + ; + +fragment DecimalConstant + : NonzeroDigit Digit* + ; + +fragment OctalConstant + : '0' OctalDigit* + ; + +fragment HexadecimalConstant + : HexadecimalPrefix HexadecimalDigit+ + ; + +fragment HexadecimalPrefix + : '0' [xX] + ; + +fragment NonzeroDigit + : [1-9] + ; + +fragment OctalDigit + : [0-7] + ; + +fragment HexadecimalDigit + : [0-9a-fA-F] + ; + +fragment IntegerSuffix + : UnsignedSuffix LongSuffix? + | UnsignedSuffix LongLongSuffix + | LongSuffix UnsignedSuffix? + | LongLongSuffix UnsignedSuffix? + ; + +fragment UnsignedSuffix + : [uU] + ; + +fragment LongSuffix + : [lL] + ; + +fragment LongLongSuffix + : 'll' + | 'LL' + ; + +fragment FloatingConstant + : DecimalFloatingConstant + | HexadecimalFloatingConstant + ; + +fragment DecimalFloatingConstant + : FractionalConstant ExponentPart? FloatingSuffix? + | DigitSequence ExponentPart FloatingSuffix? + ; + +fragment HexadecimalFloatingConstant + : HexadecimalPrefix (HexadecimalFractionalConstant | HexadecimalDigitSequence) BinaryExponentPart FloatingSuffix? + ; + +fragment FractionalConstant + : DigitSequence? '.' DigitSequence + | DigitSequence '.' + ; + +fragment ExponentPart + : [eE] Sign? DigitSequence + ; + +fragment Sign + : [+-] + ; + +DigitSequence + : Digit+ + ; + +fragment HexadecimalFractionalConstant + : HexadecimalDigitSequence? '.' HexadecimalDigitSequence + | HexadecimalDigitSequence '.' + ; + +fragment BinaryExponentPart + : [pP] Sign? DigitSequence + ; + +fragment HexadecimalDigitSequence + : HexadecimalDigit+ + ; + +fragment FloatingSuffix + : [flFL] + ; + +fragment CharacterConstant + : '\'' CCharSequence '\'' + | 'L\'' CCharSequence '\'' + | 'u\'' CCharSequence '\'' + | 'U\'' CCharSequence '\'' + ; + +fragment CCharSequence + : CChar+ + ; + +fragment CChar + : ~['\\\r\n] + | EscapeSequence + ; + +fragment EscapeSequence + : SimpleEscapeSequence + | OctalEscapeSequence + | HexadecimalEscapeSequence + | UniversalCharacterName + ; + +fragment SimpleEscapeSequence + : '\\' ['"?abfnrtv\\] + ; + +fragment OctalEscapeSequence + : '\\' OctalDigit OctalDigit? OctalDigit? + ; + +fragment HexadecimalEscapeSequence + : '\\x' HexadecimalDigit+ + ; + +StringLiteral + : EncodingPrefix? '"' SCharSequence? '"' + ; + +fragment EncodingPrefix + : 'u8' + | 'u' + | 'U' + | 'L' + ; + +fragment SCharSequence + : SChar+ + ; + +fragment SChar + : ~["\\\r\n] + | EscapeSequence + | '\\\n' // Added line + | '\\\r\n' // Added line + ; + +MultiLineMacro + : '#' (~[\n]*? '\\' '\r'? '\n')+ ~ [\n]+ -> channel (HIDDEN) + ; + +Directive + : '#' ~ [\n]* -> channel (HIDDEN) + ; + +// ignore the following asm blocks: +/* + asm + { + mfspr x, 286; + } + */ +AsmBlock + : 'asm' ~'{'* '{' ~'}'* '}' -> channel(HIDDEN) + ; + +Whitespace + : [ \t]+ -> channel(HIDDEN) + ; + +Newline + : ('\r' '\n'? | '\n') -> channel(HIDDEN) + ; + +BlockComment + : '/*' .*? '*/' -> channel(HIDDEN) + ; + +LineComment + : '//' ~[\r\n]* -> channel(HIDDEN) + ; \ No newline at end of file diff --git a/c/C.g4 b/c/CParser.g4 similarity index 60% rename from c/C.g4 rename to c/CParser.g4 index 6646a235d4..ae40dbd21e 100644 --- a/c/C.g4 +++ b/c/CParser.g4 @@ -31,7 +31,22 @@ // $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false // $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging -grammar C; +parser grammar CParser; + +options { + superClass=CParserBase; + tokenVocab=CLexer; +} + + +compilationUnit + : translationUnit? EOF + ; + +translationUnit + : externalDeclaration+ + ; + primaryExpression : Identifier @@ -74,7 +89,7 @@ unaryExpression : ('++' | '--' | 'sizeof')* ( postfixExpression | unaryOperator castExpression - | ('sizeof' | '_Alignof') '(' typeName ')' + | ('sizeof' | Alignof) '(' typeName ')' | '&&' Identifier // GCC extension address of label ) ; @@ -167,16 +182,12 @@ constantExpression ; declaration - : declarationSpecifiers initDeclaratorList? ';' + : declarationSpecifiers initDeclaratorList? ';' {this.EnterDeclaration();} | staticAssertDeclaration ; declarationSpecifiers - : declarationSpecifier+ - ; - -declarationSpecifiers2 - : declarationSpecifier+ + : ({ this.IsType()}? declarationSpecifier )+ ; declarationSpecifier @@ -214,7 +225,7 @@ typeSpecifier | 'double' | 'signed' | 'unsigned' - | '_Bool' + | Bool | '_Complex' | '__m128' | '__m128d' @@ -228,8 +239,11 @@ typeSpecifier ; structOrUnionSpecifier - : structOrUnion Identifier? '{' structDeclarationList '}' - | structOrUnion Identifier + : structOrUnion + ( Identifier? '{' ( {this.NullStructDeclarationListExtension()}? | structDeclarationList) '}' + | Identifier + ) +// {this.EnterDeclaration();} ; structOrUnion @@ -298,7 +312,7 @@ functionSpecifier ; alignmentSpecifier - : '_Alignas' '(' (typeName | constantExpression) ')' + : Alignas '(' (typeName | constantExpression) ')' ; declarator @@ -306,15 +320,14 @@ declarator ; directDeclarator - : Identifier + : Identifier attributeSpecifierSequence? | '(' declarator ')' - | directDeclarator '[' typeQualifierList? assignmentExpression? ']' - | directDeclarator '[' 'static' typeQualifierList? assignmentExpression ']' - | directDeclarator '[' typeQualifierList 'static' assignmentExpression ']' - | directDeclarator '[' typeQualifierList? '*' ']' - | directDeclarator '(' parameterTypeList ')' - | directDeclarator '(' identifierList? ')' - | Identifier ':' DigitSequence // bit field + | directDeclarator '[' typeQualifierList? assignmentExpression? ']' attributeSpecifierSequence? + | directDeclarator '[' 'static' typeQualifierList? assignmentExpression ']' attributeSpecifierSequence? + | directDeclarator '[' typeQualifierList 'static' assignmentExpression ']' attributeSpecifierSequence? + | directDeclarator '[' typeQualifierList? '*' ']' attributeSpecifierSequence? + | directDeclarator '(' parameterTypeList? ')' attributeSpecifierSequence? +// | Identifier ':' DigitSequence // bit field | vcSpecificModifer Identifier // Visual C Extension | '(' vcSpecificModifer declarator ')' // Visual C Extension ; @@ -363,8 +376,7 @@ parameterList ; parameterDeclaration - : declarationSpecifiers declarator - | declarationSpecifiers2 abstractDeclarator? + : declarationSpecifiers ( declarator | abstractDeclarator? ) ; identifierList @@ -421,7 +433,43 @@ designator ; staticAssertDeclaration - : '_Static_assert' '(' constantExpression ',' StringLiteral+ ')' ';' + : '_Static_assert' '(' constantExpression (',' StringLiteral)? ')' ';' + ; + +attributeSpecifierSequence + : attributeSpecifier+ + ; + +attributeSpecifier + : '[' '[' attributeList ']' ']' + ; + +attributeList + : attribute (',' attribute)* // May not be correct. + ; + +attribute + : attributeToken attributeArgumentClause? + ; + +attributeToken + : Identifier + | Identifier '::' Identifier + ; + +attributeArgumentClause + : '(' balancedTokenSequence? ')' + ; + +balancedTokenSequence + : balancedToken+ + ; + +balancedToken + : '(' balancedTokenSequence? ')' + | '[' balancedTokenSequence? ']' + | '{' balancedTokenSequence? '}' + // any token other than a parenthesis, bracket, or brace ; statement @@ -451,8 +499,8 @@ blockItemList ; blockItem - : statement - | declaration + : {this.IsNotType()}? statement + | {this.IsType()}? declaration ; expressionStatement @@ -495,14 +543,6 @@ jumpStatement ) ';' ; -compilationUnit - : translationUnit? EOF - ; - -translationUnit - : externalDeclaration+ - ; - externalDeclaration : functionDefinition | declaration @@ -517,596 +557,3 @@ declarationList : declaration+ ; -Auto - : 'auto' - ; - -Break - : 'break' - ; - -Case - : 'case' - ; - -Char - : 'char' - ; - -Const - : 'const' - ; - -Continue - : 'continue' - ; - -Default - : 'default' - ; - -Do - : 'do' - ; - -Double - : 'double' - ; - -Else - : 'else' - ; - -Enum - : 'enum' - ; - -Extern - : 'extern' - ; - -Float - : 'float' - ; - -For - : 'for' - ; - -Goto - : 'goto' - ; - -If - : 'if' - ; - -Inline - : 'inline' - ; - -Int - : 'int' - ; - -Long - : 'long' - ; - -Register - : 'register' - ; - -Restrict - : 'restrict' - ; - -Return - : 'return' - ; - -Short - : 'short' - ; - -Signed - : 'signed' - ; - -Sizeof - : 'sizeof' - ; - -Static - : 'static' - ; - -Struct - : 'struct' - ; - -Switch - : 'switch' - ; - -Typedef - : 'typedef' - ; - -Union - : 'union' - ; - -Unsigned - : 'unsigned' - ; - -Void - : 'void' - ; - -Volatile - : 'volatile' - ; - -While - : 'while' - ; - -Alignas - : '_Alignas' - ; - -Alignof - : '_Alignof' - ; - -Atomic - : '_Atomic' - ; - -Bool - : '_Bool' - ; - -Complex - : '_Complex' - ; - -Generic - : '_Generic' - ; - -Imaginary - : '_Imaginary' - ; - -Noreturn - : '_Noreturn' - ; - -StaticAssert - : '_Static_assert' - ; - -ThreadLocal - : '_Thread_local' - ; - -LeftParen - : '(' - ; - -RightParen - : ')' - ; - -LeftBracket - : '[' - ; - -RightBracket - : ']' - ; - -LeftBrace - : '{' - ; - -RightBrace - : '}' - ; - -Less - : '<' - ; - -LessEqual - : '<=' - ; - -Greater - : '>' - ; - -GreaterEqual - : '>=' - ; - -LeftShift - : '<<' - ; - -RightShift - : '>>' - ; - -Plus - : '+' - ; - -PlusPlus - : '++' - ; - -Minus - : '-' - ; - -MinusMinus - : '--' - ; - -Star - : '*' - ; - -Div - : '/' - ; - -Mod - : '%' - ; - -And - : '&' - ; - -Or - : '|' - ; - -AndAnd - : '&&' - ; - -OrOr - : '||' - ; - -Caret - : '^' - ; - -Not - : '!' - ; - -Tilde - : '~' - ; - -Question - : '?' - ; - -Colon - : ':' - ; - -Semi - : ';' - ; - -Comma - : ',' - ; - -Assign - : '=' - ; - -// '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '&=' | '^=' | '|=' -StarAssign - : '*=' - ; - -DivAssign - : '/=' - ; - -ModAssign - : '%=' - ; - -PlusAssign - : '+=' - ; - -MinusAssign - : '-=' - ; - -LeftShiftAssign - : '<<=' - ; - -RightShiftAssign - : '>>=' - ; - -AndAssign - : '&=' - ; - -XorAssign - : '^=' - ; - -OrAssign - : '|=' - ; - -Equal - : '==' - ; - -NotEqual - : '!=' - ; - -Arrow - : '->' - ; - -Dot - : '.' - ; - -Ellipsis - : '...' - ; - -Identifier - : IdentifierNondigit (IdentifierNondigit | Digit)* - ; - -fragment IdentifierNondigit - : Nondigit - | UniversalCharacterName - //| // other implementation-defined characters... - ; - -fragment Nondigit - : [a-zA-Z_] - ; - -fragment Digit - : [0-9] - ; - -fragment UniversalCharacterName - : '\\u' HexQuad - | '\\U' HexQuad HexQuad - ; - -fragment HexQuad - : HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit - ; - -Constant - : IntegerConstant - | FloatingConstant - //| EnumerationConstant - | CharacterConstant - ; - -fragment IntegerConstant - : DecimalConstant IntegerSuffix? - | OctalConstant IntegerSuffix? - | HexadecimalConstant IntegerSuffix? - | BinaryConstant - ; - -fragment BinaryConstant - : '0' [bB] [0-1]+ - ; - -fragment DecimalConstant - : NonzeroDigit Digit* - ; - -fragment OctalConstant - : '0' OctalDigit* - ; - -fragment HexadecimalConstant - : HexadecimalPrefix HexadecimalDigit+ - ; - -fragment HexadecimalPrefix - : '0' [xX] - ; - -fragment NonzeroDigit - : [1-9] - ; - -fragment OctalDigit - : [0-7] - ; - -fragment HexadecimalDigit - : [0-9a-fA-F] - ; - -fragment IntegerSuffix - : UnsignedSuffix LongSuffix? - | UnsignedSuffix LongLongSuffix - | LongSuffix UnsignedSuffix? - | LongLongSuffix UnsignedSuffix? - ; - -fragment UnsignedSuffix - : [uU] - ; - -fragment LongSuffix - : [lL] - ; - -fragment LongLongSuffix - : 'll' - | 'LL' - ; - -fragment FloatingConstant - : DecimalFloatingConstant - | HexadecimalFloatingConstant - ; - -fragment DecimalFloatingConstant - : FractionalConstant ExponentPart? FloatingSuffix? - | DigitSequence ExponentPart FloatingSuffix? - ; - -fragment HexadecimalFloatingConstant - : HexadecimalPrefix (HexadecimalFractionalConstant | HexadecimalDigitSequence) BinaryExponentPart FloatingSuffix? - ; - -fragment FractionalConstant - : DigitSequence? '.' DigitSequence - | DigitSequence '.' - ; - -fragment ExponentPart - : [eE] Sign? DigitSequence - ; - -fragment Sign - : [+-] - ; - -DigitSequence - : Digit+ - ; - -fragment HexadecimalFractionalConstant - : HexadecimalDigitSequence? '.' HexadecimalDigitSequence - | HexadecimalDigitSequence '.' - ; - -fragment BinaryExponentPart - : [pP] Sign? DigitSequence - ; - -fragment HexadecimalDigitSequence - : HexadecimalDigit+ - ; - -fragment FloatingSuffix - : [flFL] - ; - -fragment CharacterConstant - : '\'' CCharSequence '\'' - | 'L\'' CCharSequence '\'' - | 'u\'' CCharSequence '\'' - | 'U\'' CCharSequence '\'' - ; - -fragment CCharSequence - : CChar+ - ; - -fragment CChar - : ~['\\\r\n] - | EscapeSequence - ; - -fragment EscapeSequence - : SimpleEscapeSequence - | OctalEscapeSequence - | HexadecimalEscapeSequence - | UniversalCharacterName - ; - -fragment SimpleEscapeSequence - : '\\' ['"?abfnrtv\\] - ; - -fragment OctalEscapeSequence - : '\\' OctalDigit OctalDigit? OctalDigit? - ; - -fragment HexadecimalEscapeSequence - : '\\x' HexadecimalDigit+ - ; - -StringLiteral - : EncodingPrefix? '"' SCharSequence? '"' - ; - -fragment EncodingPrefix - : 'u8' - | 'u' - | 'U' - | 'L' - ; - -fragment SCharSequence - : SChar+ - ; - -fragment SChar - : ~["\\\r\n] - | EscapeSequence - | '\\\n' // Added line - | '\\\r\n' // Added line - ; - -MultiLineMacro - : '#' (~[\n]*? '\\' '\r'? '\n')+ ~ [\n]+ -> channel (HIDDEN) - ; - -Directive - : '#' ~ [\n]* -> channel (HIDDEN) - ; - -// ignore the following asm blocks: -/* - asm - { - mfspr x, 286; - } - */ -AsmBlock - : 'asm' ~'{'* '{' ~'}'* '}' -> channel(HIDDEN) - ; - -Whitespace - : [ \t]+ -> channel(HIDDEN) - ; - -Newline - : ('\r' '\n'? | '\n') -> channel(HIDDEN) - ; - -BlockComment - : '/*' .*? '*/' -> channel(HIDDEN) - ; - -LineComment - : '//' ~[\r\n]* -> channel(HIDDEN) - ; \ No newline at end of file diff --git a/c/CSharp/CParserBase.cs b/c/CSharp/CParserBase.cs new file mode 100644 index 0000000000..bb2b56ec85 --- /dev/null +++ b/c/CSharp/CParserBase.cs @@ -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; + } +} + diff --git a/c/CSharp/Symbol.cs b/c/CSharp/Symbol.cs new file mode 100644 index 0000000000..cb8e6db73b --- /dev/null +++ b/c/CSharp/Symbol.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +public class Symbol { + public string Name { get; set; } + public TypeClassification Classification { get; set; } + public Dictionary 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; + } +} diff --git a/c/CSharp/SymbolTable.cs b/c/CSharp/SymbolTable.cs new file mode 100644 index 0000000000..3afc263fdc --- /dev/null +++ b/c/CSharp/SymbolTable.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Text; + +public class SymbolTable { + private Stack scopeStack = new Stack(); + + 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(); + } +} diff --git a/c/CSharp/TypeClassification.cs b/c/CSharp/TypeClassification.cs new file mode 100644 index 0000000000..b5f4ca15cc --- /dev/null +++ b/c/CSharp/TypeClassification.cs @@ -0,0 +1,10 @@ +using System; + +public enum TypeClassification { + Global_, + Function_, + Variable_, + Type_, + StorageClassSpecifier_, + TypeQualifier_, +} diff --git a/c/decls/1.c b/c/decls/1.c new file mode 100644 index 0000000000..73c0a2b846 --- /dev/null +++ b/c/decls/1.c @@ -0,0 +1,4 @@ +struct { + int a; + int b; +}; // unnamed. diff --git a/c/decls/2.c b/c/decls/2.c new file mode 100644 index 0000000000..9826cc18ee --- /dev/null +++ b/c/decls/2.c @@ -0,0 +1,8 @@ +struct { + int a; + int b; +} x; + +void foo() { + x.a = 1; +} \ No newline at end of file diff --git a/c/decls/3.c b/c/decls/3.c new file mode 100644 index 0000000000..8e52941887 --- /dev/null +++ b/c/decls/3.c @@ -0,0 +1,4 @@ +struct z { + int a; + int b; +} x; diff --git a/c/decls/4.c b/c/decls/4.c new file mode 100644 index 0000000000..d627ac62fd --- /dev/null +++ b/c/decls/4.c @@ -0,0 +1,11 @@ +int a; +int * b; +extern int c; +extern int *d; + +void foo() { + a = 1; + *b = 2; + c = 3; + *d = 4; +} \ No newline at end of file diff --git a/c/decls/5.c b/c/decls/5.c new file mode 100644 index 0000000000..5a5437bce5 --- /dev/null +++ b/c/decls/5.c @@ -0,0 +1,4 @@ +typedef struct z { + int a; + int b; +} x; diff --git a/c/desc.xml b/c/desc.xml index 3d50d6f453..578b82d570 100644 --- a/c/desc.xml +++ b/c/desc.xml @@ -1,4 +1,7 @@ - ;Antlr4ng;Cpp;CSharp;Dart;Go;Java;JavaScript;PHP;Python3;Rust;TypeScript + CSharp + diff --git a/c/examples/1065.c b/c/examples/1065.c new file mode 100644 index 0000000000..74307d2696 --- /dev/null +++ b/c/examples/1065.c @@ -0,0 +1,3 @@ +typedef int UINTN; +void * __cdecl LibPcdGetPtr (UINTN TokenNumber); +void __cdecl LibPcdGetPtr (UINTN TokenNumber); diff --git a/c/examples/1066.c b/c/examples/1066.c new file mode 100644 index 0000000000..7d1e2eb62a --- /dev/null +++ b/c/examples/1066.c @@ -0,0 +1,11 @@ +typedef int UINTN; +typedef long GUID; + +typedef + void + (__cdecl *PCD_CALLBACK)( + const GUID *CallBackGuid, + UINTN CallBackToken, + void *TokenData, + UINTN TokenDataSize + ); \ No newline at end of file diff --git a/c/examples/1130.c b/c/examples/1130.c new file mode 100644 index 0000000000..8a090da148 --- /dev/null +++ b/c/examples/1130.c @@ -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; +} diff --git a/c/examples/1130.c.trq b/c/examples/1130.c.trq new file mode 100644 index 0000000000..53878bd3dc --- /dev/null +++ b/c/examples/1130.c.trq @@ -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."; diff --git a/c/examples/1979.c b/c/examples/1979.c new file mode 100644 index 0000000000..91ff51e539 --- /dev/null +++ b/c/examples/1979.c @@ -0,0 +1,3 @@ +struct X { + int val1; +}; diff --git a/c/examples/4380.c b/c/examples/4380.c new file mode 100644 index 0000000000..892e0442b8 --- /dev/null +++ b/c/examples/4380.c @@ -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; +} diff --git a/c/examples/4380.c.trq b/c/examples/4380.c.trq new file mode 100644 index 0000000000..3f005e5bfd --- /dev/null +++ b/c/examples/4380.c.trq @@ -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."; diff --git a/c/examples/4380b.c b/c/examples/4380b.c new file mode 100644 index 0000000000..57d1c3f1c3 --- /dev/null +++ b/c/examples/4380b.c @@ -0,0 +1,4 @@ +// See https://groups.google.com/g/antlr-discussion/c/nGvUxmnOxsI +int main() { + int *b; +} \ No newline at end of file diff --git a/c/examples/4380b.c.trq b/c/examples/4380b.c.trq new file mode 100644 index 0000000000..4bab53fb33 --- /dev/null +++ b/c/examples/4380b.c.trq @@ -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."; + diff --git a/c/examples/4676.c b/c/examples/4676.c new file mode 100644 index 0000000000..7516f7d23f --- /dev/null +++ b/c/examples/4676.c @@ -0,0 +1,2 @@ +extern int* x; +extern int y; diff --git a/c/examples/4676.c.trq b/c/examples/4676.c.trq new file mode 100644 index 0000000000..fc52f4f672 --- /dev/null +++ b/c/examples/4676.c.trq @@ -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."; diff --git a/c/examples/FuncCallAsFuncArgument.c b/c/examples/FuncCallAsFuncArgument.c index 877051c278..ff0f4f1f86 100644 --- a/c/examples/FuncCallAsFuncArgument.c +++ b/c/examples/FuncCallAsFuncArgument.c @@ -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); @@ -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)); } diff --git a/c/examples/FuncCallwithVarArgs.c b/c/examples/FuncCallwithVarArgs.c index 4cf2639bea..a9c479d326 100644 --- a/c/examples/FuncCallwithVarArgs.c +++ b/c/examples/FuncCallwithVarArgs.c @@ -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); void a4(int, ...); @@ -18,8 +18,8 @@ int f(int arg1, char arg2) a1(arg1); a2(arg1, arg2); a3(); - a1(a1()); - a1(a1(), a2(a1(), x1)); + a1(a1(1)); + a4(a1(1), a2(a1(1), 1)); } diff --git a/c/examples/FuncForwardDeclaration.c b/c/examples/FuncForwardDeclaration.c index 684f8a1401..97c9a01c12 100644 --- a/c/examples/FuncForwardDeclaration.c +++ b/c/examples/FuncForwardDeclaration.c @@ -5,7 +5,7 @@ And func forward declarations. void aX(void); int a1(int param1); -int a2(int param1, param2); +int a2(int param1, int param2); void a3(); void a3(void); diff --git a/c/examples/FunctionPointer.c b/c/examples/FunctionPointer.c index c1c15309e9..da75474687 100644 --- a/c/examples/FunctionPointer.c +++ b/c/examples/FunctionPointer.c @@ -1,29 +1,32 @@ //function pointer +typedef struct {} MyType; +typedef struct {} MyStruct; + typedef void * (*f1)( - const MyType *param1, - long param2, + const MyType *param1, + long param2, void *param3, - short param4 + short param4 ); typedef int (*f2)( - const MyType *param1, - long param2, + const MyType *param1, + long param2, char *param3, - int param4 + int param4 ); typedef MyStruct ( *f3 ) ( - const MyType *param1, - double param2, + const MyType *param1, + double param2, float *param3, - long param4 + long param4 ); \ No newline at end of file diff --git a/c/examples/FunctionReturningPointer.c b/c/examples/FunctionReturningPointer.c index 47f8726591..90483a3fbe 100644 --- a/c/examples/FunctionReturningPointer.c +++ b/c/examples/FunctionReturningPointer.c @@ -1,3 +1,6 @@ +typedef int UINTN; +typedef struct {} MyStruct; + //function returns pointer void * __cdecl @@ -13,7 +16,7 @@ f2 ( ); -int MyStruct * +MyStruct * f3 ( int param1, char param2 diff --git a/c/examples/ParameterOfPointerType.c b/c/examples/ParameterOfPointerType.c index c21f8fd5da..7a06ba5e1d 100644 --- a/c/examples/ParameterOfPointerType.c +++ b/c/examples/ParameterOfPointerType.c @@ -1,4 +1,7 @@ //parameter contains pointer +typedef int MyType; +typedef int MyType1; + int __cdecl f1 ( @@ -9,7 +12,7 @@ f1 ( MyType1 __cdecl -f1 ( +f2 ( MyType *param1, int * param2 ); @@ -17,6 +20,6 @@ f1 ( void __cdecl -f1 ( +f3 ( void *param1 ); \ No newline at end of file diff --git a/c/examples/add.c b/c/examples/add.c index 521d9633b5..ba38260a89 100644 --- a/c/examples/add.c +++ b/c/examples/add.c @@ -1,3 +1,5 @@ +int LAST; + int main() { int i, sum = 0; diff --git a/c/examples/q.c b/c/examples/q.c new file mode 100644 index 0000000000..fa868b08ed --- /dev/null +++ b/c/examples/q.c @@ -0,0 +1 @@ +typedef struct {int z;} x;