private static void CheckActionList(IList<IBfsAction> actions, IBfsDataBlock block) { if (actions == null) return; for( int index = 0; index < actions.Count; index++) { IBfsAction action = actions[index]; if (action is BfsActionUnresolvedAssignment) { BfsActionUnresolvedAssignment unresolved = action as BfsActionUnresolvedAssignment; BfsActionAssignment assignment = new BfsActionAssignment(); assignment.Expression = unresolved.Expression; assignment.SourceRange = unresolved.SourceRange; if (block.LocalFields.ContainsKey(unresolved.UnresolvedVariableName)) assignment.LocalVariable = block.LocalFields[unresolved.UnresolvedVariableName]; else BfsCompiler.ReportError(assignment.SourceRange, "Could not find local variable: '"+unresolved.UnresolvedVariableName+"'"); actions.Insert(index, assignment); actions.Remove(action); } } }
private void ReadDataBlock(IBfsDataBlock block, TreeNode parent) { if (block is BfsStruct) ReadStruct(block as BfsStruct, parent); else if (block is BfsEnum) ReadEnum(block as BfsEnum, parent); else if (block is BfsBitfield) ReadBitField(block as BfsBitfield, parent); }
public bool MakeActionList(IBfsDataBlock owner, List<string> actionList, IList<IBfsAction> actions) { //This loop is terminated when encountering an error statement. foreach (IBfsAction action in actions) { if (action is BfsActionAssignment) { BfsActionAssignment assignment = action as BfsActionAssignment; actionList.Add( owner.Name.ToLower() + "." + assignment.LocalVariable + " = " + CSHelper.MakeExpression(assignment.Expression,owner)+";"); } else if (action is BfsActionOutput) { BfsActionOutput output = action as BfsActionOutput; if (output.FunctionName == "error") { actionList.Add("throw new Exception(" + output.Argument + ");"); return false; } else if (output.FunctionName == "warning") actionList.Add("//WARNING: " + output.Argument); } } return true; }
private void CheckExpression(BfsExpression expression, IBfsDataBlock block) { CheckExpressionNode(expression, expression.ExpressionGroup, block); CheckForEnumMembers(expression.ExpressionGroup, block); }
private void CheckForEnumMembers(BfsExpGroup group, IBfsDataBlock block) { //For each expression variable in the expression group for (int index = 0; index < group.Members.Count; index++) { //Recursively visit the sub-expressions IBfsExpNode node = group.Members[index]; if (node is BfsExpGroup) { CheckForEnumMembers(node as BfsExpGroup, block); continue; } //Ignore irrelevant objects (operators and known variables) if (!(node is BfsExpressionVariable)) continue; BfsExpressionVariable expressionvar = node as BfsExpressionVariable; if (!(expressionvar.LastField is BfsExpressionUnknown)) continue; //Only interested in resolving the BfsExpressionUnknowns BfsExpressionUnknown unknown = expressionvar.LastField as BfsExpressionUnknown; BfsExpressionVariable candidatevar = null; bool resolvedTheVar = false; BfsOperator op = null; if (index >= 2 && group.Members[index - 2] is BfsExpressionVariable) { op = group.Members[index - 1] as BfsOperator; candidatevar = group.Members[index - 2] as BfsExpressionVariable; } else if (index + 2 < group.Members.Count && group.Members[index + 2] is BfsExpressionVariable) { op = group.Members[index + 1] as BfsOperator; candidatevar = group.Members[index + 2] as BfsExpressionVariable; } if ( candidatevar != null && candidatevar.LastField is BfsStructField && (candidatevar.LastField as BfsStructField).FieldType is BfsNamedType) { BfsStructField field = candidatevar.LastField as BfsStructField; BfsNamedType fieldtype = field.FieldType as BfsNamedType; if (fieldtype.DataBlock is BfsEnum && (fieldtype.DataBlock as BfsEnum).EnumAliases.ContainsKey(unknown.Name)) { resolvedTheVar = true; BfsEnumFieldAlias enumalias = (fieldtype.DataBlock as BfsEnum).EnumAliases[unknown.Name]; BfsEnumAliasExp aliasExp = new BfsEnumAliasExp(); aliasExp.EnumBlock = fieldtype.DataBlock as BfsEnum; aliasExp.Alias = enumalias; aliasExp.SourceRange = unknown.SourceRange; //Only allow equality operators on EnumAliases if (op.Operator == "==" || op.Operator == "!=") { group.Members.Insert(index, aliasExp); group.Members.Remove(node); } else BfsCompiler.ReportError(op.SourceRange, "The operator '"+op.Operator+"' cannot be used with the enum alias '"+enumalias.Name+"'. Only == and != are allowed."); expressionvar.LastField = aliasExp; } } if(!resolvedTheVar) BfsCompiler.ReportError(unknown.SourceRange, "Unresolved variable name: '" + unknown.Name + "'"); } }
private void CheckExpressionNode(BfsExpression exp, BfsExpGroup group, IBfsDataBlock block) { for (int index = 0; index < group.Members.Count; index++) { IBfsExpNode node = group.Members[index]; if (node is BfsOperator) continue; if (node is BfsExpGroup) CheckExpressionNode(exp, node as BfsExpGroup, block); else if (node is BfsCallExp) { BfsCallExp call = node as BfsCallExp; if (call.FunctionName != "sizeof") { BfsCompiler.ReportError(call.NameSourceRange, "Unknown function: '" + call.FunctionName + "'"); break; } //If the argument in sizeof(data-block) can be found. else if (schema.DataBlocks.ContainsKey(call.FunctionArgument)) { if (schema.DataBlocks[call.FunctionArgument] is IBfsStructType) CalculateStructSize(call.SourceRange, schema.DataBlocks[call.FunctionArgument] as IBfsStructType); call.SizeInBytes = schema.DataBlocks[call.FunctionArgument].SizeInBytes; continue; } else BfsCompiler.ReportError(call.ArgumentSourceRange, "Could not find the data-block: '"+call.FunctionArgument+"'"); } else if (node is BfsUnresolvedVariableExp) { BfsUnresolvedVariableExp unresolved = node as BfsUnresolvedVariableExp; //Boolean(true/false)? if (unresolved.ToString() == "true" || unresolved.ToString() == "false") { BfsBooleanExp booleanExp = new BfsBooleanExp(); booleanExp.SourceRange = unresolved.SourceRange; booleanExp.Value = (unresolved.ToString() == "true") ? true : false; group.Members.Insert(index, booleanExp); group.Members.Remove(unresolved); continue; } //Value expression? if (unresolved.ToString() == "value") { if (block is IBfsConsumptionType) { BfsValueExp valueExp = new BfsValueExp(); valueExp.SourceRange = unresolved.SourceRange; group.Members.Insert(index, valueExp); group.Members.Remove(unresolved); continue; } else { BfsCompiler.ReportError(unresolved.SourceRange, "The 'value' expression variable may only be used in consumed types."); continue; } } //Else it is a named variable. BfsExpressionVariable namedVar = new BfsExpressionVariable(); namedVar.SourceRange = node.SourceRange; group.Members.Insert(index, namedVar); group.Members.Remove(node); string containertype = block.ToString(); //Check hiearchy IBfsDataBlock container = block; for (int i = 0; i < unresolved.NameHierarchy.Count; i++) { string varname = unresolved.NameHierarchy[i]; if (container == null) { BfsCompiler.ReportError(node.SourceRange, "Variable '" + unresolved.NameHierarchy[i - 1] + "' cannot contain any variables because it of type: " + containertype); break; } if (container.LocalFields.ContainsKey(varname)) { namedVar.NameHierarchy.Add(container.LocalFields[varname]); containertype = " local variable"; container = null; } else if (container is IBfsStructType && (container as IBfsStructType).StructFields.ContainsKey(varname)) { IBfsType type = (container as IBfsStructType).StructFields[varname].FieldType; IBfsNamedField namedtype = (container as IBfsStructType).StructFields[varname]; if (type is BfsNamedType) { container = (type as BfsNamedType).DataBlock; if (container is IBfsConsumptionType) { IBfsConsumptionType consumed = container as IBfsConsumptionType; namedtype.PrimitiveType = consumed.PrimitiveType; } namedVar.NameHierarchy.Add(namedtype); } else if (type is BfsPrimitiveType) { containertype = "primitive type"; namedVar.NameHierarchy.Add(namedtype); container = null; } else if (type is BfsFunctionType) { containertype = "function type"; namedVar.NameHierarchy.Add(namedtype); container = null; } else BfsCompiler.ReportError(container.SourceRange, "Unexpected error. Unknown type."); } else { containertype = "unknown variable or enum-alias."; BfsExpressionUnknown unknown = new BfsExpressionUnknown(); unknown.Name = varname; unknown.SourceRange = unresolved.SourceRange; namedVar.NameHierarchy.Add(unknown); container = null; } } //Building map over dependant variables. exp.DependantVariables.Add(namedVar); } } }
public CodeClass MakeClass(IBfsDataBlock block) { //Append all local fields no matter the type CodeClass codeClass = new CodeClass(block.Name); foreach (BfsLocalField localField in block.LocalFieldList) codeClass.CodeFields.Add( localField.PrimitiveType.PrimitiveType.ToString().ToLower() + " " + localField.Name + ";"); if (block is BfsStruct) { BfsStruct dataStruct = block as BfsStruct; MakeStruct(codeClass, dataStruct); return codeClass; } else if (block is BfsEnum) { BfsEnum dataEnum = block as BfsEnum; MakeEnum(codeClass, dataEnum); return codeClass; } else if (block is BfsBitfield) { BfsBitfield dataField = block as BfsBitfield; MakeBitfield(codeClass, dataField); return codeClass; } else if (block is BfsAbsOffset || block is BfsRelOffset) { BfsCompiler.ReportError(block.BlockTypeSourceRange,"Not yet implemented: Support for abs_offset or rel_offset!"); } return null; }
private void ConvertLocalField(PegNode node, IBfsDataBlock block) { BfsLocalField localfield = new BfsLocalField(); StoreSourceRange(node, localfield); localfield.Name = GetNodeText(node.child_); localfield.PrimitiveType = ConvertPrimitiveType(node.child_.next_); node = node.child_.next_.next_; if (node != null && GetNodeId(node) == EBinaryFileSchemaParser.expression) localfield.AssignmentExpression = ConvertExpression(node); block.LocalFieldList.Add(localfield); }
//Recursive visit of expression groups public static string VisitExpGroup(BfsExpGroup group, IBfsDataBlock owner) { StringBuilder b = new StringBuilder(); b.Append("("); for (int i = 0; i < group.Members.Count; i++) { IBfsExpNode node = group.Members[i]; if (node is BfsExpGroup) b.Append(VisitExpGroup(node as BfsExpGroup, owner)); else if (node is BfsExpressionVariable) { BfsExpressionVariable expVar = node as BfsExpressionVariable; b.Append(owner.Name.ToLower()); foreach (IBfsNamedField namedField in expVar.NameHierarchy) b.Append("." + namedField.Name); //Only append this last reading into the enum type if the value is being compared against an EnumAliasExp if ((group.Members.Count > i + 2 && group.Members[i + 2] is BfsEnumAliasExp) || (i >= 2 && group.Members[i - 2] is BfsEnumAliasExp)) b.Append("." + expVar.NameHierarchy[expVar.NameHierarchy.Count - 1]); } else if (node is BfsEnumAliasExp) { //TODO BfsEnumAliasExp enumAliasExp = node as BfsEnumAliasExp; b.Append(enumAliasExp.EnumBlock.Name + "." + enumAliasExp.EnumBlock.Name + "Enum." + enumAliasExp.Alias.Name); } else if (node is BfsLocalField) { BfsLocalField localField = node as BfsLocalField; b.Append(localField.Name); } else b.Append(" " + node + " "); } b.Append(")"); return b.ToString(); }
//Output C# code for an expression public static string MakeExpression(BfsExpression expression, IBfsDataBlock owner) { string exp = VisitExpGroup(expression.ExpressionGroup, owner); //Trim unnessecary parenthesis (BROKEN! not sure the parenthethis are matching) /*while (exp.StartsWith("(") && exp.EndsWith(")")) exp = exp.Substring(1, exp.Length - 2);*/ return exp.Trim(); }
private void CheckGroup( BfsExpGroup group, IBfsDataBlock block ) { foreach (IBfsExpNode node in group.Members) { if (node is BfsNumberExp) CheckType(group, BfsPrimitiveTypeEnum.Int, block); else if (node is BfsBooleanExp) CheckType(group, BfsPrimitiveTypeEnum.Bool, block); else if (node is BfsCallExp) CheckType(group, BfsPrimitiveTypeEnum.CallExpression, block); else if (node is BfsExpressionVariable) { BfsExpressionVariable expvar = node as BfsExpressionVariable; //Check if the type of the variable is a function type (like ascii("Hello")) if (expvar.LastField is BfsStructField) if ((expvar.LastField as BfsStructField).FieldType is BfsFunctionType) BfsCompiler.ReportError(expvar.SourceRange, "Cannot have function types in expressions!"); CheckType(group, expvar.PrimitiveType, block); //Checking if any part of an expression variable references a variable that is array-extended foreach( IBfsNamedField field in expvar.NameHierarchy ) if (field is BfsStructField) { BfsStructField f = field as BfsStructField; if (f != null) { if (f.FieldType.ArrayExtension != null) BfsCompiler.ReportError(expvar.SourceRange, "Cannot use array-extended type in expression: '" + expvar + "'"); if (f.Skip) BfsCompiler.ReportError(expvar.SourceRange, "The variable '" + expvar + "' has been marked as skipped data and therefore cannot be used in expressions."); } } } else if (node is BfsEnumAliasExp) CheckType(group, BfsPrimitiveTypeEnum.EnumMember, block); else if (node is BfsOperator) CheckOperator(group, node as BfsOperator); else if (node is BfsExpGroup) { BfsExpGroup g = node as BfsExpGroup; CheckGroup(g, block); //Compare the subgroups type to the parents (this) type. CheckType(group, g.PrimitiveType, block); //If the group consists of comparissons then the type of the group must be boolean. if (g.OperatorPrecedenceLevel == BfsExpGroupOperatorLevel.Comparisson) group.PrimitiveType = BfsPrimitiveTypeEnum.Bool; } } }
private void CheckExpression(BfsExpression expression, IBfsDataBlock block) { CheckGroup(expression.ExpressionGroup, block); //BfsCompiler.ReportWarning(expression.ExpressionGroup.SourceRange, expression.ToString() + ": " + expression.PrimitiveType); }
private void CheckType(BfsExpGroup group, BfsPrimitiveTypeEnum type, IBfsDataBlock block) { //If boolean and non-boolean types are mixed. if((group.PrimitiveType == BfsPrimitiveTypeEnum.Bool && type > BfsPrimitiveTypeEnum.Bool)) BfsCompiler.ReportError(group.SourceRange, "Cannot mix boolean and " + type + " types"); else if(type == BfsPrimitiveTypeEnum.Bool && group.PrimitiveType > BfsPrimitiveTypeEnum.Bool) BfsCompiler.ReportError(group.SourceRange, "Cannot mix boolean and " + group.PrimitiveType + " types"); //if (type == BfsPrimitiveTypeEnum.FunctionType || group.PrimitiveType == BfsPrimitiveTypeEnum.FunctionType) // BfsCompiler.ReportError(group.SourceRange, "You cannot use function typed variables in expressions"); if (type == BfsPrimitiveTypeEnum.Undetermined) BfsCompiler.ReportError(group.SourceRange,"Undetermined type of variable"); //If all is well then it will pick the largest type that can contain the variable. //Hiearchy: Undetermined,Bool,Ubyte,Sbyte,Ushort,Short,Uint,Int,Ulong,Long BfsPrimitiveTypeEnum a = group.PrimitiveType; BfsPrimitiveTypeEnum b = type; group.PrimitiveType = (a > b) ? a : b; }