blob: 24328c6884eb85559a64239b63f167410ade9efa [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/*
This file contains parseCmd which parses a set of .mojom files and emits a
serialized MojomFileGraph struct. See mojom_files.mojom for the definition of
MojomFileGraph.
The parse command is invoked as follows:
mojom parse [-I <include_dirs>] [-out <out_file>] [-debug] <mojom_file>...
<include_dirs> is comma-separated list of directory paths to search for mojom imports.
<out_file> is the path to the output file. If not given the output will be written to standard out.
<mojom_file>... is one or more paths to .mojom files to be parsed.
If there are no errors then the program returns status zero and writes nothing
to standard error and writes nothing to standard out except possibly the output
if <out_file> is not specified. If there are any errors then the program returns
status code 1 and writes error messages to standard error.
If -debug is specified then the program emits lots of debugging data to
standard out, including a depiction of the parse trees. If also <out_file> is
not specified then the actual output is written at the end after the debugging
data.
*/
package main
import (
"bufio"
"flag"
"fmt"
"io/ioutil"
"log"
"mojom/mojom_tool/mojom"
"mojom/mojom_tool/parser"
"mojom/mojom_tool/serialization"
"os"
"path/filepath"
)
// parseCmd implements the parse command for the mojom tool.
// The slice of strings |args| is the list of arguments passed on the command
// line starting with the program name and followed by the invoked command.
func parseCmd(args []string) {
flagSet := flag.NewFlagSet("parse", flag.ContinueOnError)
var directoryListFlag DirectoryList
flagSet.Var(&directoryListFlag, "I", "comma-separated list of directory paths to search for mojom imports")
outFile := flagSet.String("out", "", "The path to the output file. If not present the output will "+
"be written to standard out.")
debug := flagSet.Bool("debug", false, "Generate debug data including the parse tree and print it to standard out.")
metaDataOnly := flagSet.Bool("meta-data-only", false, "Only parse file attributes and 'module' statement, "+
"not mojom declarations or import statements.")
flagSet.SetOutput(ioutil.Discard)
printUsage := func() {
fmt.Fprintf(os.Stderr, "Usage: %s parse [-I <include_dirs>] [-out <out_file>] [-debug] [-meta-data-only] <mojom_file>...\n\n", filepath.Base(args[0]))
fmt.Fprintf(os.Stderr, UsageString(flagSet))
}
if err := flagSet.Parse(args[2:]); err != nil {
if err != flag.ErrHelp {
fmt.Fprintln(os.Stderr, err.Error())
}
printUsage()
os.Exit(1)
}
fileNames := flagSet.Args()
bytes := parse(fileNames, directoryListFlag, printUsage, *metaDataOnly, *debug)
// Emit the output to a file or standard out.
if len(*outFile) == 0 {
w := bufio.NewWriter(os.Stdout)
if _, err := w.Write(bytes); err != nil {
log.Fatalf("Error writing output to standard out: %s.\n", err.Error())
}
w.Flush()
} else {
if err := ioutil.WriteFile(*outFile, bytes, os.ModePerm); err != nil {
log.Fatalf("Error writing output to %s: %s.", *outFile, err.Error())
} else {
if *debug {
fmt.Printf("The output was written to %s.\n", *outFile)
}
}
}
}
// parse parses a list of mojom files and returns a serialized MojomFileGraph.
//
// fileNames is a list of paths to the .mojom files to be parsed.
// importPaths is a list of directories where imports should be looked up.
// printUsage is a function which prints the usage of the invoked mojom tool command.
// metaDataOnly limits parsing to module statements and file attributes.
// debug if true causes the parse tree and other debug information to be printed to standard out.
func parse(fileNames []string, importPaths DirectoryList, printUsage func(), metaDataOnly, debug bool) []byte {
if len(fileNames) == 0 {
fmt.Fprintln(os.Stderr, "No .mojom files given.")
printUsage()
os.Exit(1)
}
parseDriver := parser.NewDriver(importPaths, debug, metaDataOnly)
// Do the parsing
descriptor, err := parseDriver.ParseFiles(fileNames)
if err != nil {
log.Fatalln(err.Error())
} else if debug {
fmt.Println("Parsing complete.")
}
// Serialize the result.
bytes, debug_string, err := serialization.Serialize(descriptor, debug)
if err != nil {
log.Fatalf("Serialization error: %s\n", err)
}
// In debug mode print out the debug information.
if debug {
printDebugOutput(debug_string, descriptor)
}
return bytes
}
func printDebugOutput(debugString string, descriptor *mojom.MojomDescriptor) {
fmt.Println("\n\n=============================================")
fmt.Println("\n Pre-Serialized Go Object:")
fmt.Printf("\n%s\n", descriptor.String())
fmt.Println("\n\n=============================================")
fmt.Println("\n Debug Serialized Output:")
fmt.Println(debugString)
}