// Parses each of the given .mojom files and all of the files in the // import graph rooted by each file. A single MojomDescriptor is created and // populated with the result of parsing all of those files. If the parsing is // successful then err will be nil. // // fileNames must not be nil or we will panic. func (d *ParseDriver) ParseFiles(fileNames []string) (descriptor *mojom.MojomDescriptor, err error) { if fileNames == nil { // We panic instead of returning an error here because this would be a programming error // as opposed to an error in the input. panic("fileNames may not be nil.") } filesToProcess := make([]*FileReference, len(fileNames)) descriptor = mojom.NewMojomDescriptor() for i, fileName := range fileNames { filesToProcess[i] = &FileReference{specifiedPath: fileName} } for len(filesToProcess) > 0 { currentFile := filesToProcess[0] filesToProcess = filesToProcess[1:] if err = d.fileProvider.findFile(currentFile); err != nil { return } var importedFrom *mojom.MojomFile = nil if currentFile.importedFrom != nil { importedFrom = currentFile.importedFrom.mojomFile // Tell the importing file about the absolute path of the imported file. // Note that we must do this even if the imported file has already been processed // because a given file may be imported by multiple files and each of those need // to be told about the absolute path of the imported file. importedFrom.SetCanonicalImportName(currentFile.specifiedPath, currentFile.absolutePath) } if !descriptor.ContainsFile(currentFile.absolutePath) { contents, fileReadError := d.fileProvider.provideContents(currentFile) if fileReadError != nil { err = fileReadError return } // topLevelFileName should be non-empty if and only if the current file is a top-level file. topLevelFileName := "" if importedFrom == nil { topLevelFileName = currentFile.specifiedPath } parser := MakeParser(currentFile.absolutePath, topLevelFileName, contents, descriptor, importedFrom) parser.SetDebugMode(d.debugMode) // Invoke parser.Parse() (but skip doing so in tests sometimes.) d.parseInvoker.invokeParse(&parser) if d.debugMode { fmt.Printf("\nParseTree for %s:", currentFile) fmt.Println(parser.GetParseTree()) } if !parser.OK() { err = parser.GetError() return } currentFile.mojomFile = d.fileExtractor.extractMojomFile(&parser) for _, importedFile := range currentFile.mojomFile.Imports { // Note that it is important that we append all of the imported files here even // if some of them have already been processed. That is because when the imported // file is pulled from the queue it will be pre-processed during which time the // absolute path to the file will be discovered and this absolute path will be // set in |mojomFile| which is necessary for serializing mojomFile. filesToProcess = append(filesToProcess, &FileReference{importedFrom: currentFile, specifiedPath: importedFile.SpecifiedName}) } } } // Perform type and value resolution if err = descriptor.Resolve(); err != nil { return } // Compute enum value integers. if err = descriptor.ComputeEnumValueIntegers(); err != nil { return } // Compute data for generators. err = descriptor.ComputeDataForGenerators() return }