blob: 1b7de31ddb05d65ed83bbe6465069e6c1dc61f77 [file] [log] [blame]
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Formatter for Emboss source files.
This program formats an Emboss source file given on the command line.
"""
from __future__ import absolute_import
from __future__ import print_function
import argparse
import os
import sys
from compiler.front_end import format_emb
from compiler.front_end import parser
from compiler.front_end import tokenizer
from compiler.util import error
def _parse_command_line(argv):
"""Parses the given command-line arguments."""
argparser = argparse.ArgumentParser(
description="Emboss compiler front end.", prog=argv[0]
)
argparser.add_argument(
"input_file", type=str, nargs="+", help=".emb file to compile."
)
argparser.add_argument(
"--no-check-result",
default=True,
action="store_false",
dest="check_result",
help="Verify that the resulting formatted text "
"contains only whitespace changes.",
)
argparser.add_argument(
"--debug-show-line-types",
default=False,
help="Show the computed type of each line.",
)
argparser.add_argument(
"--no-edit-in-place",
default=True,
action="store_false",
dest="edit_in_place",
help="Write the formatted text back to the input " "file.",
)
argparser.add_argument(
"--indent",
type=int,
default=2,
help="Number of spaces to use for each level of " "indentation.",
)
argparser.add_argument(
"--color-output",
default="if-tty",
choices=["always", "never", "if-tty", "auto"],
help="Print error messages using color. 'auto' is a " "synonym for 'if-tty'.",
)
return argparser.parse_args(argv[1:])
def _print_errors(errors, source_codes, flags):
use_color = flags.color_output == "always" or (
flags.color_output in ("auto", "if-tty") and os.isatty(sys.stderr.fileno())
)
print(error.format_errors(errors, source_codes, use_color), file=sys.stderr)
def main(argv=()):
flags = _parse_command_line(argv)
if not flags.edit_in_place and len(flags.input_file) > 1:
print(
"Multiple files may only be formatted without --no-edit-in-place.",
file=sys.stderr,
)
return 1
if flags.edit_in_place and flags.debug_show_line_types:
print(
"The flag --debug-show-line-types requires --no-edit-in-place.",
file=sys.stderr,
)
return 1
for file_name in flags.input_file:
with open(file_name) as f:
source_code = f.read()
tokens, errors = tokenizer.tokenize(source_code, file_name)
if errors:
_print_errors(errors, {file_name: source_code}, flags)
continue
parse_result = parser.parse_module(tokens)
if parse_result.error:
_print_errors(
[error.make_error_from_parse_error(file_name, parse_result.error)],
{file_name: source_code},
flags,
)
continue
formatted_text = format_emb.format_emboss_parse_tree(
parse_result.parse_tree,
format_emb.Config(
show_line_types=flags.debug_show_line_types, indent_width=flags.indent
),
)
if flags.check_result and not flags.debug_show_line_types:
errors = format_emb.sanity_check_format_result(formatted_text, source_code)
if errors:
for e in errors:
print(e, file=sys.stderr)
continue
if flags.edit_in_place:
with open(file_name, "w") as f:
f.write(formatted_text)
else:
sys.stdout.write(formatted_text)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))