/// <summary> /// Parse field options. /// </summary> /// <param name="field">The field to parse.</param> /// <returns>True if ok otherwise false.</returns> internal bool ParseFieldOptions(Field field) { // are there any options ? if (Word != "[") { return true; // no, return } do { if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"option\" or \"default\"."); return false; } switch (Word) { case "default": if (!ParseDefault(field)) { return false; } break; default: if (!ParseFieldOption()) { return false; } break; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \",\" or \"]\"."); return false; } } while (Word == ","); // do while until no more options are found if (Word != "]") { AddNewError("Expected \",\" or \"]\"."); } else { IncrementIndex(true); } return true; }
/// <summary> /// Parse enum entry. /// </summary> /// <param name="isTopLevel">True if top level command else false.</param> /// <returns>True if ok, else false.</returns> internal bool ParseEnum(bool isTopLevel) { var field = new Field { FieldType = FieldType.TypeUnknown, HasOption = false }; AddNewToken(isTopLevel ? CodeType.TopLevelCmd : CodeType.Keyword); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected enum name."); return false; } if (!Helper.IsIdentifier(Word)) { AddNewError("Expected enum name."); return false; } AddNewToken(CodeType.SymDef); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"{\"."); return false; } if (Word != "{") { AddNewError("Expected \"{\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"option\", \"}\", \";\" or enum constant name."); return false; } do { if (Word == "option") { if (!ParseOption(false)) { return false; } } if (!Helper.IsIdentifier(Word)) { AddNewError("Expected enum constant name"); return false; } AddNewToken(CodeType.Enums); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"=\"."); return false; } if (Word != "=") { AddNewError("Expected \"=\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected numeric value for enum constant."); return false; } if (!Helper.IsInteger(Word)) { AddNewError("Expected numeric value for enum constant."); return false; } AddNewToken(CodeType.Number); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \";\"."); return false; } if (!ParseFieldOptions(field)) { return false; } if (Word != ";") { AddNewError("Expected \";\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"option\", \"}\", \";\" or enum constant name."); return false; } } while (Word != "}"); if (!IncrementIndex(true)) { return true; } if (Word == ";") { IncrementIndex(true); } return true; }
/// <summary> /// Parse the "default" of a message field. /// </summary> /// <param name="field">The field to parse.</param> /// <returns>True if ok otherwise false.</returns> internal bool ParseDefault(Field field) { if (field.HasOption) { AddNewError("Already set option \"default\"."); } // eat the word "default" AddNewToken(CodeType.Keyword); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"=\"."); return false; } if (Word != "=") { AddNewError("Expected \"=\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected default value."); return false; } switch (field.FieldType) { case FieldType.TypeUnknown: // enum value AddNewToken(CodeType.Enums); break; case FieldType.TypeInt32: case FieldType.TypeInt64: case FieldType.TypeSint32: case FieldType.TypeSint64: case FieldType.TypeSfixed32: case FieldType.TypeSfixed64: if (!Helper.IsInteger(Word)) { AddNewError("Expected number."); } AddNewToken(CodeType.Number); break; case FieldType.TypeUint64: case FieldType.TypeFixed64: if (!Helper.IsPositive64Integer(Word)) { AddNewError("Expected unsigned number."); } AddNewToken(CodeType.Number); break; case FieldType.TypeUint32: case FieldType.TypeFixed32: if (!Helper.IsPositiveInteger(Word)) { AddNewError("Expected unsigned number."); } AddNewToken(CodeType.Number); break; case FieldType.TypeFloat: case FieldType.TypeDouble: int i = Matches[Index].Index; // save position var num = GetFloatNumber(); if (!Helper.IsDoubleOrFloat(num)) { AddNewError(i, Matches[Index].Index + Matches[Index].Length - i, "Expected number."); } AddNewToken(i, Matches[Index].Index + Matches[Index].Length - i, num, CodeType.Number); break; case FieldType.TypeBool: if (Helper.IsTrueOrFalse(Word)) { AddNewToken(CodeType.Keyword); } else { AddNewError("Expected \"true\" or \"false\"."); } break; case FieldType.TypeString: case FieldType.TypeBytes: // tokenize string if (!GetString("Expected string.")) { return false; } break; default: AddNewToken(CodeType.Number); AddNewError("Expected default value."); break; } return true; }
/// <summary> /// Parse a oneof field. /// </summary> /// <returns>True if ok otherwise false.</returns> internal bool ParseOneOfField() { // ReSharper disable once UseObjectOrCollectionInitializer var field = new Field(); //if (!IncrementIndex(true)) //{ // AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field type."); // return false; //} field.FieldType = Helper.GetFieldType(Word); if (field.FieldType == FieldType.TypeUnknown) { while (true) { if (!Helper.IsIdentifier(Word)) { AddNewError("Expected Identifier."); } AddNewToken(CodeType.SymRef); if (!IncrementIndex()) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } if (Word == ".") { if (!IncrementIndex()) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected Identifier."); return false; } } else { break; } } } else { AddNewToken(CodeType.Keyword); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } } if (!Helper.IsIdentifier(Word)) { AddNewError("Invalid field name."); return false; } AddNewToken(CodeType.SymDef); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"=\"."); return false; } if (Word != "=") { AddNewError("Expected \"=\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field number."); return false; } if (!Helper.IsPositiveInteger(Word)) { AddNewError("Expected field number."); } else { AddNewToken(CodeType.Number); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \";\""); return false; } } if (Word != ";") { AddNewError("Expected \";\""); return false; } IncrementIndex(true); return true; }
/// <summary> /// Parse a message field. /// </summary> /// <returns>True if ok otherwise false.</returns> internal bool ParseMessageField() { var field = new Field(); if (!Helper.IsFieldRule(Word)) { AddNewError("Expected \"required\", \"optional\", or \"repeated\"."); IncrementIndex(true); return false; } AddNewToken(CodeType.FieldRule); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field type."); return false; } field.FieldType = Helper.GetFieldType(Word); if (field.FieldType == FieldType.TypeUnknown) { while (true) { if (Word == ".") { if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected Identifier."); return false; } } if (!Helper.IsIdentifier(Word)) { AddNewError("Expected Identifier."); } AddNewToken(CodeType.SymRef); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } if (Word == ".") { if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected Identifier."); return false; } } else { break; } } } else { AddNewToken(CodeType.Keyword); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } } if (!Helper.IsIdentifier(Word)) { AddNewError("Invalid field name."); return false; } AddNewToken(CodeType.SymDef); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"=\"."); return false; } if (Word != "=") { AddNewError("Expected \"=\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field number."); return false; } if (!Helper.IsPositiveInteger(Word)) { AddNewError("Expected field number."); } else { AddNewToken(CodeType.Number); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \";\""); return false; } } ParseFieldOptions(field); if (Word != ";") { AddNewError("Expected \";\""); return false; } IncrementIndex(true); return true; }
/// <summary> /// Parse a map. /// </summary> /// <returns>True if ok otherwise false.</returns> internal bool ParseMap() { AddNewToken(CodeType.Keyword); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"<\"."); return false; } if (Word != "<") { AddNewError("Expected \"<\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field type."); return false; } var field = new Field { FieldType = Helper.GetFieldType(Word) }; if (field.FieldType == FieldType.TypeUnknown) { while (true) { if (!Helper.IsIdentifier(Word)) { AddNewError("Expected Identifier."); } AddNewToken(CodeType.SymRef); if (!IncrementIndex()) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } if (Word == ".") { if (!IncrementIndex()) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected Identifier."); return false; } } else { break; } } } else { AddNewToken(CodeType.Keyword); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } } if (Word != ",") { AddNewError("Expected \",\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field type."); return false; } field = new Field { FieldType = Helper.GetFieldType(Word) }; if (field.FieldType == FieldType.TypeUnknown) { while (true) { if (!Helper.IsIdentifier(Word)) { AddNewError("Expected Identifier."); } AddNewToken(CodeType.SymRef); if (!IncrementIndex()) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } if (Word == ".") { if (!IncrementIndex()) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected Identifier."); return false; } } else { break; } } } else { AddNewToken(CodeType.Keyword); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } } if (Word != ">") { AddNewError("Expected \">\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field name."); return false; } if (!Helper.IsIdentifier(Word)) { AddNewError("Invalid field name."); return false; } AddNewToken(CodeType.SymDef); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \"=\"."); return false; } if (Word != "=") { AddNewError("Expected \"=\"."); return false; } if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected field number."); return false; } if (!Helper.IsPositiveInteger(Word)) { AddNewError("Expected field number."); } else { AddNewToken(CodeType.Number); if (!IncrementIndex(true)) { AddNewError(Matches[Index - 1].Index + Matches[Index - 1].Length, 1, "Expected \";\""); return false; } } if (Word != ";") { AddNewError("Expected \";\""); return false; } IncrementIndex(true); return true; }