func (p *Parser) duplicateNameMessage(dupeError *mojom.DuplicateNameError, nameToken lexer.Token) string { if dupeError == nil { return "" } if dupeError.ExistingType() != nil { return fmt.Sprintf("%s:%s. Duplicate definition for name '%s'. "+ "The fully-qualified name of this type would be the same as "+ "an existing type definition: "+ "%s %s in %s.", p.mojomFile.FileName, nameToken.ShortLocationString(), nameToken.Text, dupeError.ExistingType().Kind(), dupeError.ExistingType().FullyQualifiedName(), dupeError.ExistingType().Scope()) } else { return fmt.Sprintf("%s:%s. Duplicate definition for name '%s'. "+ "The fully-qualified name of this value would be the same as "+ "an existing value definition: "+ "%s %s in %s.", p.mojomFile.FileName, nameToken.ShortLocationString(), nameToken.Text, dupeError.ExistingValue().Kind(), dupeError.ExistingValue().FullyQualifiedName(), dupeError.ExistingValue().Scope()) } }
// UserErrorMessageP is responsible for formatting user-facing error messages // This function is similar to UserErrorMessage except that it also allows the // caller to specify the message prefix. // prefix: An error message prefix such as "Error:". It should not end with a space. func UserErrorMessageP(file *MojomFile, token lexer.Token, prefix, message string) string { // TODO(rudominer) Allow users to disable the use of color in snippets. useColor := true // Optionally color the prefix red. if useColor && len(prefix) > 0 { prefix = fmt.Sprintf("\x1b[31;1m%s\x1b[0m", prefix) } if len(prefix) > 0 { prefix = fmt.Sprintf("%s ", prefix) } message = fmt.Sprintf("%s%s", prefix, message) filePath := "Unknown file" importedFromMessage := "" snippet := "" if file != nil { if len(file.fileContents) > 0 { snippet = fmt.Sprintf("\n%s", token.Snippet(file.fileContents, useColor)) } filePath = RelPathIfShorter(file.CanonicalFileName) importedFromMessage = file.ImportedFromMessage() } return fmt.Sprintf("\n%s:%s: %s%s\n%s", filePath, token.ShortLocationString(), message, snippet, importedFromMessage) }
func (p *Parser) matchSemicolonToken(previousToken lexer.Token) bool { if !p.OK() { return false } if p.match(lexer.Semi) { return true } message := fmt.Sprintf("Missing semicolon after %s at %s.", previousToken, previousToken.LongLocationString()) p.err = &ParseError{ParserErrorCodeUnexpectedToken, message} return false }
func (p *Parser) matchSemicolonToken(previousToken lexer.Token) bool { if !p.OK() { return false } if p.match(lexer.SEMI) { return true } message := fmt.Sprintf("Missing semicolon after %s at %s.", previousToken, previousToken.LongLocationString()) p.err = &ParseError{E_UNEXPECTED_TOKEN, message} return false }
// |unexpected| should be a string of the grammatical form "Unexpected token at %s: %s." // |expected| should be a string of the grammatic form "a semicolon" func (p *Parser) expectedTokenError(token lexer.Token, unexpected string, expected string) string { message := fmt.Sprintf(" Expecting %s.", expected) switch token.Kind { case lexer.ErrorUnknown, lexer.ErrorIllegalChar, lexer.ErrorUnterminatedStringLiteral, lexer.ErrorUnterminatedComment: message = fmt.Sprintf("%s at %s.", token, token.LongLocationString()) + message default: message = fmt.Sprintf(unexpected, token.LongLocationString(), token) + message } p.err = &ParseError{ParserErrorCodeUnexpectedToken, message} return message }
// |unexpected| should be a string of the grammatical form "Unexpected token at %s: %s." // |expected| should be a string of the grammatic form "a semicolon" func (p *Parser) expectedTokenError(token lexer.Token, unexpected string, expected string) string { message := fmt.Sprintf(" Expecting %s.", expected) switch token.Kind { case lexer.ERROR_UNKNOWN, lexer.ERROR_ILLEGAL_CHAR, lexer.ERROR_UNTERMINATED_STRING_LITERAL, lexer.ERROR_UNTERMINATED_COMMENT: message = fmt.Sprintf("%s at %s.", token, token.LongLocationString()) + message default: message = fmt.Sprintf(unexpected, token.LongLocationString(), token) + message } p.err = &ParseError{E_UNEXPECTED_TOKEN, message} return message }
// STRUCT_FIELD -> TYPE name [ordinal] [equals DEFAULT_VALUE] semi // DEFAULT_VALUE -> APPROPRIATE_VAL_SPEC | default // APPROPRIATE_VAL_SPEC -> VALUE_REF {{that resolves to a type that is assignment compatible to the type of the assignee}} func (p *Parser) parseStructField(attributes *mojom.Attributes) *mojom.StructField { if !p.OK() { return nil } p.pushChildNode("structField") defer p.popNode() fieldType := p.parseType() fieldName := p.readName() nameToken := p.lastConsumed p.attachToken() ordinalValue, err := p.readOrdinal() if err != nil { p.err = p.newInvalidOrdinalError("field", fieldName, nameToken, err) return nil } var defaultValue mojom.ValueRef var defaultValueToken lexer.Token if p.tryMatch(lexer.Equals) { defaultValueToken = p.peekNextToken("Expecting a default value.") if defaultValueToken.Kind == lexer.Default { p.consumeNextToken() defaultValue = mojom.MakeDefaultLiteral() } else { defaultValue = p.parseValue(fieldType) } } if !p.matchSemicolon() { return nil } declData := p.DeclDataWithOrdinal(fieldName, nameToken, attributes, ordinalValue) field := mojom.NewStructField(declData, fieldType, defaultValue) if !field.ValidateDefaultValue() { valueString := fmt.Sprintf("%v", defaultValue) valueTypeString := "" concreteValue := defaultValue.ResolvedConcreteValue() if concreteValue != nil { valueString = fmt.Sprintf("%v", concreteValue.Value()) valueTypeString = fmt.Sprintf(" of type %s", concreteValue.ValueType()) } message := fmt.Sprintf("Illegal assignment at %s: Field %s of type %s may not be assigned the value %v%s.", defaultValueToken.LongLocationString(), fieldName, fieldType, valueString, valueTypeString) p.err = &ParseError{ParserErrorCodeNotAssignmentCompatible, message} return nil } return field }
// STRUCT_FIELD -> TYPE name [ordinal] [equals DEFAULT_VALUE] semi // DEFAULT_VALUE -> APPROPRIATE_VAL_SPEC | default // APPROPRIATE_VAL_SPEC -> VALUE_REF {{that resolves to a type that is assignment compatible to the type of the assignee}} func (p *Parser) parseStructField(attributes *mojom.Attributes) *mojom.StructField { if !p.OK() { return nil } p.pushChildNode("structField") defer p.popNode() fieldType := p.parseType() fieldName := p.readName() p.attachToken() ordinalValue := p.readOrdinal() var defaultValue mojom.ValueRef var defaultValueToken lexer.Token if p.tryMatch(lexer.EQUALS) { defaultValueToken = p.peekNextToken("Expecting a default value.") if defaultValueToken.Kind == lexer.DEFAULT { p.consumeNextToken() defaultValue = mojom.MakeDefaultLiteral() } else { defaultValue = p.parseValue(fieldType) } } if !p.matchSemicolon() { return nil } field := mojom.NewStructField(fieldType, fieldName, ordinalValue, attributes, defaultValue) if !field.ValidateDefaultValue() { valueString := fmt.Sprintf("%v", defaultValue) valueTypeString := "" concreteValue := defaultValue.ResolvedConcreteValue() if concreteValue != nil { valueString = fmt.Sprintf("%v", concreteValue.Value()) valueTypeString = fmt.Sprintf(" of type %s", concreteValue.ValueType()) } message := fmt.Sprintf("Illegal assignment at %s: Field %s of type %s may not be assigned the value %v%s.", defaultValueToken.LongLocationString(), fieldName, fieldType, valueString, valueTypeString) p.err = &ParseError{E_TYPE_NOT_ASSIGNMENT_COMPATIBLE, message} return nil } return field }
func (p *Parser) newInvalidOrdinalError(objectType, objectName string, nameToken lexer.Token, err error) *ParseError { message := fmt.Sprintf("%s:%s %s %q: %s", p.mojomFile.CanonicalFileName, nameToken.ShortLocationString(), objectType, objectName, err.Error()) return &ParseError{ParserErrorCodeBadOrdinal, message} }