1#!/usr/bin/env ruby
2# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15require 'erb'
16require 'ostruct'
17require 'set'
18
19keywords = [
20    # keywords start with 'a'
21    {
22        "abstract" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_ABSTRACT"],
23        "any" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_ANY"],
24        "arguments" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_ARGUMENTS"],
25        "as" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_AS"],
26        "asserts" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_ASSERTS"],
27        "async" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_ASYNC"],
28        "await" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_AWAIT"],
29        "accessor" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_ACCESSOR"],
30    },
31
32    # keywords start with 'b'
33    {
34        "bigint" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_BIGINT"],
35        "boolean" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_BOOLEAN"],
36        "break" => ["TokenType::KEYW_BREAK", "TokenType::KEYW_BREAK"],
37    },
38
39    # keywords start with 'c'
40    {
41        "case" => ["TokenType::KEYW_CASE", "TokenType::KEYW_CASE"],
42        "catch" => ["TokenType::KEYW_CATCH", "TokenType::KEYW_CATCH"],
43        "class" => ["TokenType::KEYW_CLASS", "TokenType::KEYW_CLASS"],
44        "const" => ["TokenType::KEYW_CONST", "TokenType::KEYW_CONST"],
45        "continue" => ["TokenType::KEYW_CONTINUE", "TokenType::KEYW_CONTINUE"]
46    },
47
48    # keywords start with 'd'
49    {
50        "debugger" => ["TokenType::KEYW_DEBUGGER", "TokenType::KEYW_DEBUGGER"],
51        "declare" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_DECLARE"],
52        "default" => ["TokenType::KEYW_DEFAULT", "TokenType::KEYW_DEFAULT"],
53        "delete" => ["TokenType::KEYW_DELETE", "TokenType::KEYW_DELETE"],
54        "do" => ["TokenType::KEYW_DO", "TokenType::KEYW_DO"],
55    },
56
57    # keywords start with 'e'
58    {
59        "else" => ["TokenType::KEYW_ELSE", "TokenType::KEYW_ELSE"],
60        "enum" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_ENUM"],
61        "eval" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_EVAL"],
62        "export" => ["TokenType::KEYW_EXPORT", "TokenType::KEYW_EXPORT"],
63        "extends" => ["TokenType::KEYW_EXTENDS", "TokenType::KEYW_EXTENDS"],
64    },
65
66    # keywords start with 'f'
67    {
68        "false" => ["TokenType::LITERAL_FALSE", "TokenType::LITERAL_FALSE"],
69        "finally" => ["TokenType::KEYW_FINALLY", "TokenType::KEYW_FINALLY"],
70        "for" => ["TokenType::KEYW_FOR", "TokenType::KEYW_FOR"],
71        "from" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_FROM"],
72        "function" => ["TokenType::KEYW_FUNCTION", "TokenType::KEYW_FUNCTION"],
73    },
74
75    # keywords start with 'g'
76    {
77        "get" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_GET"],
78        "global" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_GLOBAL"],
79    },
80
81    # keywords start with 'i'
82    {
83        "if" => ["TokenType::KEYW_IF", "TokenType::KEYW_IF"],
84        "implements" => ["TokenType::KEYW_IMPLEMENTS", "TokenType::KEYW_IMPLEMENTS"],
85        "import" => ["TokenType::KEYW_IMPORT", "TokenType::KEYW_IMPORT"],
86        "in" => ["TokenType::KEYW_IN", "TokenType::KEYW_IN"],
87        "infer" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_INFER"],
88        "instanceof" => ["TokenType::KEYW_INSTANCEOF", "TokenType::KEYW_INSTANCEOF"],
89        "interface" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_INTERFACE"],
90        "is" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_IS"],
91    },
92
93    # keywords start with 'k'
94    {
95        "keyof" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_KEYOF"],
96    },
97
98    # keywords start with 'l'
99    {
100        "lazy" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_LAZY"],
101        "let" => ["TokenType::KEYW_LET", "TokenType::KEYW_LET"],
102    },
103
104    # keywords start with 'm'
105    {
106        "meta" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_META"],
107        "module" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_MODULE"],
108        "namespace" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_NAMESPACE"],
109    },
110
111    # keywords start with 'n'
112    {
113        "never" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_NEVER"],
114        "new" => ["TokenType::KEYW_NEW", "TokenType::KEYW_NEW"],
115        "null" => ["TokenType::LITERAL_NULL", "TokenType::LITERAL_NULL"],
116        "number" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_NUMBER"],
117    },
118
119    # keywords start with 'o'
120    {
121        "object" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_OBJECT"],
122        "of" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_OF"],
123        "out" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_OUT"],
124        "override" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_OVERRIDE"],
125    },
126
127    # keywords start with 'p'
128    {
129        "package" => ["TokenType::KEYW_PACKAGE", "TokenType::KEYW_PACKAGE"],
130        "private" => ["TokenType::KEYW_PRIVATE", "TokenType::KEYW_PRIVATE"],
131        "protected" => ["TokenType::KEYW_PROTECTED", "TokenType::KEYW_PROTECTED"],
132        "public" => ["TokenType::KEYW_PUBLIC", "TokenType::KEYW_PUBLIC"],
133    },
134
135    # keywords start with 'r'
136    {
137        "readonly" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_READONLY"],
138        "return" => ["TokenType::KEYW_RETURN", "TokenType::KEYW_RETURN"],
139        "require" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_REQUIRE"],
140    },
141
142    # keywords start with 's'
143    {
144        "satisfies" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_SATISFIES"],
145        "set" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_SET"],
146        "static" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_STATIC"],
147        "string" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_STRING"],
148        "super" => ["TokenType::KEYW_SUPER", "TokenType::KEYW_SUPER"],
149        "switch" => ["TokenType::KEYW_SWITCH", "TokenType::KEYW_SWITCH"],
150        "symbol" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_SYMBOL"],
151    },
152
153    # keywords start with 't'
154    {
155        "this" => ["TokenType::KEYW_THIS", "TokenType::KEYW_THIS"],
156        "throw" => ["TokenType::KEYW_THROW", "TokenType::KEYW_THROW"],
157        "true" => ["TokenType::LITERAL_TRUE", "TokenType::LITERAL_TRUE"],
158        "try" => ["TokenType::KEYW_TRY", "TokenType::KEYW_TRY"],
159        "type" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_TYPE"],
160        "typeof" => ["TokenType::KEYW_TYPEOF", "TokenType::KEYW_TYPEOF"],
161    },
162
163    # keywords start with 'u'
164    {
165        "undefined" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_UNDEFINED"],
166        "unique" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_UNIQUE"],
167        "unknown" => ["TokenType::LITERAL_IDENT", "TokenType::KEYW_UNKNOWN"],
168    },
169
170    # keywords start with 'v'
171    {
172        "var" => ["TokenType::KEYW_VAR", "TokenType::KEYW_VAR"],
173        "void" => ["TokenType::KEYW_VOID", "TokenType::KEYW_VOID"],
174    },
175
176    # keywords start with 'w'
177    {
178        "while" => ["TokenType::KEYW_WHILE", "TokenType::KEYW_WHILE"],
179        "with" => ["TokenType::KEYW_WITH", "TokenType::KEYW_WITH"],
180    },
181
182    # keywords start with 'y'
183    {
184        "yield" => ["TokenType::KEYW_YIELD", "TokenType::KEYW_YIELD"],
185    },
186]
187
188def collect_functions(functions, keys)
189    offset = 0
190
191    while true
192        has_more = false
193
194        keys.each do |key|
195            if key.length < offset + 1
196                next
197            end
198
199            has_more = true
200            func_name = key[0..offset];
201
202            if functions.has_key?(func_name)
203                functions[func_name].add(key[offset + 1])
204            else
205                functions[func_name] = Set[key[offset + 1]]
206            end
207        end
208
209        if has_more
210            offset += 1
211            next
212        end
213
214        break
215    end
216end
217
218def generate(keywords, template_file, output_file)   
219    functions = {}
220    keywords.each do |group|
221        collect_functions(functions, group.keys)
222    end
223
224    template = File.read(template_file)
225    t = ERB.new(template, nil, '%-')
226    t.filename = OpenStruct.new.template
227    res = t.result(binding)
228
229    File.open(output_file, "w") do |file|
230        file.write(res)
231    end
232end
233
234abort "Failed: input file required!" if ARGV.size < 2
235
236generate(keywords, ARGV[0], ARGV[1])
237