private static void ColorExpression(BfsExpGroup group) { if (group == null) return; foreach (IBfsExpNode node in group.Members) { //Put nodes here that should have been replaced in the TypeLinking phase. //if (node is BfsUnresolvedVariableExp) //throw new Exception("Unresolved variable expression detected!"); if (node is BfsExpGroup) ColorExpression(node as BfsExpGroup); else if (node is BfsBooleanExp) { BfsBooleanExp exp = node as BfsBooleanExp; ColorRange(exp.SourceRange, keywordcolor); } else if (node is BfsNumberExp) { BfsNumberExp val = node as BfsNumberExp; ColorRange(val.SourceRange, numbercolor); } else if (node is BfsOperator) { //TODO } else if (node is BfsValueExp) { BfsValueExp val = node as BfsValueExp; ColorRange(val.SourceRange, keywordcolor); } else if (node is BfsEnumAliasExp) { BfsEnumAliasExp val = node as BfsEnumAliasExp; ColorRange(val.SourceRange, enumaliascolor); } else if (node is BfsCallExp) { BfsCallExp val = node as BfsCallExp; ColorRange(val.NameSourceRange, keywordcolor); ColorRange(val.ArgumentSourceRange, typecolor); } } }
private void ConvertExpNodes( BfsExpGroup group, PegNode node ) { HashSet<EBinaryFileSchemaParser> groupnodes = new HashSet<EBinaryFileSchemaParser>( new EBinaryFileSchemaParser[] { EBinaryFileSchemaParser.logical, EBinaryFileSchemaParser.bitwise, EBinaryFileSchemaParser.comp, EBinaryFileSchemaParser.shift, EBinaryFileSchemaParser.sum, EBinaryFileSchemaParser.prod }); for (PegNode startnode = node.child_; startnode != null; startnode = startnode.next_) { //If the node is an operator: logical, bitwise, comparisson, bitshift, sum or product if (groupnodes.Contains(GetNodeId(startnode))) { //Recursively generate subgroups BfsExpGroup subgroup = new BfsExpGroup(); subgroup.SourceRange = GetSourceRange(startnode); ConvertExpNodes(subgroup, startnode); group.Members.Add(subgroup); } else { switch (GetNodeId(startnode)) { case EBinaryFileSchemaParser.number: BfsNumberExp number = new BfsNumberExp(); StoreSourceRange(startnode, number); number.Value = long.Parse( GetNodeText(startnode), CultureInfo.InvariantCulture ); group.Members.Add( number ); break; case EBinaryFileSchemaParser.named_value: BfsUnresolvedVariableExp var = new BfsUnresolvedVariableExp(); StoreSourceRange(startnode, var); for (PegNode v = startnode.child_; v != null; v = v.next_) var.NameHierarchy.Add(GetNodeText(v)); group.Members.Add(var); break; case EBinaryFileSchemaParser.call: BfsCallExp call = new BfsCallExp(); call.SourceRange = GetSourceRange(startnode); call.FunctionName = GetNodeText(startnode.child_); call.NameSourceRange = GetSourceRange(startnode.child_); call.FunctionArgument = GetNodeText(startnode.child_.next_); call.ArgumentSourceRange = GetSourceRange(startnode.child_.next_); group.Members.Add(call); break; //Operators default: BfsOperator op = new BfsOperator(); StoreSourceRange(startnode, op); op.Operator = GetNodeText(startnode); group.Members.Add(op); break; } } } }
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; }
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 CheckOperator(BfsExpGroup group, BfsOperator op) { //Just a formality check if the operators in the same group actually do belong to the same operator precedence-group if (group.OperatorPrecedenceLevel == BfsExpGroupOperatorLevel.Undetermined) group.OperatorPrecedenceLevel = op.PrecendenceLevel; else if (group.OperatorPrecedenceLevel != op.PrecendenceLevel) BfsCompiler.ReportError(op.SourceRange,"Mixed operator-precedence groups! '" + op + "' doesn't belong in '"+group.OperatorPrecedenceLevel+"'"); }