• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright 2014 the V8 project authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""This program either generates the parser files for Torque, generating
8the source and header files directly in V8's src directory."""
9
10import subprocess
11import sys
12import re
13from subprocess import Popen, PIPE
14
15def decode(arg, encoding="utf-8"):
16  return arg.decode(encoding)
17
18def encode(arg, encoding="utf-8"):
19  return arg.encode(encoding)
20
21kPercentEscape = r'α';  # Unicode alpha
22kDerefEscape = r'☆'; # Unicode star
23kAddressofEscape = r'⌂'; # Unicode house
24
25def preprocess(input):
26  # Special handing of '%' for intrinsics, turn the percent
27  # into a unicode character so that it gets treated as part of the
28  # intrinsic's name if it's already adjacent to it.
29  input = re.sub(r'%([A-Za-z])', kPercentEscape + r'\1', input)
30  # Similarly, avoid treating * and & as binary operators when they're
31  # probably used as address operators.
32  input = re.sub(r'([^/])\*([a-zA-Z(])', r'\1' + kDerefEscape + r'\2', input)
33  input = re.sub(r'&([a-zA-Z(])', kAddressofEscape + r'\1', input)
34
35
36  input = re.sub(r'(if\s+)constexpr(\s*\()', r'\1/*COxp*/\2', input)
37  input = re.sub(r'(\s+)operator\s*(\'[^\']+\')', r'\1/*_OPE \2*/', input)
38  input = re.sub(r'\btypeswitch\s*(\([^{]*\))\s{', r' if /*tPsW*/ \1 {', input)
39  input = re.sub(r'\bcase\s*(\([^{]*\))\s*:\s*deferred\s*{', r' if /*cAsEdEfF*/ \1 {', input)
40  input = re.sub(r'\bcase\s*(\([^{]*\))\s*:\s*{', r' if /*cA*/ \1 {', input)
41
42  input = re.sub(r'\bgenerates\s+\'([^\']+)\'\s*',
43      r'_GeNeRaTeS00_/*\1@*/', input)
44  input = re.sub(r'\bconstexpr\s+\'([^\']+)\'\s*',
45      r' _CoNsExP_/*\1@*/', input)
46  input = re.sub(r'\notherwise',
47      r'\n otherwise', input)
48  input = re.sub(r'(\n\s*\S[^\n]*\s)otherwise',
49      r'\1_OtheSaLi', input)
50  input = re.sub(r'@if\(', r'@iF(', input)
51  input = re.sub(r'@export', r'@eXpOrT', input)
52  input = re.sub(r'js-implicit[ \n]+', r'jS_iMpLiCiT_', input)
53  input = re.sub(r'^(\s*namespace\s+[a-zA-Z_0-9]+\s*{)(\s*)$', r'\1}\2', input, flags = re.MULTILINE)
54
55  # includes are not recognized, change them into comments so that the
56  # formatter ignores them first, until we can figure out a way to format cpp
57  # includes within a JS file.
58  input = re.sub(r'^#include', r'// InClUdE', input, flags=re.MULTILINE)
59
60  return input
61
62def postprocess(output):
63  output = re.sub(r'\/\*COxp\*\/', r'constexpr', output)
64  output = re.sub(r'(\S+)\s*: type([,>])', r'\1: type\2', output)
65  output = re.sub(r'(\n\s*)labels( [A-Z])', r'\1    labels\2', output)
66  output = re.sub(r'\/\*_OPE \'([^\']+)\'\*\/', r"operator '\1'", output)
67  output = re.sub(r'\bif\s*\/\*tPsW\*\/', r'typeswitch', output)
68  output = re.sub(r'\bif\s*\/\*cA\*\/\s*(\([^{]*\))\s*{', r'case \1: {', output)
69  output = re.sub(r'\bif\s*\/\*cAsEdEfF\*\/\s*(\([^{]*\))\s*{', r'case \1: deferred {', output)
70  output = re.sub(r'\n_GeNeRaTeS00_\s*\/\*([^@]+)@\*\/',
71      r"\n    generates '\1'", output)
72  output = re.sub(r'_GeNeRaTeS00_\s*\/\*([^@]+)@\*\/',
73      r"generates '\1'", output)
74  output = re.sub(r'_CoNsExP_\s*\/\*([^@]+)@\*\/',
75      r"constexpr '\1'", output)
76  output = re.sub(r'\n(\s+)otherwise',
77      r"\n\1    otherwise", output)
78  output = re.sub(r'\n(\s+)_OtheSaLi',
79      r"\n\1otherwise", output)
80  output = re.sub(r'_OtheSaLi',
81      r"otherwise", output)
82  output = re.sub(r'@iF\(', r'@if(', output)
83  output = re.sub(r'@eXpOrT',
84      r"@export", output)
85  output = re.sub(r'jS_iMpLiCiT_',
86      r"js-implicit ", output)
87  output = re.sub(r'}\n *label ', r'} label ', output);
88  output = re.sub(r'^(\s*namespace\s+[a-zA-Z_0-9]+\s*{)}(\s*)$', r'\1\2', output, flags = re.MULTILINE);
89
90  output = re.sub(kPercentEscape, r'%', output)
91  output = re.sub(kDerefEscape, r'*', output)
92  output = re.sub(kAddressofEscape, r'&', output)
93
94
95  output = re.sub( r'^// InClUdE',r'#include', output, flags=re.MULTILINE)
96
97  return output
98
99def process(filename, lint, should_format):
100  with open(filename, 'r') as content_file:
101    content = content_file.read()
102
103  original_input = content
104
105  if sys.platform.startswith('win'):
106    p = Popen(['clang-format', '-assume-filename=.ts'], stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
107  else:
108    p = Popen(['clang-format', '-assume-filename=.ts'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
109  output, err = p.communicate(encode(preprocess(content)))
110  output = postprocess(decode(output))
111  rc = p.returncode
112  if (rc != 0):
113    print("error code " + str(rc) + " running clang-format. Exiting...")
114    sys.exit(rc);
115
116  if (output != original_input):
117    if lint:
118      print(filename + ' requires formatting', file=sys.stderr)
119
120    if should_format:
121      output_file = open(filename, 'wb')
122      output_file.write(encode(output))
123      output_file.close()
124
125def print_usage():
126  print('format-torque -i file1[, file2[, ...]]')
127  print('    format and overwrite input files')
128  print('format-torque -l file1[, file2[, ...]]')
129  print('    merely indicate which files need formatting')
130
131def Main():
132  if len(sys.argv) < 3:
133    print("error: at least 2 arguments required")
134    print_usage();
135    sys.exit(-1)
136
137  def is_option(arg):
138    return arg in ['-i', '-l', '-il']
139
140  should_format = lint = False
141  use_stdout = True
142
143  flag, files = sys.argv[1], sys.argv[2:]
144  if is_option(flag):
145    if '-i' == flag:
146      should_format = True
147    elif '-l' == flag:
148      lint = True
149    else:
150      lint = True
151      should_format = True
152  else:
153    print("error: -i and/or -l flags must be specified")
154    print_usage();
155    sys.exit(-1);
156
157  for filename in files:
158    process(filename, lint, should_format)
159
160  return 0
161
162if __name__ == '__main__':
163  sys.exit(Main());
164