/* C grammar and JJTree definition for use with JavaCC Contributed by Doug South (dsouth@squirrel.com.au) 21/3/97 From: https://github.com/javacc/javacc/blob/master/grammars/CParser.jj */ /* The following code has been significantly modified so as to make it compatible with Ghidra's decompiled output * and for the Rust transpilation */ options { MULTI = true; VISITOR = true; STATIC = false; } PARSER_BEGIN(CParser) import java.io.InputStream; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import ghidrust.decompiler.parser.c.CVisitor; public class CParser { private static CParser c_parser; // Run the parser public static String transpile(String c_code) { InputStream stream = new ByteArrayInputStream(c_code.getBytes(StandardCharsets.UTF_8)); return transpile(stream); } public static String transpile(InputStream stream) { c_parser = new CParser(stream); try { return parse(); } catch (ParseException e) { System.out.println("Rust transpiler: Encountered errors during parsing."); e.printStackTrace(); return null; } } public static String parse() throws ParseException { CParserVisitor visitor = new CVisitor(); return (String) c_parser.FunctionDefinition().jjtAccept(visitor, null); } } PARSER_END(CParser) SKIP : { " " | "\t" | "\n" | "\r" | <"//" (~["\n","\r"])* ("\n" | "\r" | "\r\n")> | <"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/"> | "#" : PREPROCESSOR_OUTPUT } SKIP: { "\n" : DEFAULT } MORE: { "\\\n" | "\\\r\n" | < ~[] > } TOKEN : { (["l","L"])? | (["l","L"])? | (["l","L"])?> | <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])*> | <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+> | <#OCTAL_LITERAL: "0" (["0"-"7"])*> | )? (["f","F","d","D"])? | "." (["0"-"9"])+ ()? (["f","F","d","D"])? | (["0"-"9"])+ (["f","F","d","D"])? | (["0"-"9"])+ ()? ["f","F","d","D"]> | <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+> | | | | )?> // Ghidra specific unknown type } TOKEN : { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | // code ptr, Ghidra specific } TOKEN : { | ) ( | | )*> | <#LETTER: ["$","A"-"Z","_","a"-"z"]> | <#DIGIT: ["0"-"9"]> | <#SEPARATOR: [":"]> } SimpleNode FunctionDefinition() : {} { [LOOKAHEAD(DeclarationSpecifiers()) DeclarationSpecifiers()] Declarator() CompoundStatement() { return jjtThis; } } void Declaration() : {} { DeclarationSpecifiers() [ InitDeclaratorList() ] ";" } void DeclarationList() : {} { ( LOOKAHEAD(Declaration()) Declaration() )+ } void DeclarationSpecifiers() : {} { StorageClassSpecifier() [ LOOKAHEAD(DeclarationSpecifiers()) DeclarationSpecifiers() ] | TypeSpecifier() [ LOOKAHEAD(DeclarationSpecifiers()) DeclarationSpecifiers() ] | TypeQualifier() [ LOOKAHEAD(DeclarationSpecifiers()) DeclarationSpecifiers() ] } void StorageClassSpecifier() #GhostStringToken : { Token t; } { ( t = | t = | t = | t = | t = ) { jjtThis.setValue(t.image); } } void TypeSpecifier() #TypeStringToken : { Token t; } { ( t = | t = | t = | t = | t = | t = | t = | t = | t = | t = | t = | t = ) { jjtThis.setValue(t.image); } } void TypeQualifier() #StringToken : { Token t; } { ( t = | t = ) { jjtThis.setValue(t.image); } } void InitDeclaratorList() : {} { InitDeclarator() ("," InitDeclarator())* } void InitDeclarator() : {} { Declarator() [ "=" Initializer() ] } void SpecifierQualifierList() : {} { TypeSpecifier() [ LOOKAHEAD(SpecifierQualifierList()) SpecifierQualifierList() ]| TypeQualifier() [ LOOKAHEAD(SpecifierQualifierList()) SpecifierQualifierList() ] } void Declarator() : {} { [ Pointer() ] DirectDeclarator() } void DirectDeclarator() : {} { ( Identifier() | "(" Declarator() ")" ) ( "[" [ ConstantExpression() ] "]" | LOOKAHEAD(3) "(" ParameterTypeList() ")" | "(" [ IdentifierList() ] ")" )* } void Pointer() : {} { "*" [ TypeQualifierList() ] [ Pointer() ] } void TypeQualifierList() : {} { (TypeQualifier())+ } void ParameterTypeList() : {} { ParameterList() ["," "..." ] } void ParameterList() : {} { ParameterDeclaration() (LOOKAHEAD(2) "," ParameterDeclaration())* } void ParameterDeclaration() : {} { DeclarationSpecifiers() ( LOOKAHEAD(Declarator()) Declarator() | [ AbstractDeclarator() ] ) } void IdentifierList() : {} { Identifier() ("," Identifier())* } void Initializer() : {} { ( AssignmentExpression() | "{" InitializerList() [","] "}" ) } void InitializerList() : {} { Initializer() (LOOKAHEAD(2) "," Initializer())* } void TypeName() : {} { SpecifierQualifierList() [ AbstractDeclarator() ] } void AbstractDeclarator() : {} { ( LOOKAHEAD(3) Pointer() | [Pointer()] DirectAbstractDeclarator() ) } void DirectAbstractDeclarator() : {} { ( LOOKAHEAD(2) "(" AbstractDeclarator() ")" | "[" [ConstantExpression()] "]" | "(" [ParameterTypeList()] ")" ) ( "[" [ ConstantExpression() ] "]" | "(" [ ParameterTypeList() ] ")" )* } void Statement() : {} { ( LOOKAHEAD(Identifier() ":") LabeledStatement() | ExpressionStatement() | CompoundStatement() | SelectionStatement() | IterationStatement() | JumpStatement() ) } void LabeledStatement() : {} { ( Identifier() ":" Statement() | ConstantExpression() ":" Statement() | ":" Statement() ) } void ExpressionStatement() : {} { [ Expression() ] ";" } void CompoundStatement() : {} { "{" [ LOOKAHEAD(DeclarationList()) DeclarationList() ] [ StatementList() ] "}" } void StatementList() : {} { (Statement())+ } void SelectionStatement() : {} { ( "(" Expression() ")" Statement() [ LOOKAHEAD(2) Statement() ] | "(" Expression() ")" Statement() ) } void IterationStatement() : {} { ( "(" Expression() ")" Statement() | Statement() "(" Expression() ")" ";" | "(" [ Expression() ] ";" [ Expression() ] ";" [ Expression() ] ")" Statement() ) } void JumpStatement() : {} { ( Identifier() ";" | ";" | ";" | [ Expression() ] ";" ) } void Expression() : {} { AssignmentExpression() ( "," AssignmentExpression() )* | DeclarationSpecifiers() InitDeclaratorList() } void AssignmentExpression() : {} { LOOKAHEAD(UnaryExpression() AssignmentOperator()) UnaryExpression() AssignmentOperator() AssignmentExpression() | LOOKAHEAD(3) ConditionalExpression() } void AssignmentOperator() #StringToken : { Token t; } { ( t = "=" | t = "*=" | t = "/=" | t = "%=" | t = "+=" | t = "-=" | t = "<<=" | t = ">>=" | t = "&=" | t = "^=" | t = "|=" ) { jjtThis.setValue(t.image); } } void ConditionalExpression() : {} { LogicalORExpression() [ "?" Expression() ":" ConditionalExpression() ] } void ConstantExpression() : {} { ConditionalExpression() } void LogicalORExpression() : {} { LogicalANDExpression() [ "||" LogicalORExpression() ] } void LogicalANDExpression() : {} { InclusiveORExpression() [ "&&" LogicalANDExpression() ] } void InclusiveORExpression() : {} { ExclusiveORExpression() [ "|" InclusiveORExpression() ] } void ExclusiveORExpression() : {} { ANDExpression() [ "^" ExclusiveORExpression() ] } void ANDExpression() : {} { EqualityExpression() [ "&" ANDExpression() ] } void EqualityExpression() : {} { RelationalExpression() [ ( "==" | "!=" ) EqualityExpression() ] } void RelationalExpression() : {} { ShiftExpression() [ ( "<" | ">" | "<=" | ">=" ) RelationalExpression() ] } void ShiftExpression() : {} { AdditiveExpression() [ ( "<<" | ">>" ) ShiftExpression() ] } void AdditiveExpression() : {} { MultiplicativeExpression() [ AdditionOperator() AdditiveExpression() ] } void AdditionOperator() #StringToken : { Token t; } { ( t = "+" | t = "-" ) { jjtThis.setValue(t.image); } } void MultiplicativeExpression() : {} { CastExpression() [ ( "*" | "/" | "%" ) MultiplicativeExpression() ] } void CastExpression() : {} { ( LOOKAHEAD("(" TypeName() ")" CastExpression() ) "(" TypeName() ")" CastExpression() | UnaryExpression() ) } void UnaryExpression() : {} { ( LOOKAHEAD(3) PostfixExpression() | "++" UnaryExpression() | "--" UnaryExpression() | UnaryOperator() CastExpression() | ( LOOKAHEAD(UnaryExpression() ) UnaryExpression() | "(" TypeName() ")" ) ) } void UnaryOperator() : {} { ( "&" | "*" | "+" | "-" | "~" | "!" ) } void PostfixExpression() : { int choice = 0; } { PrimaryExpression() ( "[" Expression() "]" { choice = 1; } | "(" [ LOOKAHEAD(ArgumentExpressionList() ) ArgumentExpressionList() ] ")" { choice = 2; } | "." Identifier() { choice = 3; } | "->" Identifier() | { choice = 4; } "++" | { choice = 5; } "--" { choice = 6; } )* { jjtThis.choice = choice; } } void PrimaryExpression() : {} { ( Identifier() | Constant() | "(" Expression() ")" ) } void ArgumentExpressionList() : {} { AssignmentExpression() ( "," AssignmentExpression() )* } ASTStringToken Identifier() #StringToken : { Token r = null; ASTStringToken t = null; Token s = null; int choice; } { (LOOKAHEAD() r = { choice = 0; } | [ r = ] "<" t = Identifier() ">" [ s = ] { choice = 1; }) { if (choice == 1) { jjtThis.setValue((r != null ? r.image : "") + "<" + t.getValue() + ">" + (s != null ? s.image : "")); } else { jjtThis.setValue(r.image); } return jjtThis; } } void Constant() #StringToken : { Token t; } { (t = | t = | t = | t = | t = ) { jjtThis.setValue(t.image); } }