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); } } }
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 + "'"); } }
//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(); }