static void VerifyFieldCount(LfdLine line, Int32 fieldCount) { int lineFieldCount = (line.fields == null) ? 0 : line.fields.Length; if (lineFieldCount != fieldCount) { throw new ParseException(line, "Expected line to have {0} fields but had {1}", fieldCount, lineFieldCount); } }
// Assumption: filename already exists and is already verified to be a file public static void LoadFile(MetabuildProject metabuild, String filename) { Console.WriteLine("[DEBUG] Metabuild.LoadFile \"{0}\"", filename); String relativeDir = null; using (LfdTextReader reader = new LfdTextReader(new StreamReader(new FileStream( filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))) { LfdParser parser = new LfdParser(reader, filename); LfdLine line = parser.reader.ReadLineIgnoreComments(); for (; ;) { if (line == null) { return; } if (line.id == "Import") { parser.errors.EnforceFieldCount(line, 1); MetabuildUnit.LoadDirOrFile(metabuild, line.fields[0]); line = parser.reader.ReadLineIgnoreComments(); } else if (line.id == "CSharpProject") { if (relativeDir == null) { relativeDir = Path.GetDirectoryName(filename); } line = CSharpProject.Parse(metabuild, parser, line, false, relativeDir); } else if (line.id == "CSharpTestProject") { if (relativeDir == null) { relativeDir = Path.GetDirectoryName(filename); } line = CSharpProject.Parse(metabuild, parser, line, true, relativeDir); } else if (line.id == "GeneratePathPrefix") { parser.errors.EnforceFieldCount(line, 1); if (metabuild.generatePathPrefix != null) { throw parser.errors.Error(line, "GeneratePathPrefix was set more than once"); } metabuild.generatePathPrefix = line.fields[0]; line = parser.reader.ReadLineIgnoreComments(); } else { throw parser.errors.Error(line, "unknown directive '{0}'", line.id); } } } }
public void EnforceFieldCount(LfdLine line, UInt32 expected) { UInt32 fieldsLength = (line.fields == null) ? 0 : (UInt32)line.fields.Length; if (fieldsLength != expected) { throw Error(line, "property '{0}' requires {1} field(s) but got {2}", line.id, expected, fieldsLength); } }
public static PdlArrayType Parse(LfdLine line, String sizeTypeString) { if (String.IsNullOrEmpty(sizeTypeString)) { return(BasedOnCommandLength); } Char firstChar = sizeTypeString[0]; if (firstChar >= '0' && firstChar <= '9') { UInt32 fixedLength; if (!UInt32.TryParse(sizeTypeString, out fixedLength)) { throw new ParseException(line, "First character of array size type '{0}' was a number but coult not parse it as a number", sizeTypeString); } return(new PdlFixedLengthArrayType(fixedLength)); } PdlArraySizeTypeEnum typeEnum; try { typeEnum = (PdlArraySizeTypeEnum)Enum.Parse(typeof(PdlArraySizeTypeEnum), sizeTypeString); } catch (ArgumentException) { throw new ParseException(line, "The array size type inside the brackets '{0}' is invalid, expected 'Byte','UInt16','UInt24' or 'UInt32'", sizeTypeString); } if (typeEnum == PdlArraySizeTypeEnum.Fixed) { throw new InvalidOperationException("Fixed is an invalid array size type, use an unsigned integer to specify a fixed length array"); } switch (typeEnum) { case PdlArraySizeTypeEnum.BasedOnCommand: return(BasedOnCommandLength); case PdlArraySizeTypeEnum.Byte: return(ByteLength); case PdlArraySizeTypeEnum.UInt16: return(UInt16Length); case PdlArraySizeTypeEnum.UInt24: return(UInt24Length); case PdlArraySizeTypeEnum.UInt32: return(UInt32Length); case PdlArraySizeTypeEnum.UInt64: return(UInt64Length); } throw new InvalidOperationException(String.Format("CodeBug: Unhandled PdlArraySizeTypeEnum {0}", typeEnum)); }
static void ParseEnumOrFlagsDefinition(BinaryFormatFile file, LfdLineReader reader, NamedObjectDefinition currentObjectDefinition, LfdLine enumDefinitionLine, out LfdLine nextLine, Boolean isFlagsDefinition) { String enumOrFlagsString = isFlagsDefinition ? "Flags" : "Enum"; VerifyFieldCount(enumDefinitionLine, 2); String underlyingIntegerTypeString = enumDefinitionLine.fields[0]; BinaryFormatType underlyingIntegerType = BinaryFormatTypeExtensions.ParseIntegerType(underlyingIntegerTypeString); EnumOrFlagsDefinition definition; try { definition = new EnumOrFlagsDefinition(file, isFlagsDefinition, currentObjectDefinition, underlyingIntegerType, enumDefinitionLine.fields[1]); } catch (FormatException e) { throw new ParseException(enumDefinitionLine, e.Message); } Debug(" Entering {0} '{1}' (IntegerType={2})", enumOrFlagsString, enumDefinitionLine.id, definition.underlyingIntegerType); // // Read enum values // nextLine = reader.ReadLineIgnoreComments(); while (nextLine != null && nextLine.parent == enumDefinitionLine) { LfdLine enumValueLine = nextLine; VerifyFieldCount(enumValueLine, 1); Debug(" {0} {1} {2}", enumOrFlagsString, enumValueLine.id, enumValueLine.fields[0]); if (isFlagsDefinition) { definition.Add(new FlagsValueDefinition(enumValueLine.fields[0], Byte.Parse(enumValueLine.id))); } else { definition.Add(new EnumValueDefinition(enumValueLine.id, enumValueLine.fields[0])); } nextLine = reader.ReadLineIgnoreComments(); } Debug(" Exiting {0} '{1}'", enumOrFlagsString, definition.typeName); }
public static void ParsePdlFile(PdlFile pdlFile, LfdReader reader) { LfdLine nextLine = reader.ReadLineIgnoreComments(); while (nextLine != null) { if (nextLine.id.Equals("enum", StringComparison.OrdinalIgnoreCase)) { ParseEnumOrFlagsDefinition(pdlFile, reader, null, nextLine, out nextLine, false); } else if (nextLine.id.Equals("flags", StringComparison.OrdinalIgnoreCase)) { ParseEnumOrFlagsDefinition(pdlFile, reader, null, nextLine, out nextLine, true); } else { LfdLine currentCommandLine = nextLine; VerifyFieldCount(currentCommandLine, 0); NamedObjectDefinition objectDefinition = ParseObjectDefinition(pdlFile, reader, currentCommandLine, null, currentCommandLine.id, out nextLine); } } }
public ParseException(LfdLine line, String reason) : base(String.Format("Parse Error (line {0}): {1}\n at line: \"{2}\"", line.actualLineNumber, reason, line.ToString())) { }
public static void ParseObjectFieldLine(PdlFile pdlFile, LfdReader reader, NamedObjectDefinition containingNamedObject, IFieldContainer containingObject, LfdLine fieldLine, out LfdLine nextLine) { // // Check if it is only a definition (enum or flag) // if (fieldLine.id.Equals("enum", StringComparison.OrdinalIgnoreCase)) { ParseEnumOrFlagsDefinition(pdlFile, reader, containingNamedObject, fieldLine, out nextLine, false); return; } if (fieldLine.id.Equals("flags", StringComparison.OrdinalIgnoreCase)) { ParseEnumOrFlagsDefinition(pdlFile, reader, containingNamedObject, fieldLine, out nextLine, true); return; } String typeString = fieldLine.id; // // The rest of the fields can have arrayParse the Array Size Type // PdlArrayType arrayType; int indexOfOpenBracket = typeString.IndexOf('['); if (indexOfOpenBracket < 0) { arrayType = null; } else { String arraySizeTypeString = typeString.Substring(indexOfOpenBracket + 1); typeString = typeString.Remove(indexOfOpenBracket); int indexOfCloseBracket = arraySizeTypeString.IndexOf(']'); if (indexOfCloseBracket < 0) { throw new ParseException(fieldLine, "Found an opening bracket '[' without a closing bracket"); } if (indexOfCloseBracket != arraySizeTypeString.Length - 1) { throw new ParseException(fieldLine, "The array size type '{0}' had a closing bracket, but the closing bracket was not the last character", arraySizeTypeString); } arraySizeTypeString = arraySizeTypeString.Remove(indexOfCloseBracket); arrayType = PdlArrayType.Parse(fieldLine, arraySizeTypeString); } // // Parse object inline definition // if (typeString.Equals("object", StringComparison.OrdinalIgnoreCase)) { VerifyFieldCount(fieldLine, 1); String objectDefinitionAndFieldName = fieldLine.fields[0]; NamedObjectDefinition fieldObjectDefinition = ParseObjectDefinition(pdlFile, reader, fieldLine, containingNamedObject, objectDefinitionAndFieldName, out nextLine); containingObject.AddField(new ObjectDefinitionField( new ObjectTypeReference(objectDefinitionAndFieldName, fieldObjectDefinition, arrayType), objectDefinitionAndFieldName)); return; } // // Check if it is a serializer // if (fieldLine.id.Equals("serializer", StringComparison.OrdinalIgnoreCase)) { VerifyFieldCount(fieldLine, 2); String serializerLengthTypeString = fieldLine.fields[0]; String serializerFieldName = fieldLine.fields[1]; PdlArrayType serializerLengthType = PdlArrayType.Parse(fieldLine, serializerLengthTypeString); containingObject.AddField(new ObjectDefinitionField(new SerializerTypeReference(serializerLengthType, arrayType), serializerFieldName)); nextLine = reader.ReadLineIgnoreComments(); return; } // // Check if it is an 'if' type // if (typeString.Equals("if", StringComparison.OrdinalIgnoreCase)) { VerifyFieldCount(fieldLine, 1); IfTypeReference ifType = ParseIf(pdlFile, reader, fieldLine, containingNamedObject, out nextLine); containingObject.AddField(new ObjectDefinitionField(ifType, null)); return; } // // Check if it is a switch type // if (typeString.Equals("switch", StringComparison.OrdinalIgnoreCase)) { VerifyFieldCount(fieldLine, 1); SwitchTypeReference switchType = ParseSwitch(pdlFile, reader, fieldLine, containingNamedObject, out nextLine); containingObject.AddField(new ObjectDefinitionField(switchType, null)); return; } // // The field is only one line, so read the next line now for the caller // nextLine = reader.ReadLineIgnoreComments(); EnumOrFlagsDefinition enumDefinition = pdlFile.TryGetEnumOrFlagsDefinition(containingNamedObject, typeString); if (enumDefinition != null) { VerifyFieldCount(fieldLine, 1); containingObject.AddField(new ObjectDefinitionField(new EnumOrFlagsTypeReference(typeString, enumDefinition, arrayType), fieldLine.fields[0])); return; } // Check if it is an object type NamedObjectDefinition objectDefinition = pdlFile.TryGetObjectDefinition(containingNamedObject, typeString); if (objectDefinition != null) { if (fieldLine.fields == null || fieldLine.fields.Length <= 0) { // // Add each field from the object definition to the current object definition // List <ObjectDefinitionField> objectDefinitionFields = objectDefinition.Fields; for (int i = 0; i < objectDefinitionFields.Count; i++) { ObjectDefinitionField fieldDefinition = objectDefinitionFields[i]; containingObject.AddField(fieldDefinition); } } else if (fieldLine.fields.Length == 1) { containingObject.AddField(new ObjectDefinitionField( new ObjectTypeReference(typeString, objectDefinition, arrayType), fieldLine.fields[0])); } else { throw new ParseException(fieldLine, "Expected line to have 0 or 1 fields but had {0}", fieldLine.fields.Length); } return; } // // Check if it a string type // if (typeString.Equals("ascii", StringComparison.OrdinalIgnoreCase)) { VerifyFieldCount(fieldLine, 1); containingObject.AddField(new ObjectDefinitionField( new AsciiTypeReference(typeString, arrayType), fieldLine.fields[0])); return; } // // It must be an integer type // VerifyFieldCount(fieldLine, 1); PdlType type; try { type = (PdlType)Enum.Parse(typeof(PdlType), typeString, true); } catch (ArgumentException) { throw new FormatException(String.Format("Unknown Pdl Type '{0}'", typeString)); } if (!type.IsIntegerType()) { throw new InvalidOperationException(String.Format("Unhandled PDL type '{0}'", type)); } containingObject.AddField(new ObjectDefinitionField(new IntegerTypeReference(type, arrayType), fieldLine.fields[0])); }
static NamedObjectDefinition ParseObjectDefinition(PdlFile pdlFile, LfdReader reader, LfdLine objectDefinitionLine, NamedObjectDefinition currentObjectDefinition, String objectDefinitionName, out LfdLine nextLine) { NamedObjectDefinition objectDefinition = new NamedObjectDefinition(pdlFile, objectDefinitionName, objectDefinitionName.ToLowerInvariant(), currentObjectDefinition); Debug("Entering Object Definition '{0}'", objectDefinition.name); nextLine = reader.ReadLineIgnoreComments(); while (nextLine != null && nextLine.parent == objectDefinitionLine) { ParseObjectFieldLine(pdlFile, reader, objectDefinition, objectDefinition, nextLine, out nextLine); } objectDefinition.CalculateFixedSerializationLength(); return(objectDefinition); }
static SwitchTypeReference ParseSwitch(PdlFile pdlFile, LfdReader reader, LfdLine switchLine, NamedObjectDefinition containingNamedObject, out LfdLine nextLine) { List <Case> cases = new List <Case>(); String switchFieldString = switchLine.fields[0]; Debug("Entering Switch Definition '{0}'", switchFieldString); nextLine = reader.ReadLineIgnoreComments(); while (nextLine != null && nextLine.parent == switchLine) { Boolean isCase = nextLine.id.Equals("case", StringComparison.OrdinalIgnoreCase); if (!isCase && !nextLine.id.Equals("default", StringComparison.OrdinalIgnoreCase)) { throw new FormatException(String.Format("Expected 'Case' or 'Default' but got '{0}'", nextLine)); } VerifyFieldCount(nextLine, isCase ? 1 : 0); LfdLine currentCaseLine = nextLine; String currentCaseValueString = isCase ? nextLine.fields[0] : null; ObjectDefinition currentCaseObjectDefinition = new ObjectDefinition(pdlFile); nextLine = reader.ReadLineIgnoreComments(); while (nextLine != null && nextLine.parent == currentCaseLine) { ParseObjectFieldLine(pdlFile, reader, containingNamedObject, currentCaseObjectDefinition, nextLine, out nextLine); } currentCaseObjectDefinition.CalculateFixedSerializationLength(); cases.Add(new Case(currentCaseValueString, currentCaseObjectDefinition)); } return(new SwitchTypeReference(switchFieldString, cases)); }
static IfTypeReference ParseIf(PdlFile pdlFile, LfdReader reader, LfdLine ifLine, NamedObjectDefinition containingNamedObject, out LfdLine nextLine) { Case trueCase, falseCase = null; String conditionString = ifLine.fields[0]; Debug("Entering If Definition '{0}'", conditionString); ObjectDefinition trueCaseObjectDefinition = new ObjectDefinition(pdlFile); nextLine = reader.ReadLineIgnoreComments(); while (nextLine != null && nextLine.parent == ifLine) { ParseObjectFieldLine(pdlFile, reader, containingNamedObject, trueCaseObjectDefinition, nextLine, out nextLine); } trueCaseObjectDefinition.CalculateFixedSerializationLength(); trueCase = new Case(conditionString, trueCaseObjectDefinition); if (nextLine != null && nextLine.id.Equals("else", StringComparison.OrdinalIgnoreCase)) { LfdLine falseCaseLine = nextLine; ObjectDefinition falseCaseObjectDefinition = new ObjectDefinition(pdlFile); nextLine = reader.ReadLineIgnoreComments(); while (nextLine != null && nextLine.parent == falseCaseLine) { ParseObjectFieldLine(pdlFile, reader, containingNamedObject, falseCaseObjectDefinition, nextLine, out nextLine); } falseCaseObjectDefinition.CalculateFixedSerializationLength(); falseCase = new Case(conditionString, falseCaseObjectDefinition); } return(new IfTypeReference(conditionString, trueCase, falseCase)); }
public ParseException(LfdLine line, String reasonFmt, params Object[] reasonObj) : this(line, String.Format(reasonFmt, reasonObj)) { }
public UnresolvedCSharpProjectReference(CSharpProject project, LfdErrorReporter errors, LfdLine line) { this.project = project; this.errors = errors; this.line = line; errors.EnforceFieldCount(line, 1); this.referenceName = line.fields[0]; }
public static LfdLine Parse(MetabuildProject metabuild, LfdParser parser, LfdLine projectLine, Boolean isTestProject, String relativePath) { parser.errors.EnforceFieldCount(projectLine, 1); CSharpProject project = new CSharpProject(relativePath, projectLine.fields[0], isTestProject); bool setOutputType = false; LfdLine line; for (; ;) { line = parser.reader.ReadLineIgnoreComments(); if (line == null) { break; } if (line.id == "ProjectGuid") { parser.errors.EnforceFieldCount(line, 1); if (project.projectGuid != default(Guid)) { throw parser.errors.Error(line, "ProjectGuid was set more than once"); } project.projectGuid = new Guid(line.fields[0]); } else if (line.id == "OutputType") { parser.errors.EnforceFieldCount(line, 1); if (setOutputType) { throw parser.errors.Error(line, "OutputType was set more than once"); } setOutputType = true; project.outputType = (OutputType)Enum.Parse(typeof(OutputType), line.fields[0], false); } else if (line.id == "AssemblyName") { parser.errors.EnforceFieldCount(line, 1); if (project.assemblyName != null) { throw parser.errors.Error(line, "AssemblyName was set more than once"); } project.assemblyName = line.fields[0]; } else if (line.id == "AllowUnsafeBlocks") { parser.errors.EnforceFieldCount(line, 0); if (project.allowUnsafeBlocks) { throw parser.errors.Error(line, "AllowUnsafeBlocks was set more than once"); } project.allowUnsafeBlocks = true; } else if (line.id == "Reference") { parser.errors.EnforceFieldCount(line, 1); project.referenceList.Add(line.fields[0]); } else if (line.id == "ProjectReference") { metabuild.AddUnresolvedReference(new UnresolvedCSharpProjectReference(project, parser.errors, line)); } else if (line.id == "Source") { parser.errors.EnforceFieldCount(line, 1); project.sourceList.Add(line.fields[0]); } else { break; } } // // Verify the project is valid // if (!setOutputType) { throw parser.errors.ErrorNoLine("Missing the 'OutputType' property"); } if (project.assemblyName == null) { project.assemblyName = project.name; } if (project.projectGuid == default(Guid)) { project.projectGuid = Guid.NewGuid(); } metabuild.units.Add(project); return(line); }
public void PrintError(LfdLine line, String fmt, params Object[] obj) { Console.WriteLine("{0}({1}) Error: {2}", filenameForErrors, line.actualLineNumber, String.Format(fmt, obj)); }
public ProjectLoadException Error(LfdLine line, String fmt, params Object[] obj) { return(new ProjectLoadException(String.Format("{0}({1}) {2}", filenameForErrors, line.actualLineNumber, String.Format(fmt, obj)))); }