Java tutorial
/* * 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 * * http://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. */ package com.facebook.presto.sql; import com.facebook.presto.sql.parser.ParsingException; import com.facebook.presto.sql.parser.SqlBaseLexer; import com.facebook.presto.sql.parser.SqlParser; import com.facebook.presto.sql.tree.Identifier; import com.google.common.collect.ImmutableSet; import org.antlr.v4.runtime.Vocabulary; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.google.common.base.Strings.nullToEmpty; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static java.lang.String.format; public final class ReservedIdentifiers { private static final Pattern IDENTIFIER = Pattern.compile("'([A-Z_]+)'"); private static final Pattern TABLE_ROW = Pattern.compile("``([A-Z_]+)``.*"); private static final String TABLE_PREFIX = "============================== "; private static final SqlParser PARSER = new SqlParser(); private ReservedIdentifiers() { } @SuppressWarnings("CallToPrintStackTrace") public static void main(String[] args) throws IOException { if ((args.length == 2) && args[0].equals("validateDocs")) { try { validateDocs(Paths.get(args[1])); } catch (Throwable t) { t.printStackTrace(); System.exit(100); } } else { for (String name : reservedIdentifiers()) { System.out.println(name); } } } private static void validateDocs(Path path) throws IOException { System.out.println("Validating " + path); List<String> lines = Files.readAllLines(path); if (lines.stream().filter(s -> s.startsWith(TABLE_PREFIX)).count() != 3) { throw new RuntimeException("Failed to find exactly one table"); } Iterator<String> iterator = lines.iterator(); // find table and skip header while (!iterator.next().startsWith(TABLE_PREFIX)) { // skip } if (iterator.next().startsWith(TABLE_PREFIX)) { throw new RuntimeException("Expected to find a header line"); } if (!iterator.next().startsWith(TABLE_PREFIX)) { throw new RuntimeException("Found multiple header lines"); } Set<String> reserved = reservedIdentifiers(); Set<String> found = new HashSet<>(); while (true) { String line = iterator.next(); if (line.startsWith(TABLE_PREFIX)) { break; } Matcher matcher = TABLE_ROW.matcher(line); if (!matcher.matches()) { throw new RuntimeException("Invalid table line: " + line); } String name = matcher.group(1); if (!reserved.contains(name)) { throw new RuntimeException("Documented identifier is not reserved: " + name); } if (!found.add(name)) { throw new RuntimeException("Duplicate documented identifier: " + name); } } for (String name : reserved) { if (!found.contains(name)) { throw new RuntimeException("Reserved identifier is not documented: " + name); } } System.out.println(format("Validated %s reserved identifiers", reserved.size())); } public static Set<String> reservedIdentifiers() { return possibleIdentifiers().stream().filter(ReservedIdentifiers::reserved).sorted() .collect(toImmutableSet()); } private static Set<String> possibleIdentifiers() { ImmutableSet.Builder<String> names = ImmutableSet.builder(); Vocabulary vocabulary = SqlBaseLexer.VOCABULARY; for (int i = 0; i <= vocabulary.getMaxTokenType(); i++) { String name = nullToEmpty(vocabulary.getLiteralName(i)); Matcher matcher = IDENTIFIER.matcher(name); if (matcher.matches()) { names.add(matcher.group(1)); } } return names.build(); } private static boolean reserved(String name) { try { return !(PARSER.createExpression(name) instanceof Identifier); } catch (ParsingException ignored) { return true; } } }