Files
GhidRust/src/main/java/ghidrust/decompiler/parser/c/gen/c.jjt
Dhruv Maroo 425c633efe Add decompilation logic for more constructs
* Function calls decompiled correctly
    * Add boolean type and boolean constants in the grammar
    * Allow angled braces in identifier names
    * Overload the `transpile` to also allow input streams
    * Update the generate script accordingly
2023-04-23 17:11:26 +05:30

517 lines
11 KiB
Plaintext

/*
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
}
<PREPROCESSOR_OUTPUT> SKIP:
{
"\n" : DEFAULT
}
<PREPROCESSOR_OUTPUT> MORE:
{
"\\\n"
|
"\\\r\n"
|
< ~[] >
}
TOKEN : {
<INTEGER_LITERAL: <DECIMAL_LITERAL> (["l","L"])? | <HEX_LITERAL> (["l","L"])? | <OCTAL_LITERAL> (["l","L"])?>
| <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])*>
| <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+>
| <#OCTAL_LITERAL: "0" (["0"-"7"])*>
| <FLOATING_POINT_LITERAL: (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])? | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])? | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])? | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]>
| <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+>
| <CHARACTER_LITERAL: "\'" (~["\'","\\","\n","\r"] | "\\" (["n","t","b","r","f","\\","\'","\""] | ["0"-"7"] (["0"-"7"])? | ["0"-"3"] ["0"-"7"] ["0"-"7"])) "\'">
| <STRING_LITERAL: "\"" ( ~["\"","\\","\n","\r"] | "\\" ( ["n","t","b","r","f","\\","\'","\""] | ["0"-"7"] (["0"-"7"])? | ["0"-"3"] ["0"-"7"] ["0"-"7"] | ( ["\n","\r"] | "\r\n")))* "\"">
| <BOOLEAN: "true" | "false">
| <UNDEFINED_TYPE: "undefined" (<DECIMAL_LITERAL>)?> // Ghidra specific unknown type
}
TOKEN : {
<CONTINUE: "continue"> |
<VOLATILE: "volatile"> |
<REGISTER: "register"> |
<UNSIGNED: "unsigned"> |
<TYPEDEF: "typedef"> |
<DFLT: "default"> |
<DOUBLE: "double"> |
<SIZEOF: "sizeof"> |
<SWITCH: "switch"> |
<RETURN: "return"> |
<EXTERN: "extern"> |
<STRUCT: "struct"> |
<STATIC: "static"> |
<SIGNED: "signed"> |
<WHILE: "while"> |
<BREAK: "break"> |
<UNION: "union"> |
<CONST: "const"> |
<FLOAT: "float"> |
<SHORT: "short"> |
<ELSE: "else"> |
<CASE: "case"> |
<LONG: "long"> |
<ENUM: "enum"> |
<AUTO: "auto"> |
<VOID: "void"> |
<CHAR: "char"> |
<GOTO: "goto"> |
<FOR: "for"> |
<INT: "int"> |
<IF: "if"> |
<DO: "do"> |
<BOOL_TYPE: "bool"> |
<CODE: "code"> // code ptr, Ghidra specific
}
TOKEN : {
<IDENTIFIER: (<LETTER> | <SEPARATOR> <SEPARATOR>) (<LETTER> | <SEPARATOR> <SEPARATOR> | <DIGIT>)*>
| <#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 = <AUTO> | t = <REGISTER> | t = <STATIC> | t = <EXTERN> | t = <TYPEDEF> )
{
jjtThis.setValue(t.image);
}
}
void TypeSpecifier() #TypeStringToken :
{
Token t;
}
{
( t = <VOID> | t = <CHAR> | t = <SHORT> | t = <INT> | t = <LONG> | t = <FLOAT> | t = <DOUBLE> | t = <SIGNED> |
t = <UNSIGNED> | t = <BOOL_TYPE> | t = <CODE> | t = <UNDEFINED_TYPE> )
{
jjtThis.setValue(t.image);
}
}
void TypeQualifier() #StringToken :
{
Token t;
}
{
( t = <CONST> | t = <VOLATILE> )
{
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() |
<CASE> ConstantExpression() ":" Statement() |
<DFLT> ":" Statement() )
}
void ExpressionStatement() : {}
{
[ Expression() ] ";"
}
void CompoundStatement() : {}
{
"{" [ LOOKAHEAD(DeclarationList()) DeclarationList() ]
[ StatementList() ]
"}"
}
void StatementList() : {}
{
(Statement())+
}
void SelectionStatement() : {}
{
( <IF> "(" Expression() ")" Statement() [ LOOKAHEAD(2) <ELSE> Statement() ] |
<SWITCH> "(" Expression() ")" Statement() )
}
void IterationStatement() : {}
{
( <WHILE> "(" Expression() ")" Statement() |
<DO> Statement() <WHILE> "(" Expression() ")" ";" |
<FOR> "(" [ Expression() ] ";" [ Expression() ] ";" [ Expression() ] ")" Statement() )
}
void JumpStatement() : {}
{
( <GOTO> Identifier() ";" |
<CONTINUE> ";" |
<BREAK> ";" |
<RETURN> [ 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() |
<SIZEOF> ( 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(<IDENTIFIER>) r = <IDENTIFIER> { choice = 0; } | [ r = <IDENTIFIER> ] "<" t = Identifier() ">" [ s = <IDENTIFIER> ] { 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 = <INTEGER_LITERAL> | t = <FLOATING_POINT_LITERAL> | t = <CHARACTER_LITERAL> | t = <STRING_LITERAL> | t = <BOOLEAN>)
{
jjtThis.setValue(t.image);
}
}