Added the modules and everything

This commit is contained in:
standash 2017-08-24 17:37:25 +02:00
parent 07af5bf983
commit b4f1ccff9b
87 changed files with 28121 additions and 0 deletions

7
.gitignore vendored Executable file
View File

@ -0,0 +1,7 @@
.classpath
.project
*.iml
*.ipr
*.iws
.idea/
target/

136
molerat/pom.xml Normal file
View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- parent project -->
<parent>
<groupId>it.unitn</groupId>
<artifactId>foss-vuln-tracker</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>it.unitn.molerat</groupId>
<artifactId>molerat</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- declare dependencies -->
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.7</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>bson</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>it.unitn.repoman</groupId>
<artifactId>repoman</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-core</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>4.2.0.201601211800-r</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit-cli</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit-javahl16</artifactId>
<version>1.8.13</version>
</dependency>
<!--
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit-javahl</artifactId>
<version>1.3.5</version>
</dependency>
-->
</dependencies>
<!-- build plugins -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>it.unitn.molerat.cmd.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,267 @@
package it.unitn.molerat.cmd;
import it.unitn.molerat.data.csv.InputDataPoint;
import it.unitn.molerat.data.csv.VulnEvidenceDataPoint;
import it.unitn.molerat.data.db.MongoWrapper;
import it.unitn.molerat.data.memory.AnalysisEntry;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.trackers.vuln.VulnerabilityEvidenceTracker;
import it.unitn.molerat.repos.trackers.vuln.VulnerabilityEvidenceTrackerFactory;
import it.unitn.molerat.repos.utils.IORoutines;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.cli.*;
import org.bson.types.ObjectId;
public class Main {
private static MongoWrapper db = new MongoWrapper("molerat");
public static void main(String[] args) {
Options opts = new Options();
Option listTrackersOpt = Option.builder()
.longOpt("list-trackers")
.desc("List the available trackers for vulnerability molerat.evidence")
.build();
opts.addOption(listTrackersOpt);
Option projectNameOpt = Option.builder()
.longOpt("project-name")
.desc("The name of the project")
.hasArg()
.build();
opts.addOption(projectNameOpt);
Option repoTypeOpt = Option.builder()
.longOpt("repo-type")
.desc("The type of the source code repository ('git' or 'svn')")
.hasArg()
.build();
opts.addOption(repoTypeOpt);
Option repoPathOpt = Option.builder()
.longOpt("repo-path")
.desc("The path of the working copy of the source code repository")
.hasArg()
.build();
opts.addOption(repoPathOpt);
Option cveIdOpt = Option.builder()
.longOpt("cve-id")
.desc("The CVE identifier of a vulnerability")
.hasArg()
.build();
opts.addOption(cveIdOpt);
Option fixCommitOpt = Option.builder()
.longOpt("fix-commit")
.desc("The commit that fixed a vulnerability")
.hasArg()
.build();
opts.addOption(fixCommitOpt);
Option trackerTypeOpt = Option.builder()
.longOpt("tracker-type")
.desc("The type of the vulnerability molerat.evidence tracker")
.hasArg()
.build();
opts.addOption(trackerTypeOpt);
Option inputFileOpt = Option.builder()
.longOpt("input-file")
.desc("Path to the input .csv file")
.hasArg()
.argName("input-file-path")
.build();
opts.addOption(inputFileOpt);
Option outputFileOpt = Option.builder()
.longOpt("output-file")
.desc("Path to the output .csv file")
.hasArg()
.argName("output-file-path")
.build();
opts.addOption(outputFileOpt);
CommandLineParser cmdParser = new DefaultParser();
HelpFormatter helpFormatter = new HelpFormatter();
CommandLine cmd;
try {
cmd = cmdParser.parse(opts, args);
if (cmd.getOptions().length == 0) {
throw new ParseException("Arguments are not specified");
}
if (cmd.hasOption("list-trackers")) {
System.out.println(VulnerabilityEvidenceTrackerFactory.getTrackersList());
return;
}
if (cmd.hasOption("input-file")) {
String i = cmd.getOptionValue("input-file");
collectVulnEvidence(i);
}
if (cmd.hasOption("output-file")) {
String o = cmd.getOptionValue("output-file");
generateCsv(o);
}
if (!cmd.hasOption("input-file") && !cmd.hasOption("output-file")) {
String projectName = null;
String repoType = null;
String repoPath = null;
String cveId = null;
String fixCommit = null;
String trackerType = null;
if (cmd.hasOption("project-name")) {
projectName = cmd.getOptionValue("project-name");
}
if (cmd.hasOption("repo-type")) {
repoType = cmd.getOptionValue("repo-type");
}
if(cmd.hasOption("repo-path")) {
repoPath = cmd.getOptionValue("repo-path");
}
if(cmd.hasOption("cve-id")) {
cveId = cmd.getOptionValue("cve-id");
}
if(cmd.hasOption("fix-commit")) {
fixCommit = cmd.getOptionValue("fix-commit");
}
if(cmd.hasOption("tracker-type")) {
trackerType = cmd.getOptionValue("tracker-type");
}
if (projectName == null) {
throw new ParseException("The 'project-name' parameter is not specified");
}
if (repoType == null) {
throw new ParseException("The 'repo-type' parameter is not specified");
}
if (repoPath == null) {
throw new ParseException("The 'repo-path' parameter is not specified");
}
if (cveId == null) {
throw new ParseException("The 'cve-id' parameter is not specified");
}
if (fixCommit == null) {
throw new ParseException("The 'fix-commit' parameter is not specified");
}
if (trackerType == null) {
throw new ParseException("The 'tracker-type' parameter is not specified");
}
collect(projectName, repoType, repoPath, cveId, fixCommit, trackerType);
}
}
catch (ParseException e) {
System.out.println("ERROR: " + e.getMessage());
helpFormatter.printHelp("utility-name", opts);
}
}
private static void collectVulnEvidence(String inputCsvPath) {
try {
Set<InputDataPoint> inputs = IORoutines.readInputDataPoints(inputCsvPath);
for (InputDataPoint ip : inputs) {
collect(ip.PROJECTID,
ip.REPO_TYPE,
ip.REPO_ROOT,
ip.CVEID,
ip.FIX_REV,
ip.TRACKER_TYPE);
}
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
}
private static void collect(String projectName, String repositoryType,
String repositoryPath, String cveName, String fixCommit, String trackerType) {
try {
boolean entryExists = db.analysisEntryExists(projectName, cveName, repositoryType, repositoryPath);
if (entryExists) {
System.out.format("WARNING: The analysis entry for '%s' from '%s' already exists, skipping\n", cveName, projectName);
return;
}
System.out.format("INFO: Collecting the molerat.evidence for '%s' from '%s'\n", cveName, projectName);
VulnerabilityEvidenceTracker vulnTracker = VulnerabilityEvidenceTrackerFactory.getTracker(
repositoryPath,
fixCommit,
repositoryType,
trackerType
);
vulnTracker.trackEvidence();
AnalysisEntry entry = new AnalysisEntry(
cveName,
projectName,
repositoryType,
repositoryPath,
fixCommit,
vulnTracker.getProcessedCommits(),
vulnTracker.getEvidences(),
null // we're not tracking any changes so far
);
boolean isSuccessful = db.insertAnalysisEntry(entry);
if (!isSuccessful) {
System.out.format("WARNING: Could not get any molerat.evidence for '%s' in '%s'\n", cveName, projectName);
}
System.out.println("INFO: Done!");
}
catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
}
private static void generateCsv(String outFilePath) {
System.out.format("INFO: generating the .csv file '%s'\n", outFilePath);
String csvHeader = new VulnEvidenceDataPoint().getHeader() + "\n";
try {
IORoutines.writeFile(outFilePath, csvHeader);
Set<ObjectId> cveIds = db.getAllCveIds();
for (ObjectId cveId : cveIds) {
AnalysisEntry analysis = db.getAnalysisEntry(cveId);
if (analysis == null) {
continue;
}
String projectName = analysis.getProjectName();
String cveName = analysis.getCveName();
System.out.format("INFO: writing the entries for '%s'\n", cveName);
Set<VulnerabilityEvidence> evidences = analysis.getVulnEvidencesSet();
if (evidences.size() == 0) {
throw new Exception(String.format("There is no molerat.evidence for '%s' in the database", cveName));
}
Map<String, Integer> locsCount = new LinkedHashMap<>();
for (VulnerabilityEvidence evd : evidences) {
if (locsCount.containsKey(evd.getCommit())) {
int count = locsCount.get(evd.getCommit());
locsCount.remove(evd.getCommit());
locsCount.put(evd.getCommit(), ++count);
} else {
locsCount.put(evd.getCommit(), 1);
}
}
int timestamp = 0;
for (Map.Entry<String, Integer> entry : locsCount.entrySet()) {
VulnEvidenceDataPoint dp = new VulnEvidenceDataPoint(new String[]{
projectName,
cveName,
entry.getKey(),
String.valueOf(timestamp--),
String.valueOf(entry.getValue())
});
IORoutines.writeFile(outFilePath, dp.toString() + "\n");
}
}
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,16 @@
package it.unitn.molerat.cmd.experiments;
import it.unitn.molerat.data.csv.InputDataPoint;
import it.unitn.molerat.repos.utils.IORoutines;
import java.util.Set;
public class AbstractExperiment {
protected static Set<InputDataPoint> readInputDataPoints(String path) throws Exception {
return IORoutines.readInputDataPoints(path);
}
protected static void saveOutput(String path, String output) throws Exception {
IORoutines.writeFile(path, output + "\n");
}
}

View File

@ -0,0 +1,61 @@
package it.unitn.molerat.cmd.experiments;
import it.unitn.molerat.data.csv.InputDataPoint;
import it.unitn.molerat.data.csv.OutputDataPoint;
import it.unitn.molerat.data.csv.PerfOutputDataPoint;
import it.unitn.molerat.repos.utils.CommitMetrics;
import it.unitn.molerat.repos.wrappers.GitRepoWrapper;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.Set;
public class CalculateAllChangesExperiment extends AbstractExperiment {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("USAGE: [input.csv] [output.csv]");
return;
}
String inputCsvPath = args[0];
String outputCsvPath = args[1];
try {
Set<InputDataPoint> inputs = readInputDataPoints(inputCsvPath);
saveOutput(outputCsvPath, new PerfOutputDataPoint().getHeader());
for (InputDataPoint idp : inputs) {
System.out.println("Processing the " + idp.CVEID + "...");
long timeNow = System.currentTimeMillis();
RepoWrapper wrapper = new GitRepoWrapper(idp.REPO_ROOT);
Set<String> processedCommits = wrapper.getRevisionNumbers(idp.FIX_REV);
int timestamp = 0;
for (String commit : processedCommits) {
int publicAPICount = CommitMetrics.getNumberOfPublicMethodsPerRevision(commit, wrapper);
int rem = CommitMetrics.getGlobalPublicMethodsRemoved(commit, idp.FIX_REV, wrapper);
double currentUntouched = (((double) publicAPICount - (double) rem) / (double) publicAPICount) * 100.0;
currentUntouched = Math.round(currentUntouched * 100.0) / 100.0;
String[] output = new String[]{
idp.CVEID,
idp.TRACKER_TYPE,
"empty",
commit,
String.valueOf(timestamp),
"empty",
String.valueOf(publicAPICount),
String.valueOf(rem),
String.valueOf(currentUntouched)
};
OutputDataPoint odp = new OutputDataPoint(output);
saveOutput(outputCsvPath, odp.toString());
timestamp--;
}
long timeAfter = System.currentTimeMillis();
System.out.println("TIME (ms): " + (timeAfter - timeNow));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,53 @@
package it.unitn.molerat.cmd.experiments;
import it.unitn.molerat.data.csv.InputDataPoint;
import it.unitn.molerat.data.csv.PerfOutputDataPoint;
import it.unitn.molerat.repos.trackers.vuln.VulnerabilityEvidenceTracker;
import it.unitn.molerat.repos.trackers.vuln.VulnerabilityEvidenceTrackerFactory;
import it.unitn.molerat.repos.utils.CommitMetrics;
import java.util.Set;
public class ChangeEvdPerformanceExperiment extends AbstractExperiment {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("USAGE: [input.csv] [output.csv]");
return;
}
String inputCsvPath = args[0];
String outputCsvPath = args[1];
try {
Set<InputDataPoint> inputs = readInputDataPoints(inputCsvPath);
saveOutput(outputCsvPath, new PerfOutputDataPoint().getHeader());
for (InputDataPoint idp : inputs) {
System.out.println("Processing the " + idp.CVEID + "...");
VulnerabilityEvidenceTracker vulnTracker = VulnerabilityEvidenceTrackerFactory.getTracker(idp.REPO_ROOT, idp.FIX_REV, idp.REPO_TYPE, idp.TRACKER_TYPE);
vulnTracker.trackEvidence();
Set<String> processedCommits = vulnTracker.getProcessedCommits();
for (String commit : processedCommits) {
long timeNow = System.currentTimeMillis();
int publicAPICount = CommitMetrics.getNumberOfPublicMethodsPerRevision(commit, vulnTracker.getRepoWrapper());
int rem = CommitMetrics.getGlobalPublicMethodsRemoved(commit, vulnTracker.getFixedRevision(), vulnTracker.getRepoWrapper());
double currentUntouched = (((double) publicAPICount - (double) rem) / (double) publicAPICount) * 100.0;
currentUntouched = Math.round(currentUntouched * 100.0) / 100.0;
long timeAfter = System.currentTimeMillis();
String[] output = new String[]{
idp.CVEID,
idp.TRACKER_TYPE,
String.valueOf(timeAfter - timeNow)
};
PerfOutputDataPoint odp = new PerfOutputDataPoint(output);
saveOutput(outputCsvPath, odp.toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,45 @@
package it.unitn.molerat.cmd.experiments;
import it.unitn.molerat.data.csv.InputDataPoint;
import it.unitn.molerat.data.csv.PerfOutputDataPoint;
import it.unitn.molerat.repos.trackers.vuln.VulnerabilityEvidenceTracker;
import it.unitn.molerat.repos.trackers.vuln.VulnerabilityEvidenceTrackerFactory;
import java.util.Set;
public class VulnEvdPerformanceExperiment extends AbstractExperiment {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("USAGE: [input.csv] [output.csv]");
return;
}
String inputCsvPath = args[0];
String outputCsvPath = args[1];
try {
Set<InputDataPoint> inputs = readInputDataPoints(inputCsvPath);
saveOutput(outputCsvPath, new PerfOutputDataPoint().getHeader());
for (InputDataPoint idp : inputs) {
System.out.println("Processing the " + idp.CVEID + "...");
long timeNow = System.currentTimeMillis();
VulnerabilityEvidenceTracker vulnTracker = VulnerabilityEvidenceTrackerFactory.getTracker(idp.REPO_ROOT, idp.FIX_REV, idp.REPO_TYPE, idp.TRACKER_TYPE);
vulnTracker.trackEvidence();
long timeAfter = System.currentTimeMillis();
String[] output = new String[]{
idp.CVEID,
idp.TRACKER_TYPE,
String.valueOf(timeAfter - timeNow)
};
PerfOutputDataPoint odp = new PerfOutputDataPoint(output);
saveOutput(outputCsvPath, odp.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,68 @@
package it.unitn.molerat.data.csv;
import java.lang.reflect.Field;
public abstract class AbstractDataPoint {
public AbstractDataPoint(String[] entries) throws Exception {
Field[] fields = this.getClass().getFields();
if (entries.length != fields.length) {
throw new Exception("Bad entries for initializing a molerat.data point!");
}
int i = 0;
for (Field field : fields) {
if (!field.getName().equals("this$0")) {
try {
field.set(this, entries[i++]);
} catch (IllegalArgumentException e) {
System.out.println("ERROR: " + e.getMessage());
} catch (IllegalAccessException e) {
System.out.println("ERROR: " + e.getMessage());
}
}
}
}
public AbstractDataPoint(String str) throws Exception {
this(str.replace(" ", "").split(","));
}
public AbstractDataPoint() {
}
@Override
public final String toString() {
StringBuilder builder = new StringBuilder();
Field[] fields = this.getClass().getFields();
for (Field field : fields) {
if (!field.getName().equals("this$0")) {
try {
builder.append(field.get(this) + ",");
} catch (IllegalArgumentException e) {
System.out.println("ERROR: " + e.getMessage());
} catch (IllegalAccessException e) {
System.out.println("ERROR: " + e.getMessage());
}
}
}
builder.deleteCharAt(builder.length()-1);
return builder.toString();
}
public final String getHeader() {
StringBuilder builder = new StringBuilder();
Field[] fields = this.getClass().getFields();
for (Field field : fields) {
if (!field.getName().equals("this$0")) {
try {
builder.append(field.getName() + ",");
} catch (IllegalArgumentException e) {
System.out.println("ERROR: " + e.getMessage());
}
}
}
builder.deleteCharAt(builder.length()-1);
return builder.toString();
}
}

View File

@ -0,0 +1,25 @@
package it.unitn.molerat.data.csv;
/**
* Created by standash on 06/12/2016.
*/
public class ChangeStatsDataPoint extends AbstractDataPoint {
public String PROJECT;
public String CURRENT_COMMIT;
public String ADDED_LINES;
public String DELETED_LINES;
public String TOUCHED_METHODS;
public String TOUCHED_FILES;
public ChangeStatsDataPoint(String[] entries) throws Exception {
super(entries);
}
public ChangeStatsDataPoint(String str) throws Exception {
super(str);
}
public ChangeStatsDataPoint() {
}
}

View File

@ -0,0 +1,21 @@
package it.unitn.molerat.data.csv;
public class FixStatsDataPoint extends AbstractDataPoint {
public String CVEID;
public String ADDED_LINES;
public String DELETED_LINES;
public String TOUCHED_METHODS;
public String TOUCHED_FILES;
public FixStatsDataPoint(String[] entries) throws Exception {
super(entries);
}
public FixStatsDataPoint(String str) throws Exception {
super(str);
}
public FixStatsDataPoint() {
}
}

View File

@ -0,0 +1,23 @@
package it.unitn.molerat.data.csv;
public final class InputDataPoint extends AbstractDataPoint {
public String PROJECTID;
public String CVEID;
public String REPO_TYPE;
public String REPO_ROOT;
public String FIX_REV;
public String TRACKER_TYPE;
public InputDataPoint(String[] entries) throws Exception {
super(entries);
}
public InputDataPoint(String str) throws Exception {
super(str);
}
public InputDataPoint() {
}
}

View File

@ -0,0 +1,26 @@
package it.unitn.molerat.data.csv;
public class OutputDataPoint extends AbstractDataPoint {
public String CVEID;
public String TRACKING_METHOD;
public String CURRENT_FILE;
public String CURRENT_REV;
public String TIMESTAMP;
public String EVIDENCE_LOC;
//public String GLOBAL_PUBLIC_API_COUNT;
//public String GLOBAL_PUBLIC_API_REMOVED;
//public String GLOBAL_PUBLIC_API_UNTOUCHED;
public OutputDataPoint(String[] entries) throws Exception {
super(entries);
}
public OutputDataPoint(String str) throws Exception {
super(str);
}
public OutputDataPoint() {
}
}

View File

@ -0,0 +1,21 @@
package it.unitn.molerat.data.csv;
public class PerfOutputDataPoint extends AbstractDataPoint {
public String CVEID;
public String TRACKING_METHOD;
public String TIME_MS;
public PerfOutputDataPoint(String[] entries) throws Exception {
super(entries);
}
public PerfOutputDataPoint(String str) throws Exception {
super(str);
}
public PerfOutputDataPoint() {
}
}

View File

@ -0,0 +1,22 @@
package it.unitn.molerat.data.csv;
public class VulnEvidenceDataPoint extends AbstractDataPoint {
public String PROJECT_NAME;
public String CVEID;
public String CURRENT_REV;
public String TIMESTAMP;
public String EVIDENCE_LOC;
public VulnEvidenceDataPoint(String[] entries) throws Exception {
super(entries);
}
public VulnEvidenceDataPoint(String str) throws Exception {
super(str);
}
public VulnEvidenceDataPoint() {
}
}

View File

@ -0,0 +1,245 @@
package it.unitn.molerat.data.db;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Indexes;
import it.unitn.molerat.data.memory.AnalysisEntry;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import org.bson.Document;
import org.bson.types.ObjectId;
import java.util.*;
public class MongoWrapper {
private static final String projectCollection = "projects";
private static final String vulnsCollection = "vulns";
private static final String vulnEvdCollection = "vuln_evidences";
private MongoClient client = null;
private MongoDatabase db = null;
public MongoWrapper(String dbName) {
this.client = new MongoClient();
this.db = client.getDatabase(dbName);
}
private FindIterable<Document> getEntries(BasicDBObject query, String collection) {
MongoCollection<Document> docs = db.getCollection(collection);
return docs.find(query);
}
private Document getEntry(BasicDBObject query, String collection) {
return getEntries(query, collection).first();
}
private ObjectId getEntryId(Document doc) {
return (doc != null) ? doc.getObjectId("_id") : null;
}
private Document getProjectEntry(String name, String repoType, String repoPath) {
BasicDBObject query = new BasicDBObject();
query.put("name", name);
query.put("repo_type", repoType);
query.put("repo_path", repoPath);
return getEntry(query, projectCollection);
}
private Document getProjectEntry(ObjectId projectId) {
BasicDBObject query = new BasicDBObject();
query.put("_id", projectId);
return getEntry(query, projectCollection);
}
private ObjectId getProjectId(String name, String repoType, String repoPath) {
return getEntryId(getProjectEntry(name, repoType, repoPath));
}
private ObjectId getProjectId(ObjectId cveId) {
return getCveEntry(cveId).getObjectId("owner_id");
}
private Document getCveEntry(ObjectId projectId, String cve) {
BasicDBObject query = new BasicDBObject();
query.put("cve", cve);
query.put("owner_id", projectId);
return getEntry(query, vulnsCollection);
}
private Document getCveEntry(ObjectId cveId) {
BasicDBObject query = new BasicDBObject();
query.put("_id", cveId);
return getEntry(query, vulnsCollection);
}
private ObjectId getCveId(ObjectId projectId, String cve) {
return getEntryId(getCveEntry(projectId, cve));
}
public Set<ObjectId> getAllCveIds() {
Set<ObjectId> ids = new LinkedHashSet<>();
MongoCollection<Document> vulns = db.getCollection(vulnsCollection);
FindIterable<Document> docs = vulns.find();
for (Document doc : docs) {
ids.add(doc.getObjectId("_id"));
}
return ids;
}
private FindIterable<Document> getVulnEvidences(ObjectId cveId) {
BasicDBObject query = new BasicDBObject() ;
query.put("owner_id", cveId);
FindIterable<Document> result = getEntries(query, vulnEvdCollection);
result.sort(new BasicDBObject("order", -1));
return result;
}
private ObjectId insertProject(String name, String repoType, String repoPath) {
Document proj = getProjectEntry(name, repoType, repoPath);
if (proj == null) {
MongoCollection<Document> projects = db.getCollection(projectCollection);
proj = new Document("name", name)
.append("repo_type", repoType)
.append("repo_path", repoPath);
projects.insertOne(proj);
}
return getEntryId(proj);
}
private ObjectId insertCve(ObjectId projectId, String cve, String fixCommit) {
Document vuln = getCveEntry(projectId, cve);
if (vuln == null) {
MongoCollection<Document> vulns = db.getCollection(vulnsCollection);
vuln = new Document("cve", cve)
.append("fix_commit", fixCommit)
.append("owner_id", projectId)
.append("processed", false);
vulns.insertOne(vuln);
MongoCollection<Document> projects = db.getCollection(projectCollection);
projects.findOneAndUpdate(new BasicDBObject("_id", projectId), new BasicDBObject("$push",
new BasicDBObject("vulns", getEntryId(vuln))));
}
return getEntryId(vuln);
}
private boolean isVulnProcessed(ObjectId cveId) {
MongoCollection<Document> vulns = db.getCollection(vulnsCollection);
Document cve = vulns.find(new BasicDBObject("_id", cveId)).first();
return (Boolean)cve.get("processed");
}
public boolean insertAnalysisEntry(AnalysisEntry entry) {
// if there's no molerat.evidence for some reason, return false
if (entry.getVulnEvidences().isEmpty()) {
return false;
}
ObjectId projectId = insertProject(entry.getProjectName(), entry.getRepositoryType(), entry.getRepositoryPath());
ObjectId cveId = insertCve(projectId, entry.getCveName(), entry.getFixCommit());
MongoCollection<Document> vulns = db.getCollection(vulnsCollection);
MongoCollection<Document> evds = db.getCollection(vulnEvdCollection);
if (isVulnProcessed(cveId)) {
vulns.updateOne(
new BasicDBObject("_id", cveId),
new BasicDBObject("$set", new BasicDBObject("processed", false))
);
evds.deleteMany(new BasicDBObject("owner_id", cveId));
}
List<Document> records = new LinkedList<Document>();
int order= 0;
Set<String> commits = entry.getCommits();
for (String commit : commits) {
Set<VulnerabilityEvidence> evidences = entry.getVulnEvidences().get(commit);
if (evidences != null) {
for (VulnerabilityEvidence e : evidences) {
BasicDBObject record = new BasicDBObject();
record.put("owner_id", cveId);
record.put("revision", commit);
record.put("order", order);
record.put("file_path", e.getPath());
record.put("container", e.getContainer());
record.put("line_number", e.getLineNumber());
record.put("line_contents", e.getLineContents());
Document doc = new Document(record);
records.add(doc);
}
}
order--;
}
evds.insertMany(records);
vulns.updateOne(
new BasicDBObject("_id", cveId),
new BasicDBObject("$set", new BasicDBObject("processed", true))
);
//create index
evds.createIndex(Indexes.descending("order"));
return true;
}
public AnalysisEntry getAnalysisEntry(String projectName, String cveName, String repoType, String repoPath) {
ObjectId projectId = getProjectId(projectName, repoType, repoPath);
ObjectId cveId = getCveId(projectId, cveName);
return getAnalysisEntry(cveId);
}
public boolean analysisEntryExists(String projectName, String cveName, String repoType, String repoPath) {
ObjectId projectId = getProjectId(projectName, repoType, repoPath);
ObjectId cveId = getCveId(projectId, cveName);
return (projectId != null && cveId != null);
}
public Set<AnalysisEntry> getAnalysisEntries() {
Set<AnalysisEntry> entries = new LinkedHashSet<>();
FindIterable<Document> cves = db.getCollection(vulnsCollection).find();
for (Document cve : cves) {
ObjectId cveId = cve.getObjectId("_id");
AnalysisEntry entry = getAnalysisEntry(cveId);
entries.add(entry);
}
return entries;
}
public AnalysisEntry getAnalysisEntry(ObjectId cveId) {
if (!isVulnProcessed(cveId)) {
return null;
}
ObjectId projectId = getProjectId(cveId);
Document projectDoc = getProjectEntry(projectId);
String projectName = projectDoc.getString("name");
String repoType = projectDoc.getString("repo_type");
String repoPath = projectDoc.getString("repo_path");
Document cveDoc = getCveEntry(cveId);
String cveName = cveDoc.getString("cve");
String fixCommit = cveDoc.getString("fix_commit");
Map<String, Set<VulnerabilityEvidence>> vulnEvidences = new LinkedHashMap<>();
FindIterable<Document> docs = getVulnEvidences(cveId);
for (Document doc : docs) {
String filePath = doc.getString("file_path");
String container = doc.getString("container");
String revision = doc.getString("revision");
int lineNumber = doc.getInteger("line_number");
String lineContents = doc.getString("line_contents");
VulnerabilityEvidence evidence = new VulnerabilityEvidence(filePath, revision, container, lineNumber, lineContents);
if (vulnEvidences.containsKey(revision)) {
vulnEvidences.get(revision).add(evidence);
}
else {
Set<VulnerabilityEvidence> set = new LinkedHashSet<>();
set.add(evidence);
vulnEvidences.put(evidence.getCommit(), set);
}
}
/* TODO: add stuff for getting the changes molerat.evidence
Map<String, Set<ChangeEvidence>> chgEvidences = new TreeMap<>();
*/
return new AnalysisEntry(cveName, projectName, repoType, repoPath, fixCommit, vulnEvidences.keySet(), vulnEvidences, null);
}
}

View File

@ -0,0 +1,74 @@
package it.unitn.molerat.data.memory;
import it.unitn.molerat.evidence.ChangeEvidence;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
public class AnalysisEntry {
private final String cveId;
private final String projectId;
private final String fixCommit;
private final String repositoryType;
private final String repositoryPath;
private final Set<String> commits;
private final Map<String, Set<VulnerabilityEvidence>> vulnEvidences;
private final Map<String, Set<ChangeEvidence>> changEvidences;
public AnalysisEntry(String cveId, String projectId, String repositoryType, String repositoryPath,
String fixCommit, Set<String> commits,
Map<String, Set<VulnerabilityEvidence>> vulnEvidences,
Map<String, Set<ChangeEvidence>> changEvidences) {
this.cveId = cveId;
this.projectId = projectId;
this.repositoryType = repositoryType;
this.repositoryPath = repositoryPath;
this.commits = commits;
this.fixCommit = fixCommit;
this.vulnEvidences = vulnEvidences;
this.changEvidences = changEvidences;
}
public String getCveName() {
return cveId;
}
public Set<String> getCommits() {
return commits;
}
public String getFixCommit() {
return fixCommit;
}
public String getRepositoryType() {
return repositoryType;
}
public String getRepositoryPath() {
return repositoryPath;
}
public Map<String, Set<VulnerabilityEvidence>> getVulnEvidences() {
return vulnEvidences;
}
public Set<VulnerabilityEvidence> getVulnEvidencesSet() {
Set<VulnerabilityEvidence> evidences = new LinkedHashSet<>();
for (Set<VulnerabilityEvidence> eset : vulnEvidences.values()) {
evidences.addAll(eset);
}
return evidences;
}
public Map<String, Set<ChangeEvidence>> getChangEvidences() {
return changEvidences;
}
public String getProjectName() {
return projectId;
}
}

View File

@ -0,0 +1,46 @@
package it.unitn.molerat.data.printers;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import java.util.*;
public class VulnerabilityEvidencePrinter {
private final StringBuilder builder = new StringBuilder();
public VulnerabilityEvidencePrinter(Set<VulnerabilityEvidence> evidence) {
List<VulnerabilityEvidence> sortedEvidence = new LinkedList<>(evidence);
Collections.sort(sortedEvidence, new Comparator<VulnerabilityEvidence>() {
@Override
public int compare(VulnerabilityEvidence o1, VulnerabilityEvidence o2) {
if (o1.getLineNumber() < o2.getLineNumber()) {
return -1;
} else if (o1.getLineNumber() > o2.getLineNumber()) {
return 1;
} else {
return 0;
}
}
});
String path = "";
String container = "";
for (VulnerabilityEvidence e : sortedEvidence) {
if (!path.equals(e.getPath())) {
path = e.getPath();
builder.append("<" + path + ">\n");
}
if (!container.equals(e.getContainer())) {
container = e.getContainer();
builder.append("\t" + container + "\n");
}
builder.append("\t\t" + e.getLineNumber() + ": " + e.getLineContents() + "\n");
}
}
@Override
public String toString() {
return this.builder.toString();
}
}

View File

@ -0,0 +1,45 @@
package it.unitn.molerat.evidence;
public class ChangeEvidence extends GenericEvidence {
private final boolean removed;
public ChangeEvidence(String file, String commit, String container, boolean removed) {
super(file, commit, container);
this.removed = removed;
}
public boolean isMethodOrConstructor() {
return this.container.contains("(") && this.container.contains(")");
}
public boolean isAbsentInFix() {
return removed;
}
public String getAccessModifier() {
if (this.container.startsWith("public")) {
return "public";
}
else if (this.container.startsWith("protected")) {
return "protected";
}
else if (this.container.startsWith("private")) {
return "private";
}
return "";
}
public boolean isPublicMethodOrConstructor() {
return this.isMethodOrConstructor() && this.getAccessModifier().equals("public");
}
public boolean isProtectedMethodOrConstructor() {
return this.isMethodOrConstructor() && this.getAccessModifier().equals("protected");
}
public boolean isPrivateMethodOrConstructor() {
return this.isMethodOrConstructor() && this.getAccessModifier().equals("private");
}
}

View File

@ -0,0 +1,93 @@
package it.unitn.molerat.evidence;
import java.util.Map;
import java.util.TreeMap;
public class Changes {
private final String path;
private final String leftRev;
private final String rightRev;
private final Map<Integer, String> deletions;
private final Map<Integer, String> additions;
private String renamedTo = "";
public Changes(String path, String leftRev, String rightRev) {
this.path = path;
this.leftRev = leftRev;
this.rightRev = rightRev;
this.deletions = new TreeMap<>();
this.additions = new TreeMap<>();
}
public Changes(String path, String renamedTo, String leftRev, String rightRev) {
this(path, leftRev, rightRev);
this.renamedTo = renamedTo;
}
public Changes(Changes changes, String leftRev, String rightRev) {
this.path = changes.path;
this.leftRev = leftRev;
this.rightRev = rightRev;
this.deletions = changes.deletions;
this.additions = changes.additions;
}
public String getRenamedTo() {
return renamedTo;
}
public boolean wasRenamed() {
return !renamedTo.equals("");
}
public String getPath() {
return this.path;
}
public String getLeftRevision() {
return this.leftRev;
}
public String getRightRevision() {
return this.rightRev;
}
public void putDeletedLine(int lineNumber, String line) {
this.deletions.put(lineNumber, line);
}
public void putAddedLine(int lineNumber, String line) {
this.additions.put(lineNumber, line);
}
public Map<Integer, String> getDeletions() {
return this.deletions;
}
public Map<Integer, String> getAdditions() {
return this.additions;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("CHANGES:\n");
for (Map.Entry<Integer, String> entry : this.deletions.entrySet()) {
builder.append("-, " + this.formatAsCSV(entry) + "\n");
}
for (Map.Entry<Integer, String> entry : this.additions.entrySet()) {
builder.append("+, " + this.formatAsCSV(entry) + "\n");
}
return builder.toString();
}
private String formatAsCSV(Map.Entry<Integer, String> entry) {
return this.leftRev + ", " +
this.path + ", " +
entry.getKey() + ", " +
entry.getValue();
}
}

View File

@ -0,0 +1,30 @@
package it.unitn.molerat.evidence;
public class GenericEvidence {
protected final String commit;
protected final String container;
protected String path;
protected GenericEvidence(String file, String commit, String container) {
this.path = file;
this.commit = commit;
this.container = container;
}
public String getContainer() {
return this.container;
}
public String getCommit() {
return this.commit;
}
public String getPath() {
return this.path;
}
public void setPath(String path) {
this.path = path;
}
}

View File

@ -0,0 +1,32 @@
package it.unitn.molerat.evidence;
public class VulnerabilityEvidence extends GenericEvidence {
protected final int lineNumber;
protected final String lineContents;
public VulnerabilityEvidence(String file, String commit, String container, int lineNumber, String lineContents) {
super(file, commit, container);
this.lineNumber = lineNumber;
this.lineContents = lineContents
.trim()
.replace("\t","");
}
public int getLineNumber() {
return this.lineNumber;
}
public String getLineContents() {
return this.lineContents;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("<" + commit + ": " + path + ">\n");
builder.append("\t" + container + "\n");
builder.append("\t\t" + lineNumber + ": " + lineContents + "\n\t\n");
return builder.toString();
}
}

View File

@ -0,0 +1,56 @@
package it.unitn.molerat.repos.trackers;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.*;
public abstract class AbstractEvidenceTracker {
protected final String fixedRevision;
protected final String vulnRevision;
protected final String repoPath;
protected final RepoWrapper repoWrapper;
protected Set<Changes> changes;
protected Set<String> commits = new LinkedHashSet<>();
protected Set<String> restOfCommits = new LinkedHashSet<>();
public AbstractEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
this.fixedRevision = fixedRev;
this.repoPath = wrapper.getBasePath();
this.repoWrapper = wrapper;
Iterator<String> commitsIter = repoWrapper.getRevisionNumbers(fixedRev).iterator();
this.vulnRevision = commitsIter.next();
while (commitsIter.hasNext()) {
restOfCommits.add(commitsIter.next());
}
String initDiff = repoWrapper.doDiff(vulnRevision, fixedRevision);
this.changes = repoWrapper.inferChangesFromDiff(initDiff, vulnRevision, fixedRevision);
}
public RepoWrapper getRepoWrapper() {
return this.repoWrapper;
}
public String getFixedRevision() {
return this.fixedRevision;
}
public Set<String> getProcessedCommits() {
return this.commits;
}
// apart from non-java files, filter the files that contain "test" in ther name as well
protected Set<Changes> filterNonJavaChanges(Set<Changes> changes) {
Set<Changes> filteredChanges = new HashSet<>();
for (Changes change : changes) {
if (!change.getPath().endsWith(".java") || change.getPath().toLowerCase().contains("test")) {
filteredChanges.add(change);
}
this.repoWrapper.filterCommentsAndBlanks(change.getDeletions());
this.repoWrapper.filterCommentsAndBlanks(change.getAdditions());
}
changes.removeAll(filteredChanges);
return changes;
}
public abstract void trackEvidence() throws Exception;
}

View File

@ -0,0 +1,108 @@
package it.unitn.molerat.repos.trackers.changes;
import it.unitn.molerat.evidence.ChangeEvidence;
import it.unitn.molerat.repos.trackers.AbstractEvidenceTracker;
import it.unitn.molerat.repos.utils.CommitMetrics;
import it.unitn.molerat.repos.utils.SignatureExtractor;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class ChangeEvidenceTracker extends AbstractEvidenceTracker {
protected final Map<String, Set<ChangeEvidence>> evidences = new TreeMap<>();
protected Map<String, Set<String>> fixConstructs;
protected ChangeEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
public ChangeEvidenceTracker(RepoWrapper repoWrapper, String fixedCommit, Set<String> commits) throws Exception {
this(repoWrapper, fixedCommit);
this.commits = commits;
this.fixConstructs = extractSignatures(this.fixedRevision);
}
protected Map<String, Set<String>> extractSignatures(String commit) throws Exception {
Map<String, Set<String>> result = new TreeMap<>();
Map<String, String> files = CommitMetrics.getFileContentsPerRevision(commit, this.repoWrapper);
for (Map.Entry<String, String> file : files.entrySet()) {
SignatureExtractor se = new SignatureExtractor(file.getValue());
Set<String> signatures = new HashSet<>();
for (String signature : se.getSignaturesWithLines().keySet()) {
signatures.add(signature);
}
result.put(file.getKey(), signatures);
}
return result;
}
@Override
public void trackEvidence() throws Exception {
for (String commit : this.commits) {
// long timeNow = System.currentTimeMillis();
Map<String, Set<String>> currentSignatures = extractSignatures(commit);
for (Map.Entry<String, Set<String>> currentSignature : currentSignatures.entrySet()) {
Set<String> temp = this.fixConstructs.get(currentSignature.getKey());
if (temp == null) {
for (String sign : currentSignature.getValue()) {
ChangeEvidence evidence = new ChangeEvidence(
currentSignature.getKey(),
commit,
sign,
true
);
if (evidence.isPublicMethodOrConstructor()) {
addEvidence(evidence);
}
}
}
else {
for (String sign : currentSignature.getValue()) {
boolean removed = true;
for (String fixSign : temp) {
if (sign.equals(fixSign)) {
removed = false;
break;
}
}
ChangeEvidence evidence = new ChangeEvidence(
currentSignature.getKey(),
commit,
sign,
removed
);
if (evidence.isPublicMethodOrConstructor()) {
addEvidence(evidence);
}
}
}
}
}
}
protected void addEvidence(ChangeEvidence evidence) {
if (this.evidences.containsKey(evidence.getCommit())) {
this.evidences.get(evidence.getCommit()).add(evidence);
}
else {
Set<ChangeEvidence> set = new HashSet<>();
set.add(evidence);
this.evidences.put(evidence.getCommit(), set);
}
}
public Set<ChangeEvidence> getEvidence(String commit) {
Set<ChangeEvidence> evd = this.evidences.get(commit);
return (evd != null) ? evd : new HashSet<>();
}
public Map<String, Set<ChangeEvidence>> getEvidences() {
return this.evidences;
}
}

View File

@ -0,0 +1,13 @@
package it.unitn.molerat.repos.trackers.changes;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
public class FullChangeEvidenceTracker extends ChangeEvidenceTracker {
public FullChangeEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
this.commits = wrapper.getRevisionNumbers(fixedRev);
this.fixConstructs = extractSignatures(this.fixedRevision);
}
}

View File

@ -0,0 +1,92 @@
package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class DeletionVulnerabilityEvidenceTracker extends VulnerabilityEvidenceTracker {
public DeletionVulnerabilityEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
@Override
protected Set<VulnerabilityEvidence> getInitialVulnerabilityEvidence(Changes changes) throws Exception {
return this.recordVulnerabilityEvidence(changes.getDeletions(), changes);
}
@Override
protected Set<VulnerabilityEvidence> getVulnerabilityEvidence(String currentEvidenceCommit, String previousEvidenceCommit, Set<Changes> changes) throws Exception {
Set<VulnerabilityEvidence> newEvidences = new HashSet<>();
Set<VulnerabilityEvidence> previousEvidences = getEvidences(previousEvidenceCommit);
Set<VulnerabilityEvidence> changedEvidence = new HashSet<>();
Set<Changes> changesToProcess = new HashSet<>();
Set<VulnerabilityEvidence> stillEvidence = new HashSet<>();
// filter non-Java files
changes = filterNonJavaChanges(changes);
if (previousEvidences == null) {
return newEvidences;
}
for (VulnerabilityEvidence previousEvidence : previousEvidences) {
for (Changes change : changes ) {
// The file has been just renamed
if (change.wasRenamed()) {
if (change.getRenamedTo().equals(previousEvidence.getPath())) {
previousEvidence.setPath(change.getPath());
}
}
// The file has been changed
else if (previousEvidence.getPath().equals(change.getPath())) {
changedEvidence.add(previousEvidence);
changesToProcess.add(change);
}
}
}
stillEvidence.addAll(previousEvidences);
stillEvidence.removeAll(changedEvidence);
// "Refresh" the molerat.evidence when a file was not changed
for (VulnerabilityEvidence e : stillEvidence) {
VulnerabilityEvidence newEvidence = new VulnerabilityEvidence(
e.getPath(),
currentEvidenceCommit,
e.getContainer(),
e.getLineNumber(),
e.getLineContents()
);
newEvidences.add(newEvidence);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// "Triage" the molerat.evidence when a file was changed
for (Changes change : changesToProcess) {
Set<VulnerabilityEvidence> retain = new HashSet<>();
for (VulnerabilityEvidence e : changedEvidence) {
if (e.getPath().equals(change.getPath())) {
retain.add(e);
}
}
Map<Integer, String> linesToKeep = this.updateChangedLines(
change.getPath(),
change.getLeftRevision(),
change.getRightRevision(),
retain,
change
);
if (linesToKeep != null) {
newEvidences.addAll(this.recordVulnerabilityEvidence(linesToKeep, change));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return newEvidences;
}
}

View File

@ -0,0 +1,72 @@
package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.utils.SignatureExtractor;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class EnhancedDeletionVulnerabilityEvidenceTracker extends DeletionVulnerabilityEvidenceTracker{
public EnhancedDeletionVulnerabilityEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
@Override
protected Set<VulnerabilityEvidence> getInitialVulnerabilityEvidence(Changes changes) throws Exception {
if (changes.getDeletions().size() != 0) {
return super.getInitialVulnerabilityEvidence(changes);
}
else {
SignatureExtractor se = new SignatureExtractor(repoWrapper.doCat(changes.getPath(), changes.getRightRevision()));
Map<String, Set<Integer>> rightSignatures = se.getSignaturesWithLines();
Set<String> relevantSignatures = new HashSet<>();
for (int line : changes.getAdditions().keySet()) {
for (Map.Entry<String, Set<Integer>> entry : rightSignatures.entrySet()) {
if (entry.getValue().contains(line)) {
relevantSignatures.add(entry.getKey());
}
}
}
String leftFile = repoWrapper.doCat(changes.getPath(), changes.getLeftRevision());
Map<Integer, String> lineMappings = repoWrapper.getLineMappings(leftFile);
se = new SignatureExtractor(leftFile);
Map<String, Set<Integer>> leftSignatures = se.getSignaturesWithLines();
for (int line : changes.getDeletions().keySet()) {
for (Map.Entry<String, Set<Integer>> entry : leftSignatures.entrySet()) {
if (entry.getValue().contains(line)) {
relevantSignatures.add(entry.getKey());
}
}
}
Set<VulnerabilityEvidence> initialEvidence = new HashSet<>();
for (String signature : relevantSignatures) {
for (Map.Entry<String, Set<Integer>> entry : leftSignatures.entrySet()) {
if (signature.equals(entry.getKey())) {
for (int line : entry.getValue()) {
VulnerabilityEvidence evd = new VulnerabilityEvidence(
changes.getPath(),
changes.getLeftRevision(),
signature,
line,
lineMappings.get(line)
);
initialEvidence.add(evd);
}
}
}
}
return initialEvidence;
}
}
}

View File

@ -0,0 +1,71 @@
package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class FixStatisticsVulnerabilityEvidenceTracker extends VulnerabilityEvidenceTracker {
private int addedLines = 0;
private int deletedLines = 0;
private int touchedFiles = 0;
private int touchedMethods = 0;
public FixStatisticsVulnerabilityEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
@Override
protected Set<VulnerabilityEvidence> getInitialVulnerabilityEvidence(Changes changes) throws Exception {
return null;
}
@Override
protected Set<VulnerabilityEvidence> getVulnerabilityEvidence(String currentEvidenceCommit, String previousEvidenceCommit, Set<Changes> changes) throws Exception {
return null;
}
@Override
public void trackEvidence() throws Exception {
this.changes = filterNonJavaChanges(this.changes);
Iterator<Changes> it = changes.iterator();
while (it.hasNext()) {
Changes currentChanges = it.next();
touchedFiles++;
addedLines += currentChanges.getAdditions().size();
deletedLines += currentChanges.getDeletions().size();
Set<String> methods = new HashSet<>();
Set<VulnerabilityEvidence> evidences = recordVulnerabilityEvidenceForRightFile(currentChanges.getAdditions(), currentChanges);
evidences.addAll(recordVulnerabilityEvidence(currentChanges.getDeletions(), currentChanges));
for (VulnerabilityEvidence evd : evidences) {
if (!evd.getLineContents().contains("private") &&
!evd.getLineContents().contains("protected") &&
!evd.getLineContents().contains("public")) {
methods.add(evd.getContainer());
}
}
touchedMethods += methods.size();
commits.add(currentChanges.getLeftRevision());
}
}
public int getNumberOfAddedLines() {
return addedLines;
}
public int getNumberOfDeletedLines() {
return deletedLines;
}
public int getNumberOfTouchedMethods() {
return touchedMethods;
}
public int getNumberOfTouchedFiles() {
return touchedFiles;
}
}

View File

@ -0,0 +1,148 @@
package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.utils.SignatureExtractor;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class PatchedMethodBodyTracker extends VulnerabilityEvidenceTracker {
public PatchedMethodBodyTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
@Override
protected Set<VulnerabilityEvidence> getInitialVulnerabilityEvidence(Changes changes) throws Exception {
SignatureExtractor se = new SignatureExtractor(repoWrapper.doCat(changes.getPath(), changes.getRightRevision()));
Map<String, Set<Integer>> rightSignatures = se.getSignaturesWithLines();
Set<String> relevantSignatures = new HashSet<>();
for (int line : changes.getAdditions().keySet()) {
for (Map.Entry<String, Set<Integer>> entry : rightSignatures.entrySet()) {
if (entry.getValue().contains(line)) {
relevantSignatures.add(entry.getKey());
}
}
}
String leftFile = repoWrapper.doCat(changes.getPath(), changes.getLeftRevision());
Map<Integer, String> lineMappings = repoWrapper.getLineMappings(leftFile);
se = new SignatureExtractor(leftFile);
Map<String, Set<Integer>> leftSignatures = se.getSignaturesWithLines();
for (int line : changes.getDeletions().keySet()) {
for (Map.Entry<String, Set<Integer>> entry : leftSignatures.entrySet()) {
if (entry.getValue().contains(line)) {
relevantSignatures.add(entry.getKey());
}
}
}
Set<VulnerabilityEvidence> initialEvidence = new HashSet<>();
for (String signature : relevantSignatures) {
for (Map.Entry<String, Set<Integer>> entry : leftSignatures.entrySet()) {
if (signature.equals(entry.getKey())) {
for (int line : entry.getValue()) {
VulnerabilityEvidence evd = new VulnerabilityEvidence(
changes.getPath(),
changes.getLeftRevision(),
signature,
line,
lineMappings.get(line)
);
initialEvidence.add(evd);
}
}
}
}
return initialEvidence;
}
@Override
protected Set<VulnerabilityEvidence> getVulnerabilityEvidence(String currentEvidenceCommit, String previousEvidenceCommit, Set<Changes> changes) throws Exception {
Set<VulnerabilityEvidence> newEvidences = new HashSet<>();
Set<VulnerabilityEvidence> previousEvidences = getEvidences(previousEvidenceCommit);
Set<VulnerabilityEvidence> changedEvidence = new HashSet<>();
Set<Changes> changesToProcess = new HashSet<>();
Set<VulnerabilityEvidence> stillEvidence = new HashSet<>();
// filter non-Java files
changes = filterNonJavaChanges(changes);
if (previousEvidences == null) {
return newEvidences;
}
for (VulnerabilityEvidence previousEvidence : previousEvidences) {
for (Changes change : changes ) {
// The file has been just renamed
if (change.wasRenamed()) {
if (change.getRenamedTo().equals(previousEvidence.getPath())) {
previousEvidence.setPath(change.getPath());
}
}
// The file has been changed
else if (previousEvidence.getPath().equals(change.getPath())) {
changedEvidence.add(previousEvidence);
changesToProcess.add(change);
}
}
}
stillEvidence.addAll(previousEvidences);
stillEvidence.removeAll(changedEvidence);
// "Refresh" the molerat.evidence when a file was not changed
for (VulnerabilityEvidence e : stillEvidence) {
VulnerabilityEvidence newEvidence = new VulnerabilityEvidence(
e.getPath(),
currentEvidenceCommit,
e.getContainer(),
e.getLineNumber(),
e.getLineContents()
);
newEvidences.add(newEvidence);
}
// "Triage" the molerat.evidence when a file was changed
for (Changes change : changesToProcess) {
Set<String> relevantSignatures = new HashSet<>();
for (VulnerabilityEvidence e : changedEvidence) {
relevantSignatures.add(e.getContainer());
}
String leftFile = repoWrapper.doCat(change.getPath(), change.getLeftRevision());
Map<Integer, String> lineMappings = repoWrapper.getLineMappings(leftFile);
SignatureExtractor se = new SignatureExtractor(leftFile);
Map<String, Set<Integer>> leftSignatures = se.getSignaturesWithLines();
for (String signature : relevantSignatures) {
for (Map.Entry<String, Set<Integer>> entry : leftSignatures.entrySet()) {
if (signature.equals(entry.getKey())) {
for (int line : entry.getValue()) {
VulnerabilityEvidence evd = new VulnerabilityEvidence(
change.getPath(),
change.getLeftRevision(),
signature,
line,
lineMappings.get(line)
);
newEvidences.add(evd);
}
}
}
}
}
return newEvidences;
}
}

View File

@ -0,0 +1,85 @@
package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class SliceDecayVulnerabilityEvidenceTracker extends SliceVulnerabilityEvidenceTracker {
public SliceDecayVulnerabilityEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
@Override
protected Set<VulnerabilityEvidence> getVulnerabilityEvidence(String currentEvidenceCommit, String previousEvidenceCommit, Set<Changes> changes) throws Exception {
Set<VulnerabilityEvidence> newEvidences = new HashSet<>();
Set<VulnerabilityEvidence> previousEvidences = getEvidences(previousEvidenceCommit);
Set<VulnerabilityEvidence> changedEvidence = new HashSet<>();
Set<Changes> changesToProcess = new HashSet<>();
Set<VulnerabilityEvidence> stillEvidence = new HashSet<>();
// filter non-Java files
changes = filterNonJavaChanges(changes);
if (previousEvidences == null) {
return newEvidences;
}
for (VulnerabilityEvidence previousEvidence : previousEvidences) {
for (Changes change : changes ) {
// The file has been just renamed
if (change.wasRenamed()) {
if (change.getRenamedTo().equals(previousEvidence.getPath())) {
previousEvidence.setPath(change.getPath());
}
}
// The file has been changed
else if (previousEvidence.getPath().equals(change.getPath())) {
changedEvidence.add(previousEvidence);
changesToProcess.add(change);
}
}
}
stillEvidence.addAll(previousEvidences);
stillEvidence.removeAll(changedEvidence);
// "Refresh" the molerat.evidence when a file was not changed
for (VulnerabilityEvidence e : stillEvidence) {
VulnerabilityEvidence newEvidence = new VulnerabilityEvidence(
e.getPath(),
currentEvidenceCommit,
e.getContainer(),
e.getLineNumber(),
e.getLineContents()
);
newEvidences.add(newEvidence);
}
// "Triage" the molerat.evidence when a file was changed
for (Changes change : changesToProcess) {
Set<VulnerabilityEvidence> retain = new HashSet<>();
for (VulnerabilityEvidence e : changedEvidence) {
if (e.getPath().equals(change.getPath())) {
retain.add(e);
}
}
Map<Integer, String> linesToKeep = this.updateChangedLines(
change.getPath(),
change.getLeftRevision(),
change.getRightRevision(),
retain,
change
);
if (linesToKeep != null) {
newEvidences.addAll(this.recordVulnerabilityEvidence(linesToKeep, change));
}
}
return newEvidences;
}
}

View File

@ -0,0 +1,139 @@
package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.slicers.LightweightSlice;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class SliceVulnerabilityEvidenceTracker extends VulnerabilityEvidenceTracker {
public SliceVulnerabilityEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
@Override
protected Set<VulnerabilityEvidence> getInitialVulnerabilityEvidence(Changes changes) throws Exception {
// 1. Take the added lines as the slicing criteria and obtain the slice on the fixed revision
Map<Integer, String> slicingCriteria = changes.getAdditions();
String rightFile = this.repoWrapper.doCat(changes.getPath(), changes.getRightRevision());
Map<Integer, String> sliced = this.doSlice(slicingCriteria, rightFile);
Set<VulnerabilityEvidence> slicedEvd = this.recordVulnerabilityEvidenceForRightFile(sliced, changes);
// 2. we need to check which lines from the "fixed" slice are present in the vulnerable revision
// 2.1 we "correlate" the lines from the "fixed" slice to the vulnerable revision
Map<Integer, String> propagated = this.updateChangedLines(changes.getPath(), changes.getLeftRevision(),
changes.getRightRevision(), slicedEvd, changes);
// 2.2 take deleted lines + "correlated" changes from the fixed slice and take a new slice on the vulnerable revision
propagated.putAll(changes.getDeletions());
// 3.1 make the final slice on the vulnerable revision
slicingCriteria = propagated;
String leftFile = this.repoWrapper.doCat(changes.getPath(), changes.getLeftRevision());
sliced = this.doSlice(slicingCriteria, leftFile);
propagated.putAll(sliced);
Set<VulnerabilityEvidence> initialEvidence = this.recordVulnerabilityEvidence(propagated, changes);
return initialEvidence;
}
@Override
protected Set<VulnerabilityEvidence> getVulnerabilityEvidence(String currentEvidenceCommit, String previousEvidenceCommit, Set<Changes> changes) throws Exception {
Set<VulnerabilityEvidence> newEvidences = new HashSet<>();
Set<VulnerabilityEvidence> previousEvidences = getEvidences(previousEvidenceCommit);
Set<VulnerabilityEvidence> changedEvidence = new HashSet<>();
Set<Changes> changesToProcess = new HashSet<>();
Set<VulnerabilityEvidence> stillEvidence = new HashSet<>();
// filter non-Java files
changes = filterNonJavaChanges(changes);
if (previousEvidences == null) {
return newEvidences;
}
for (VulnerabilityEvidence previousEvidence : previousEvidences) {
for (Changes change : changes ) {
// The file has been just renamed
if (change.wasRenamed()) {
if (change.getRenamedTo().equals(previousEvidence.getPath())) {
previousEvidence.setPath(change.getPath());
}
}
// The file has been changed
else if (previousEvidence.getPath().equals(change.getPath())) {
changedEvidence.add(previousEvidence);
changesToProcess.add(change);
}
}
}
stillEvidence.addAll(previousEvidences);
stillEvidence.removeAll(changedEvidence);
// "Refresh" the molerat.evidence when a file was not changed
for (VulnerabilityEvidence e : stillEvidence) {
VulnerabilityEvidence newEvidence = new VulnerabilityEvidence(
e.getPath(),
currentEvidenceCommit,
e.getContainer(),
e.getLineNumber(),
e.getLineContents()
);
newEvidences.add(newEvidence);
}
// "Triage" the molerat.evidence when a file was changed
for (Changes change : changesToProcess) {
// --------------------------------------
Map<Integer, String> slicingCriteria = new TreeMap<>();
for (VulnerabilityEvidence e : changedEvidence) {
if (e.getPath().equals(change.getPath())) {
slicingCriteria.put(e.getLineNumber(), e.getLineContents());
}
}
String rightFile = this.repoWrapper.doCat(change.getPath(), change.getRightRevision());
Map<Integer, String> slice = this.doSlice(slicingCriteria, rightFile);
Set<VulnerabilityEvidence> slicedEvd = this.recordVulnerabilityEvidenceForRightFile(slice, change);
Map<Integer, String> linesToKeep = this.updateChangedLines(
change.getPath(),
change.getLeftRevision(),
change.getRightRevision(),
slicedEvd,
change
);
if (linesToKeep != null) {
String leftFile = this.repoWrapper.doCat(change.getPath(), change.getLeftRevision());
slice = this.doSlice(linesToKeep, leftFile);
newEvidences.addAll(this.recordVulnerabilityEvidence(slice, change));
}
}
return newEvidences;
}
protected Map<Integer, String> doSlice(Map<Integer, String> slicingCriteria, String fileContents) {
Map<Integer, String> sliced = this.repoWrapper.getLineMappings(fileContents);
LanguageFactory.init("Java", fileContents);
LightweightSlice slice;
try {
slice = new LightweightSlice(LanguageFactory.getRoot(), slicingCriteria.keySet());
sliced.keySet().retainAll(slice.getSelectedLines());
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
return sliced;
}
}

View File

@ -0,0 +1,234 @@
package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.repos.trackers.AbstractEvidenceTracker;
import it.unitn.molerat.repos.utils.SignatureExtractor;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import java.util.*;
public abstract class VulnerabilityEvidenceTracker extends AbstractEvidenceTracker {
protected Map<String, Set<VulnerabilityEvidence>> evidences = new LinkedHashMap<String, Set<VulnerabilityEvidence>>();
public VulnerabilityEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
@Override
public void trackEvidence() throws Exception {
// I. Filter all non-Java files that have been changed
this.changes = filterNonJavaChanges(this.changes);
// -------------------------------------------------
// II. Get the initial molerat.evidence from the fix
Iterator<Changes> it = changes.iterator();
while (it.hasNext()) {
Changes currentChanges = it.next();
Set<VulnerabilityEvidence> tempVulnEvidences = getInitialVulnerabilityEvidence(currentChanges);
for (VulnerabilityEvidence evidence : tempVulnEvidences) {
addEvidence(evidence);
}
commits.add(currentChanges.getLeftRevision());
}
// -------------------------------------------------
// III. Collect evidences across the rest of commits
String rightCommit = this.vulnRevision;
Iterator<String> commitIterator = restOfCommits.iterator();
String commit = "";
while (commitIterator.hasNext()) {
commit = commitIterator.next();
// Get the current changes
String leftCommit = commit;
String diffTxt = repoWrapper.doDiff(leftCommit, rightCommit);
Set<Changes> currentChanges = repoWrapper.inferChangesFromDiff(diffTxt, leftCommit, rightCommit);
Set<VulnerabilityEvidence> newEvidences = new HashSet<>();
newEvidences = getVulnerabilityEvidence(leftCommit, rightCommit, currentChanges);
// did the method/file/molerat.evidence disappear?
if (newEvidences.size() == 0) {
break;
} else {
for (VulnerabilityEvidence evidence : newEvidences) {
addEvidence(evidence);
}
rightCommit = leftCommit;
commits.add(commit);
}
}
if (commit.equals("")) {
return;
}
}
public Set<VulnerabilityEvidence> getEvidences(String commit) {
Set<VulnerabilityEvidence> evd = this.evidences.get(commit);
return (evd != null) ? evd : new HashSet<>();
}
public Map<String, Integer> countEvidenceInFiles(String commit) {
Map<String, Integer> counts = new TreeMap<>();
Set<VulnerabilityEvidence> evd = getEvidences(commit);
for (VulnerabilityEvidence e : evd) {
String filename = e.getPath();
if (!counts.containsKey(filename)) {
if (e.getLineNumber() != 0) {
counts.put(filename, 1);
}
else {
counts.put(filename, 0);
}
}
else {
if (e.getLineNumber() == 0) {
counts.replace(filename, 0);
}
else {
int locCount = counts.get(filename);
locCount++;
counts.replace(filename, locCount);
}
}
}
return counts;
}
public Map<String, Set<VulnerabilityEvidence>> getEvidences() {
return this.evidences;
}
protected void addEvidence(VulnerabilityEvidence evidence) {
if (this.evidences.containsKey(evidence.getCommit())) {
evidences.get(evidence.getCommit()).add(evidence);
}
else {
Set<VulnerabilityEvidence> set = new HashSet<>();
set.add(evidence);
this.evidences.put(evidence.getCommit(), set);
}
}
protected abstract Set<VulnerabilityEvidence> getInitialVulnerabilityEvidence(Changes changes) throws Exception;
protected abstract Set<VulnerabilityEvidence> getVulnerabilityEvidence(String currentEvidenceCommit, String previousEvidenceCommit, Set<Changes> changes) throws Exception;
protected Set<VulnerabilityEvidence> recordVulnerabilityEvidence(Map<Integer, String> lines, Changes changes) throws Exception {
Set<VulnerabilityEvidence> evidences = new HashSet<>();
String fileContents = this.repoWrapper.doCat(changes.getPath(), changes.getLeftRevision());
SignatureExtractor se = new SignatureExtractor(fileContents);
Map<String, Set<Integer>> containers = se.getSignaturesWithLines();
for (Map.Entry<String, Set<Integer>> containerEntry : containers.entrySet()) {
for (Map.Entry<Integer, String> lineEntry : lines.entrySet()) {
if (containerEntry.getValue().contains(lineEntry.getKey())) {
VulnerabilityEvidence evidence = new VulnerabilityEvidence(
changes.getPath(),
changes.getLeftRevision(),
containerEntry.getKey(),
lineEntry.getKey(),
lineEntry.getValue()
);
evidences.add(evidence);
}
}
}
return evidences;
}
protected Set<VulnerabilityEvidence> recordVulnerabilityEvidenceForRightFile(Map<Integer, String> lines, Changes changes) throws Exception {
Set<VulnerabilityEvidence> evidences = new HashSet<>();
String fileContents = this.repoWrapper.doCat(changes.getPath(), changes.getRightRevision());
SignatureExtractor se = new SignatureExtractor(fileContents);
Map<String, Set<Integer>> containers = se.getSignaturesWithLines();
for (Map.Entry<String, Set<Integer>> containerEntry : containers.entrySet()) {
for (Map.Entry<Integer, String> lineEntry : lines.entrySet()) {
if (containerEntry.getValue().contains(lineEntry.getKey())) {
VulnerabilityEvidence evidence = new VulnerabilityEvidence(
changes.getPath(),
changes.getRightRevision(),
containerEntry.getKey(),
lineEntry.getKey(),
lineEntry.getValue()
);
evidences.add(evidence);
}
}
}
return evidences;
}
protected Map<Integer, String> updateChangedLines(String path, String leftRev, String rightRev, Set<VulnerabilityEvidence> retain, Changes change) throws Exception {
Map<Integer, String> linesToKeep = new TreeMap<>();
String leftFile = this.repoWrapper.doCat(path, leftRev);
String rightFile = this.repoWrapper.doCat(path, rightRev);
SignatureExtractor rightSignatures = new SignatureExtractor(rightFile);
Map<String, Set<Integer>> rightLineSignatures = rightSignatures.getSignaturesWithLines();
Map<Integer, String> rightLineMappings = this.repoWrapper.getLineMappings(rightFile);
SignatureExtractor leftSignatures = new SignatureExtractor(leftFile);
Map<String, Set<Integer>> leftLineSignatures = leftSignatures.getSignaturesWithLines();
Map<Integer, String> leftLineMappings = this.repoWrapper.getLineMappings(leftFile);
for (VulnerabilityEvidence evd : retain) {
String container = evd.getContainer();
Set<Integer> lineNumbers = leftLineSignatures.get(container);
Map<Integer, String> leftChunk = new TreeMap<>();
// the left container might not exist anymore...
if (lineNumbers == null) {
continue;
}
// otherwise, process
for (int lineNumber : lineNumbers) {
leftChunk.put(lineNumber, leftLineMappings.get(lineNumber));
}
lineNumbers = rightLineSignatures.get(container);
Map<Integer, String> rightChunk = new TreeMap<>();
for (int lineNumber : lineNumbers) {
rightChunk.put(lineNumber, rightLineMappings.get(lineNumber));
}
String leftLine = leftChunk.get(evd.getLineNumber());
String rightLine = rightChunk.get(evd.getLineNumber());
if (leftLine != null && rightLine != null && leftLine.equals(rightLine)) {
linesToKeep.put(evd.getLineNumber(), evd.getLineContents());
continue;
} else {
if (rightLine != null && rightLine.equals(evd.getLineContents())) {
Map<Integer, String> eligibleCandidates = new TreeMap<>();
for (Map.Entry<Integer, String> candidateLine : leftChunk.entrySet()) {
if (candidateLine.getValue().equals(evd.getLineContents())) {
eligibleCandidates.put(candidateLine.getKey(), evd.getLineContents());
continue;
}
}
if (eligibleCandidates.size() > 1) {
Iterator<Map.Entry<Integer, String>> it = eligibleCandidates.entrySet().iterator();
int leftLineNumber = it.next().getKey();
int rightLineNumber = evd.getLineNumber();
int minimumDistance = rightLineNumber - leftLineNumber;
while (it.hasNext()) {
leftLineNumber = it.next().getKey();
int tempMinimumDistance = rightLineNumber - leftLineNumber;
minimumDistance = (Math.abs(tempMinimumDistance) < Math.abs(minimumDistance)) ? tempMinimumDistance : minimumDistance;
}
int newLineNumber = rightLineNumber - minimumDistance;
String newLineContents = eligibleCandidates.get(newLineNumber);
linesToKeep.put(newLineNumber, newLineContents);
}
else {
linesToKeep.putAll(eligibleCandidates);
}
}
}
}
return linesToKeep;
}
}

View File

@ -0,0 +1,73 @@
package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.repos.wrappers.GitRepoWrapper;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import it.unitn.molerat.repos.wrappers.SvnRepoWrapper;
public class VulnerabilityEvidenceTrackerFactory {
public static VulnerabilityEvidenceTracker getTracker(String repoRoot, String fixedRev, String wrapperType, String trackerType) throws Exception {
RepoWrapper wrapper = null;
switch (wrapperType.toLowerCase()) {
case "svn":
wrapper = new SvnRepoWrapper(repoRoot);
break;
case "git":
wrapper = new GitRepoWrapper(repoRoot);
break;
default:
throw new Exception("There is currently no support for '" + wrapperType + "'");
}
VulnerabilityEvidenceTracker vulnerabilityEvidenceTracker = null;
switch (trackerType.toLowerCase()) {
case "deletionvulnerabilityevidencetracker":
vulnerabilityEvidenceTracker = new DeletionVulnerabilityEvidenceTracker(wrapper, fixedRev);
break;
case "slicevulnerabilityevidencetracker":
vulnerabilityEvidenceTracker = new SliceVulnerabilityEvidenceTracker(wrapper, fixedRev);
break;
case "slicedecayvulnerabilityevidencetracker":
vulnerabilityEvidenceTracker = new SliceDecayVulnerabilityEvidenceTracker(wrapper, fixedRev);
break;
case "patchedmethodbodytracker":
vulnerabilityEvidenceTracker = new PatchedMethodBodyTracker(wrapper, fixedRev);
break;
case "enhanceddeletionvulnerabilityevidencetracker":
vulnerabilityEvidenceTracker = new EnhancedDeletionVulnerabilityEvidenceTracker(wrapper, fixedRev);
break;
case "fixstatisticsvulnerabilityevidencetracker":
vulnerabilityEvidenceTracker = new FixStatisticsVulnerabilityEvidenceTracker(wrapper, fixedRev);
break;
default:
throw new Exception("There is no such molerat.evidence tracker as '" + trackerType + "'");
}
return vulnerabilityEvidenceTracker;
}
public static String getTrackersList() {
StringBuilder builder = new StringBuilder();
builder.append("--------------------\n");
builder.append("The list of available vulnerability molerat.evidence trackers:\n");
builder.append("--------------------\n");
builder.append("\n");
builder.append("\t\"SliceDecayVulnerabilityEvidenceTracker\" - track intra-procedural slice over the fixed lines.\n");
builder.append("\n");
builder.append("\t\"DeletionVulnerabilityEvidenceTracker\" - track only the lines deleted during a fix.\n");
builder.append("\n");
builder.append("\t\"PatchedMethodBodyTracker\" - track the entire fixed methods.\n");
builder.append("\n");
builder.append("\t\"EnhancedDeletionVulnerabilityEvidenceTracker\" - track only the lines deleted during a fix, " +
"or the entire fixed methods if there are no deleted lines.\n");
builder.append("\n");
builder.append("--------------------\n");
return builder.toString();
}
}

View File

@ -0,0 +1,98 @@
package it.unitn.molerat.repos.utils;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CommitMetrics {
private static final Pattern deletedPublicMethodPattern = Pattern.compile("public .*\\([^\\)]*\\)[^;]*$");
public static int getGlobalPublicMethodsRemoved(String leftRev, String rightRev, RepoWrapper wrapper) throws Exception {
int removed = 0;
String diff = wrapper.doDiff(leftRev, rightRev);
Set<Changes> changes = wrapper.inferChangesFromDiff(diff, leftRev, rightRev);
for (Changes change : changes) {
if (!change.getPath().endsWith(".java")) {
continue;
}
Map<Integer, String> deletions = change.getDeletions();
wrapper.filterCommentsAndBlanks(deletions);
for (String del : deletions.values()) {
del = StringUtils.trim(del);
Matcher matcher = deletedPublicMethodPattern.matcher(del);
if (matcher.matches()) {
removed++;
}
matcher.reset();
}
}
return removed;
}
public static int getNumberOfPublicMethodsPerRevision(String rev, RepoWrapper wrapper) throws Exception {
int pubAPICount = 0;
Set<String> files = wrapper.getRevisionFiles(rev, ".java");
for (String f : files) {
String fc = wrapper.doCat(f, rev);
pubAPICount += countPublicMethodDeclarationsInFile(fc);
}
return pubAPICount;
}
public static Map<String, String> getFileContentsPerRevision(String rev, RepoWrapper wrapper) throws Exception {
Map<String,String> result = new TreeMap<>();
Set<String> files = wrapper.getRevisionFiles(rev, ".java");
for (String file : files) {
String contents = wrapper.doCat(file, rev);
result.put(file, contents);
}
return result;
}
@Deprecated
public static int countPublicMethodDeclarationsInFile(String fileContents) {
int pubAPICount = 0;
String[] lines = StringUtils.split(fileContents, System.getProperty("line.separator"));
for (int i=0; i<lines.length; i++) {
String line = StringUtils.replace(lines[i], "\t", " ");
line = StringUtils.trim(line);
if (StringUtils.startsWith(line, "public ")) {
int indexOfPublic = StringUtils.indexOf(line, "public");
int firstOpenBracket = StringUtils.indexOf(line, '(');
int lastOpenBracket = StringUtils.indexOf(line, '(');
int firstCloseBracket = StringUtils.indexOf(line, ')');
int lastCloseBracket = StringUtils.indexOf(line, ')');
if ((indexOfPublic < firstOpenBracket) && (firstOpenBracket == lastOpenBracket) &&
(firstCloseBracket == lastCloseBracket) && (firstOpenBracket < firstCloseBracket)) {
int semicolonIndex = StringUtils.indexOf(line, ';');
if (semicolonIndex == -1) {
StringBuilder chunk = new StringBuilder();
String nextLine = "";
for (int j=i; j<lines.length; j++) {
nextLine = StringUtils.replace(lines[j], "\t", " ");
nextLine = StringUtils.trim(nextLine);
if (StringUtils.indexOf(nextLine, ';') != -1) {
break;
}
else {
chunk.append(nextLine);
}
}
if (StringUtils.contains(chunk.toString(), '{')) {
pubAPICount++;
}
}
}
}
}
return pubAPICount;
}
}

View File

@ -0,0 +1,150 @@
package it.unitn.molerat.repos.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import it.unitn.molerat.data.csv.InputDataPoint;
import org.apache.commons.io.FileUtils;
public final class IORoutines {
private static File throwExceptionIfDoesNotExist(String path) throws FileNotFoundException {
File javaFile = new File(path);
if (!javaFile.exists()) {
throw new FileNotFoundException(path);
}
return javaFile;
}
public static String readFile(String path) throws IOException {
File javaFile = throwExceptionIfDoesNotExist(path);
BufferedReader in = new BufferedReader(new FileReader(javaFile));
StringBuffer buffer = new StringBuffer();
String line = null;
try {
while ( (line = in.readLine()) != null) {
buffer.append(line);
buffer.append('\n');
}
}
finally {
in.close();
}
return buffer.toString();
}
public static void writeFile(String path, String contents) throws IOException {
File file = null;
FileOutputStream outStream = null;
try {
file = new File(path);
outStream = new FileOutputStream(file, true);
if (!file.exists()) {
file.createNewFile();
}
byte[] bytes = contents.getBytes();
outStream.write(bytes);
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage());
throw new IOException(e.getMessage());
} finally {
try {
if (outStream != null) {
outStream.flush();
outStream.close();
}
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage());
throw new IOException(e.getMessage());
}
}
}
public static Set<String> readFileBrokenByLines(String path) throws IOException {
File javaFile = throwExceptionIfDoesNotExist(path);
Set<String> lines = new LinkedHashSet<String>();
BufferedReader in = new BufferedReader(new FileReader(javaFile));
String line = null;
try {
while ( (line = in.readLine()) != null) {
lines.add(line);
}
}
finally {
in.close();
}
return lines;
}
public static void readFilesRecursively(File source, Set<String> results) {
if (!source.exists()) {
return;
}
else if (source.isDirectory()) {
String[] files = source.list();
for (String file : files) {
readFilesRecursively(new File(source,file), results);
}
}
else {
try {
String result = readFile(source.getAbsolutePath());
results.add(result);
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage());
}
}
}
public static Set<InputDataPoint> readInputDataPoints(String path) throws Exception {
Set<InputDataPoint> dataPointSet = new HashSet<>();
File file2Parse = new File(path);
BufferedReader reader = null;
try {
String line = "";
reader = new BufferedReader(new FileReader(file2Parse));
while ((line = reader.readLine()) != null) {
InputDataPoint inputDataPoint = new InputDataPoint(line);
dataPointSet.add(inputDataPoint);
}
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
finally {
try {
reader.close();
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
}
return dataPointSet;
}
public static File joinpaths(String path1, String path2) {
return new File(path1, path2);
}
public static void mkdir(File dir) {
if (!dir.exists()) {
dir.mkdirs();
}
}
public void copyFolders(File source, File destination) {
if (source.isDirectory() && destination.isDirectory()) {
try {
FileUtils.copyDirectory(source, destination);
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage());
}
}
}
}

View File

@ -0,0 +1,233 @@
package it.unitn.molerat.repos.utils;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.lang.parsers.java.JavaBaseListener;
import it.unitn.repoman.core.lang.parsers.java.JavaParser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Queue;
import java.util.HashSet;
public class SignatureExtractor extends JavaBaseListener {
private String className = "";
private String packageName = "";
private String currentSignature = "";
private final Map<String, Set<Integer>> lines = new TreeMap<>();
private final Queue<ParserRuleContext> modifiers = new LinkedList<>();
public SignatureExtractor(String fileContents) {
LanguageFactory.init("java", fileContents);
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(this, LanguageFactory.getRoot());
}
@Override
public void enterPackageDeclaration(JavaParser.PackageDeclarationContext ctx) {
packageName = ctx.getChild(1).getText();
currentSignature = packageName;
processLine(ctx);
}
@Override
public void exitPackageDeclaration(JavaParser.PackageDeclarationContext ctx) {
currentSignature = "";
}
@Override
public void enterClassOrInterfaceModifier(JavaParser.ClassOrInterfaceModifierContext ctx) {
modifiers.add(ctx);
}
@Override
public void enterMethodDeclaration(JavaParser.MethodDeclarationContext ctx) {
StringBuilder methodDeclBuilder = new StringBuilder();
getMethodSignature(ctx,methodDeclBuilder);
String currentModifiers = retrieveModifiers();
StringBuilder signatureBuilder = new StringBuilder();
signatureBuilder.append(currentModifiers);
signatureBuilder.append(": ");
signatureBuilder.append(joinPackageNameWithClassName());
signatureBuilder.append(".");
signatureBuilder.append(methodDeclBuilder.toString());
currentSignature = signatureBuilder.toString();
}
private String joinPackageNameWithClassName() {
StringBuilder builder = new StringBuilder();
if (!packageName.equals("")) {
builder.append(packageName);
builder.append(".");
}
builder.append(className);
return builder.toString();
}
@Override
public void exitMethodDeclaration(JavaParser.MethodDeclarationContext ctx) {
currentSignature = "";
}
@Override
public void enterConstructorDeclaration(JavaParser.ConstructorDeclarationContext ctx) {
StringBuilder constrDeclBuilder = new StringBuilder();
getConstructorSignature(ctx,constrDeclBuilder);
String currentModifiers = retrieveModifiers();
StringBuilder signatureBuilder = new StringBuilder();
signatureBuilder.append(currentModifiers);
signatureBuilder.append(": ");
signatureBuilder.append(joinPackageNameWithClassName());
signatureBuilder.append(".");
signatureBuilder.append(constrDeclBuilder.toString());
currentSignature = signatureBuilder.toString();
processLine(ctx);
}
@Override
public void exitConstructorDeclaration(JavaParser.ConstructorDeclarationContext ctx) {
currentSignature = "";
}
@Override
public void enterClassDeclaration(JavaParser.ClassDeclarationContext ctx) {
if (!className.equals("")) {
return;
}
className = ctx.getChild(1).getText();
String currentModifiers = retrieveModifiers();
StringBuilder signatureBuilder = new StringBuilder();
signatureBuilder.append(currentModifiers);
signatureBuilder.append(": ");
signatureBuilder.append(joinPackageNameWithClassName());
currentSignature = signatureBuilder.toString();
processLine(ctx);
}
@Override
public void exitClassDeclaration(JavaParser.ClassDeclarationContext ctx) {
currentSignature = "";
}
@Override
public void enterStatement(JavaParser.StatementContext ctx) {
processLine(ctx);
}
@Override
public void enterFieldDeclaration(JavaParser.FieldDeclarationContext ctx) {
String currentModifiers = retrieveModifiers();
String fieldName = ctx.getChild(1).getChild(0).getChild(0).getText();
StringBuilder signatureBuilder = new StringBuilder();
signatureBuilder.append(currentModifiers);
signatureBuilder.append(": ");
signatureBuilder.append(joinPackageNameWithClassName());
signatureBuilder.append(".");
signatureBuilder.append(fieldName);
currentSignature = signatureBuilder.toString();
processLine(ctx);
}
@Override
public void exitFieldDeclaration(JavaParser.FieldDeclarationContext ctx) {
currentSignature = "";
}
@Override
public void enterLocalVariableDeclaration(JavaParser.LocalVariableDeclarationContext ctx) {
processLine(ctx);
}
@Override
public void enterCatchClause(JavaParser.CatchClauseContext ctx) {
processLine(ctx);
}
private void processLine(ParserRuleContext ctx) {
int line = ctx.getStart().getLine();
if (currentSignature != null) {
Set<Integer> tempLines = lines.get(currentSignature);
if (tempLines != null) {
lines.remove(currentSignature);
} else {
tempLines = new HashSet<>();
}
tempLines.add(line);
lines.put(currentSignature, tempLines);
}
}
/**
* Gets a method signature recursively
* @param method
* @param builder
*/
private void getMethodSignature(ParseTree method, StringBuilder builder) {
int start = (method.getClass().equals(JavaParser.MethodDeclarationContext.class)) ? 1 : 0;
for (int i=start; i<method.getChildCount(); i++) {
ParseTree node = method.getChild(i);
if (node.getClass().equals(TerminalNodeImpl.class)) {
builder.append(node.getText());
}
else if (!node.getClass().equals(JavaParser.MethodBodyContext.class) &&
!node.getClass().equals(JavaParser.VariableDeclaratorIdContext.class)) {
getMethodSignature(node, builder);
}
}
}
/**
* Gets a constructor signature recursively
* @param constructor
* @param builder
*/
private void getConstructorSignature(ParseTree constructor, StringBuilder builder) {
for (int i=0; i < constructor.getChildCount(); i++) {
ParseTree node = constructor.getChild(i);
if (node.getClass().equals(TerminalNodeImpl.class)) {
builder.append(node.getText());
}
else if (!node.getClass().equals(JavaParser.ConstructorBodyContext.class) &&
!node.getClass().equals(JavaParser.VariableDeclaratorIdContext.class)) {
getConstructorSignature(node, builder);
}
}
}
/**
* Gets the modifier keywords
* @return
*/
private String retrieveModifiers() {
StringBuilder currentModifier = new StringBuilder();
while (modifiers.size() != 0) {
ParserRuleContext modifier = modifiers.poll();
if (!modifier.getText().startsWith("@")) {
currentModifier.append(modifier.getText() + " ");
}
}
return currentModifier.toString();
}
public Map<String, Set<Integer>> getSignaturesWithLines() {
return this.lines;
}
}

View File

@ -0,0 +1,204 @@
package it.unitn.molerat.repos.wrappers;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathSuffixFilter;
import org.eclipse.jgit.lib.Ref;
public final class GitRepoWrapper extends RepoWrapper {
private final String repoRoot;
private final Repository repo;
private final Git git;
public GitRepoWrapper(String root) throws IOException {
this.diffFilePrefix = "diff --git a";
this.repoRoot = root;
FileRepositoryBuilder builder = new FileRepositoryBuilder();
builder.setGitDir(new File(this.repoRoot + "/.git"));
this.repo = builder.build();
this.git = new Git(this.repo);
}
public Map<String, String> getTagsAndCommits() throws Exception {
Map<String, String> tags = new HashMap<>();
List<Ref> call = git.tagList().call();
for (Ref tagref : call) {
tags.put(tagref.getName(), tagref.getPeeledObjectId().getName());
}
return tags;
}
@Override
public String doDiff(String path, String leftRev, String rightRev) throws Exception {
if (path.startsWith("/")) {
path = path.substring(1);
}
OutputStream out = new ByteArrayOutputStream();
try { DiffFormatter df = new DiffFormatter(out);
df.setRepository(this.git.getRepository());
df.setDetectRenames(true);
List<DiffEntry> entries = df.scan(getTreeIterator(leftRev), getTreeIterator(rightRev));
df.close();
df.format(entries);
}
catch(Exception e) {
System.out.println("[JGit error] " + e.getMessage());
throw new Exception(e);
}
return out.toString();
}
@Override
public String doDiff(String leftRev, String rightRev) throws Exception {
return this.doDiff("", leftRev, rightRev);
}
@Override
public String doCat(String path, String rev) throws Exception {
if (path.startsWith("/")) {
path = path.substring(1);
}
String output = "";
final ObjectId id = this.repo.resolve(rev);
ObjectReader reader = this.repo.newObjectReader();
RevWalk walk = null;
try {
walk = new RevWalk(reader);
RevCommit commit = walk.parseCommit(id);
RevTree tree = commit.getTree();
TreeWalk treewalk = TreeWalk.forPath(reader, path, tree);
if (treewalk != null) {
byte[] data = reader.open(treewalk.getObjectId(0)).getBytes();
output = new String(data, "utf-8");
}
} finally {
reader.close();
if (walk != null) {
walk.close();
}
}
return output;
}
@Override
public String getBasePath() {
return this.repoRoot;
}
private AbstractTreeIterator getTreeIterator(String name) throws IOException {
final ObjectId id = this.repo.resolve(name);
if (id == null) {
throw new IllegalArgumentException(name);
}
final CanonicalTreeParser p = new CanonicalTreeParser();
try (ObjectReader or = this.repo.newObjectReader();
RevWalk rw = new RevWalk(this.repo)) {
p.reset(or, rw.parseTree(id));
return p;
}
}
// TODO: UNIMPLEMENTED
@Override
public void annotate(String path, String rev, Object callback) throws Exception {
}
@Override
public Set<String> getRevisionNumbers(String topRev) throws Exception {
Set<String> commits = new LinkedHashSet<>();
for (RevCommit commit : git.log().add(this.repo.resolve(topRev + "~1")).call()) {
commits.add(commit.getName());
}
return commits;
}
// TODO: UNIMPLEMENTED
@Override
public Map<Integer, String> determineOriginatingRevision(String filePath, String revision, Map<Integer, String> lines) throws Exception {
return new HashMap<>();
}
// TODO: UNIMPLEMENTED
@Override
protected String getReleaseTag(String release) throws Exception {
/*
Map<String, String> tags = this.getTagsAndCommits();
for (String key : tags.keySet()) {
String candidate = key.replace("refs/tags/", "");
System.out.println("KEY: " + candidate);
}
*/
return ("refs/tags/" + release);
}
@Override
public String getReleaseCommit(String release) throws Exception {
String tagName = getReleaseTag(release);
String tagCommit = this.getTagsAndCommits().get(tagName);
Iterator<RevCommit> iter = git.log().add(this.repo.resolve(tagCommit)).call().iterator();
iter.next();
return iter.next().getName();
}
@Override
public Set<String> getRevisionFiles(String rev, String filter) throws Exception {
Set<String> files = new LinkedHashSet<>();
RevWalk revWalk = null;
TreeWalk treeWalk = null;
try {
ObjectId revId = this.repo.resolve(rev);
revWalk = new RevWalk(this.repo);
RevCommit commit = revWalk.parseCommit(revId);
RevTree tree = commit.getTree();
treeWalk = new TreeWalk(this.repo);
treeWalk.addTree(tree);
treeWalk.setRecursive(true);
treeWalk.setFilter(PathSuffixFilter.create(filter));
while(treeWalk.next()) {
files.add(treeWalk.getPathString());
}
} catch(Exception e) {
throw new Exception("[JGit error] " + e.getMessage());
} finally {
if (revWalk != null){
revWalk.close();
}
if (treeWalk != null){
treeWalk.close();
}
}
return files;
}
@Override
public Set<String> getAllRepositoryTransactions() throws Exception {
Iterable<RevCommit> logs = git.log().call();
Set<String> commits = new LinkedHashSet<>();
Iterator<RevCommit> it = logs.iterator();
if (it.hasNext()) {
String latestCommit = it.next().getName();
commits.add(latestCommit);
commits.addAll(this.getRevisionNumbers(latestCommit));
}
return commits;
}
}

View File

@ -0,0 +1,161 @@
package it.unitn.molerat.repos.wrappers;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import it.unitn.molerat.evidence.Changes;
public abstract class RepoWrapper {
protected String diffFilePrefix;
protected final Pattern hunkRegexPattern = Pattern.compile("@@[ ]*\\-([0-9]+)[\\,0-9 ]+\\+([0-9]+)[\\,0-9 ]+@@");
protected final Pattern commentsPattern = Pattern.compile("(\\*|\\/\\*|\\*\\/|\\/\\/)(.*)");
public abstract String doDiff(String leftRev, String rightRev) throws Exception;
public abstract String doDiff(String path, String leftRev, String rightRev) throws Exception;
public abstract void annotate(String path, String rev, Object callback) throws Exception;
public abstract String doCat(String path, String rev) throws Exception;
public abstract String getBasePath();
public abstract Set<String> getRevisionFiles(String rev, String filter) throws Exception;
public abstract Set<String> getRevisionNumbers(String topRev) throws Exception;
public abstract Map<Integer, String> determineOriginatingRevision(final String filePath, final String revision, final Map<Integer, String> lines) throws Exception;
public Set<Changes> inferChangesFromDiff(String diffText, String leftRev, String rightRev) throws IOException {
Set<Changes> relevantChanges = new LinkedHashSet<>();
Changes newRelevantChanges = null;
int deletionRange = -1;
int additionRange = -1;
boolean additionRangeNotSet = true;
boolean deletionRangeNotSet = true;
String[] diffLines = diffText.split(System.getProperty("line.separator"));
//for (String line : diffLines) {
for (int i=0; i<diffLines.length; i++) {
String line = diffLines[i];
if (line.startsWith(this.diffFilePrefix)) {
line = line.replaceAll(this.diffFilePrefix, "");
// do some additional filename filtering ----------
StringBuilder filename = new StringBuilder();
for (int j=0; j<line.length(); j++) {
char c = line.charAt(j);
if (String.valueOf(c).equals(" ")) {
break;
}
filename.append(c);
}
//--------------------------------------------------
// Here we check if a file was simply renamed...
//--------------------------------------------------
String renameTo = "";
if (diffLines[i+1].startsWith("similarity index 100%")) {
renameTo = diffLines[i+3].replace("rename to ", "");
}
//--------------------------------------------------
if (!renameTo.equals("")) {
newRelevantChanges = new Changes(filename.toString(), "/"+renameTo, leftRev, rightRev);
}
else {
newRelevantChanges = new Changes(filename.toString(), leftRev, rightRev);
}
relevantChanges.add(newRelevantChanges);
}
else if (newRelevantChanges != null && line.startsWith("@@") && line.endsWith("@@")) {
Matcher hunkMatcher = this.hunkRegexPattern.matcher(line);
hunkMatcher.matches();
deletionRange = Integer.parseInt(hunkMatcher.group(1));
additionRange = Integer.parseInt(hunkMatcher.group(2));
hunkMatcher.reset();
}
else if (newRelevantChanges != null) {
if (line.startsWith("-") && !line.startsWith("---")) {
line = line.substring(1).trim().replace("\t","");
newRelevantChanges.putDeletedLine(deletionRange, line);
if (deletionRangeNotSet) {
deletionRangeNotSet = false;
}
deletionRange++;
continue;
}
else if (line.startsWith("+") && !line.startsWith("+++")) {
line = line.substring(1).trim().replace("\t","");
newRelevantChanges.putAddedLine(additionRange, line);
if (additionRangeNotSet) {
additionRangeNotSet = false;
}
additionRange++;
continue;
}
else {
deletionRange++;
additionRange++;
}
}
}
return relevantChanges;
}
public int countNumberOfHunksInDiff(String diffText) {
int numberOfHunks = 0;
String[] diffLines = diffText.split(System.getProperty("line.separator"));
for (String line : diffLines) {
if (line.startsWith("@@") && line.endsWith("@@")) {
numberOfHunks++;
}
}
return numberOfHunks;
}
public void filterCommentsAndBlanks(Map<Integer, String> lines) {
Iterator<Map.Entry<Integer,String>> it = lines.entrySet().iterator();
while (it.hasNext()) {
String line = it.next().getValue();
Matcher commentMatcher = this.commentsPattern.matcher(line.trim());
if (line.trim().isEmpty() || commentMatcher.matches()) {
it.remove();
}
}
}
public Map<Integer, String> getLineMappings(final String fileContents) {
Map<Integer, String> lineMappings = new TreeMap<Integer, String>();
String[] lines = fileContents.split(System.getProperty("line.separator"));
int lineNumber = 1;
for (String line : lines) {
line = line.trim().replace("\t","");
lineMappings.put(lineNumber++, line);
}
return lineMappings;
}
public int getNumberOfLoc(final String fileContents) {
return this.getLineMappings(fileContents).size();
}
public int getNumberOfLocFiltered(final String fileContents) {
Map<Integer, String> locs = this.getLineMappings(fileContents);
this.filterCommentsAndBlanks(locs);
return locs.size();
}
protected abstract String getReleaseTag(String release) throws Exception;
public abstract String getReleaseCommit(String release) throws Exception;
public abstract Set<String> getAllRepositoryTransactions() throws Exception;
}

View File

@ -0,0 +1,185 @@
package it.unitn.molerat.repos.wrappers;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.ISvnObjectReceiver;
import org.tmatesoft.svn.core.wc2.SvnAnnotate;
import org.tmatesoft.svn.core.wc2.SvnAnnotateItem;
import org.tmatesoft.svn.core.wc2.SvnCat;
import org.tmatesoft.svn.core.wc2.SvnDiff;
import org.tmatesoft.svn.core.wc2.SvnLog;
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
import org.tmatesoft.svn.core.wc2.SvnRevisionRange;
import org.tmatesoft.svn.core.wc2.SvnTarget;
public final class SvnRepoWrapper extends RepoWrapper {
private final SVNURL url;
protected SVNRepository repo = null;
protected final SvnOperationFactory opFactory = new SvnOperationFactory();
public SvnRepoWrapper(String url) throws SVNException {
this.diffFilePrefix = "Index: ";
this.url = SVNURL.parseURIEncoded(url);
this.repo = SVNRepositoryFactory.create(this.url);
}
protected String doDiff(SvnTarget leftRev, SvnTarget rightRev) throws SVNException {
final ByteArrayOutputStream output = new ByteArrayOutputStream();
SvnDiff diff = opFactory.createDiff();
diff.setOutput(output);
diff.setSources(leftRev, rightRev);
diff.run();
return output.toString();
}
public Set<String> getRevisionNumbers(String topRev) throws SVNException {
Set<String> revNumbers = new LinkedHashSet<>();
LinkedList<SVNLogEntry> logEntries = new LinkedList<>();
SvnLog log = opFactory.createLog();
SvnTarget target = SvnTarget.fromURL(this.url);
log.addRange(SvnRevisionRange.create(SVNRevision.create(0), SVNRevision.create(Long.parseLong(topRev))));
log.setSingleTarget(target);
log.run(logEntries);
Iterator<SVNLogEntry> it = logEntries.descendingIterator();
if (it.hasNext()) {
it.next(); // discard the topRev
}
while (it.hasNext()) {
SVNLogEntry entry = it.next();
revNumbers.add(String.valueOf(entry.getRevision()));
}
return revNumbers;
}
protected void annotate(final SvnTarget target, ISvnObjectReceiver<SvnAnnotateItem> callback) throws SVNException {
SvnAnnotate annotate = opFactory.createAnnotate();
annotate.setSingleTarget(target);
final SVNRevision startRev = SVNRevision.create(1);
final SVNRevision endRev = target.getPegRevision();
annotate.setStartRevision(startRev);
annotate.setEndRevision(endRev);
annotate.setReceiver(callback);
annotate.run();
}
@Override
@SuppressWarnings("unchecked")
public void annotate(String path, String rev, Object callback) throws Exception {
long revLong = Long.parseLong(rev);
SvnTarget target = SvnTarget.fromURL(SVNURL.parseURIEncoded(this.getBasePath() + path), SVNRevision.create(revLong));
this.annotate(target, ((ISvnObjectReceiver<SvnAnnotateItem>)callback));
}
protected String doCat(final SvnTarget target) throws SVNException {
final ByteArrayOutputStream output = new ByteArrayOutputStream();
SvnCat cat = this.opFactory.createCat();
cat.addTarget(target);
cat.setOutput(output);
cat.run();
return output.toString();
}
@Override
public String doDiff(String leftRev, String rightRev) throws SVNException {
return this.doDiff("", leftRev, rightRev);
}
@Override
public String doDiff(String path, String leftRev, String rightRev) throws SVNException {
long leftLong = Long.parseLong(leftRev);
long rightLong = Long.parseLong(rightRev);
SvnTarget left = SvnTarget.fromURL(SVNURL.parseURIEncoded(this.url + path), SVNRevision.create(leftLong));
SvnTarget right = SvnTarget.fromURL(SVNURL.parseURIEncoded(this.url + path), SVNRevision.create(rightLong));
return this.doDiff(left, right);
}
@Override
public String getBasePath() {
return this.url.toString();
}
@Override
public String doCat(String path, String rev) throws SVNException {
long revLong = Long.parseLong(rev);
SvnTarget target = SvnTarget.fromURL(SVNURL.parseURIEncoded(this.url + path), SVNRevision.create(revLong));
return this.doCat(target);
}
//----------------------------------------------------------------------------------------------------
public String getTopmostRevision(String url) throws SVNException {
SvnLog log = opFactory.createLog();
SvnTarget target = SvnTarget.fromURL(SVNURL.parseURIEncoded(url));
log.addRange(SvnRevisionRange.create(null, null));
log.setSingleTarget(target);
SVNLogEntry entry = log.run();
return String.valueOf(entry.getRevision());
}
//----------------------------------------------------------------------------------------------------
/*----------------------------------------------------------------------------------------------------
* example found at: http://blog.gmane.org/gmane.comp.version-control.subversion.javasvn.user/month=20131101
----------------------------------------------------------------------------------------------------*/
@Override
public Map<Integer, String> determineOriginatingRevision(final String filePath,
final String revision, final Map<Integer, String> lines) throws Exception {
final Map<Integer, String> originating = new TreeMap<Integer, String>();
final long startRev = 1;
final long endRev = Long.parseLong(revision);
this.annotate(filePath, String.valueOf(endRev), new ISvnObjectReceiver<SvnAnnotateItem>() {
@Override
public void receive(SvnTarget target, SvnAnnotateItem itm) throws SVNException {
if (itm.isLine()) {
final long revision = itm.getRevision();
final int lineNumber = itm.getLineNumber() + 1;
if (startRev < revision && revision <= endRev) {
if (lines.containsKey(lineNumber)) {
originating.put(lineNumber, String.valueOf(revision));
}
}
}
}
});
return originating;
}
// TODO: UNIMPLEMENTED
@Override
protected String getReleaseTag(String release) throws Exception {
return "";
}
// TODO: UNIMPLEMENTED
@Override
public String getReleaseCommit(String release) throws Exception {
return "";
}
// TODO: UNIMPLEMENTED
@Override
public Set<String> getRevisionFiles(String rev, String filter) throws Exception {
return new LinkedHashSet<>();
}
// TODO: UNIMPLEMENTED
@Override
public Set<String> getAllRepositoryTransactions() throws Exception {
return new LinkedHashSet<>();
}
}

20
pom.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>it.unitn</groupId>
<artifactId>foss-vuln-tracker</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<modules>
<module>molerat</module>
<module>repoman</module>
</modules>
</project>

69
repoman/pom.xml Normal file
View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- parent project -->
<parent>
<groupId>it.unitn</groupId>
<artifactId>foss-vuln-tracker</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>it.unitn.repoman</groupId>
<artifactId>repoman</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- declare dependencies -->
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.7</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<!-- build plugins -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>it.unitn.repoman.cmd.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,87 @@
package it.unitn.repoman.cmd;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.slicers.LightweightSlice;
import it.unitn.repoman.core.utils.printers.ConsolePrinterListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.Set;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.apache.commons.cli.*;
public class Main {
public static void main(String[] args) {
Options opts = new Options();
Option fileOpt = Option.builder("f")
.argName("e.g, ./Code.java")
.longOpt("file")
.required(true)
.hasArg()
.desc(".java file")
.build();
opts.addOption(fileOpt);
Option lineNumbersOpt = Option.builder("l")
.argName("e.g, '1 2 3 4 ...'")
.longOpt("line-numbers")
.desc("Seed lines (line numbers separated with spaces)")
.required(true)
.hasArgs()
.build();
opts.addOption(lineNumbersOpt);
CommandLineParser cmdParser = new DefaultParser();
HelpFormatter helpFormatter = new HelpFormatter();
CommandLine cmd;
try {
cmd = cmdParser.parse(opts, args);
String file = cmd.getOptionValue("f");
LanguageFactory.init("Java", readFile(file));
String[] argLines = cmd.getOptionValues("l");
Set<Integer> lines = new LinkedHashSet<>();
for (int i=0; i<argLines.length; i++) {
lines.add(Integer.parseInt(argLines[i]));
}
Parser parser = LanguageFactory.getParser();
LightweightSlice slice = new LightweightSlice(LanguageFactory.getRoot(), lines);
ParseTreeListener printer = new ConsolePrinterListener(parser, slice);
System.out.println(printer);
}
catch (ParseException e) {
System.out.println("ERROR: " + e.getMessage());
helpFormatter.printHelp("utility-name", opts);
}
catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
}
private static String readFile(String filename) throws IOException {
File javaFile = new File(filename);
if (!javaFile.exists())
throw new FileNotFoundException(filename);
BufferedReader in = new BufferedReader(new FileReader(javaFile));
StringBuffer buffer = new StringBuffer();
String line = null;
try {
while ( (line = in.readLine()) != null) {
buffer.append(line);
buffer.append('\n');
}
}
finally {
in.close();
}
return buffer.toString();
}
}

View File

@ -0,0 +1,9 @@
package it.unitn.repoman.core.exceptions;
@SuppressWarnings("serial")
public class InvalidLineException extends Exception {
public InvalidLineException(int line) {
super("ERROR! Invalid line number --> " + line);
}
}

View File

@ -0,0 +1,59 @@
package it.unitn.repoman.core.lang;
import org.antlr.v4.runtime.*;
import it.unitn.repoman.core.lang.wrappers.c.CWrapper;
import it.unitn.repoman.core.lang.wrappers.java.JavaWrapper;
import it.unitn.repoman.core.lang.wrappers.generic.Wrapper;
import it.unitn.repoman.core.lang.parsers.c.CLexer;
import it.unitn.repoman.core.lang.parsers.c.CParser;
import it.unitn.repoman.core.lang.parsers.java.JavaLexer;
import it.unitn.repoman.core.lang.parsers.java.JavaParser;
public class LanguageFactory {
private static Wrapper wrapper;
private static Parser parser;
private static ParserRuleContext root;
private LanguageFactory() {}
public static void init(String language, String contents) {
try {
if (language.toLowerCase().equals("java")) {
wrapper = new JavaWrapper();
JavaLexer lexer = new JavaLexer(CharStreams.fromString(contents));
CommonTokenStream tokens = new CommonTokenStream(lexer);
parser = new JavaParser(tokens);
root = ((JavaParser)parser).compilationUnit();
}
else if (language.toLowerCase().equals("c")) {
wrapper = new CWrapper();
CLexer lexer = new CLexer(CharStreams.fromString(contents));
CommonTokenStream tokens = new CommonTokenStream(lexer);
parser = new CParser(tokens);
root = ((CParser)parser).compilationUnit();
}
/*
else if (language.toLowerCase().equals("javascript")) {
//TODO
}
*/
}
catch (Exception e) {
e.printStackTrace();
}
}
public static Wrapper getWrapper() {
return wrapper;
}
public static Parser getParser() {
return parser;
}
public static ParserRuleContext getRoot() {
return root;
}
}

View File

@ -0,0 +1,221 @@
Enum=25
AndAssign=97
Or=79
Break=16
LeftShift=69
GreaterEqual=68
Bool=52
ThreadLocal=58
LeftBracket=61
RightBrace=64
Equal=100
Directives=117
Restrict=35
Sizeof=39
StarAssign=90
Arrow=102
NotEqual=101
LessEqual=66
Dot=103
RightParen=60
XorAssign=98
Float=27
Switch=42
Typedef=43
StringLiteral=107
If=30
Minus=73
MinusAssign=94
LeftParen=59
Newline=114
Union=44
Case=17
Extern=26
Complex=53
RightShiftAssign=96
Comma=88
Star=75
Char=18
ComplexDefine=108
T__3=11
T__2=12
T__1=13
Question=85
T__0=14
OrOr=81
LineAfterPreprocessing=110
Inline=31
Default=21
Alignas=49
Div=76
RightBracket=62
Register=34
Else=24
Assign=89
AndAnd=80
LineDirective=111
LineComment=116
RightShift=70
LeftShiftAssign=95
Identifier=105
T__11=3
T__12=2
T__13=1
Void=46
Plus=71
AsmBlock=109
StaticAssert=57
Less=65
Short=37
T__10=4
BlockComment=115
T__9=5
Goto=29
T__8=6
T__7=7
T__6=8
T__5=9
Signed=38
T__4=10
Const=19
Imaginary=55
For=28
Semi=87
OrAssign=99
Do=22
Double=23
Not=83
And=78
Long=33
Static=40
Caret=82
Alignof=50
Generic=54
Constant=106
Atomic=51
Continue=20
Int=32
MinusMinus=74
Whitespace=113
Struct=41
Auto=15
PlusPlus=72
PlusAssign=93
Colon=86
DivAssign=91
LeftBrace=63
Return=36
Mod=77
Ellipsis=104
Tilde=84
PragmaDirective=112
While=48
Noreturn=56
Volatile=47
ModAssign=92
Unsigned=45
Greater=67
'-'=73
'typedef'=43
'else'=24
'_Static_assert'=57
'%'=77
'__builtin_offsetof'=14
'>'=67
'--'=74
'=='=100
'_Complex'=53
'...'=104
'case'=17
'->'=102
'.'=103
'_Thread_local'=58
'__m128'=13
'&'=78
'__inline__'=12
'double'=23
'break'=16
'short'=37
'<='=66
'enum'=25
'?'=85
'__attribute__'=11
'if'=30
'_Generic'=54
'goto'=29
'<<'=69
'inline'=31
'||'=81
'return'=36
'__m128i'=10
'_Imaginary'=55
'unsigned'=45
'continue'=20
'/'=76
'_Bool'=52
'__m128d'=9
'signed'=38
'__asm'=8
'register'=34
'sizeof'=39
'static'=40
'__typeof__'=7
'++'=72
'__builtin_va_arg'=6
'const'=19
'volatile'=47
'/='=91
'__declspec'=5
'do'=22
'('=59
'|='=99
'for'=28
'void'=46
'{'=63
'float'=27
'+='=93
')'=60
'__asm__'=4
'auto'=15
'!'=83
'|'=79
'['=61
':'=86
'_Atomic'=51
'*'=75
'switch'=42
'_Alignas'=49
'_Alignof'=50
'__stdcall'=3
'}'=64
';'=87
'>>='=96
'&='=97
'*='=90
'struct'=41
'+'=71
'~'=84
']'=62
'<'=65
'_Noreturn'=56
'>='=68
'long'=33
','=88
'-='=94
'union'=44
'int'=32
'__volatile__'=2
'^'=82
'<<='=95
'='=89
'restrict'=35
'>>'=70
'&&'=80
'^='=98
'while'=48
'!='=101
'__extension__'=1
'char'=18
'%='=92
'extern'=26
'default'=21

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,618 @@
// Generated from C.g4 by ANTLR 4.4
package it.unitn.repoman.core.lang.parsers.c;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class CLexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.4", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
T__13=1, T__12=2, T__11=3, T__10=4, T__9=5, T__8=6, T__7=7, T__6=8, T__5=9,
T__4=10, T__3=11, T__2=12, T__1=13, T__0=14, Auto=15, Break=16, Case=17,
Char=18, Const=19, Continue=20, Default=21, Do=22, Double=23, Else=24,
Enum=25, Extern=26, Float=27, For=28, Goto=29, If=30, Inline=31, Int=32,
Long=33, Register=34, Restrict=35, Return=36, Short=37, Signed=38, Sizeof=39,
Static=40, Struct=41, Switch=42, Typedef=43, Union=44, Unsigned=45, Void=46,
Volatile=47, While=48, Alignas=49, Alignof=50, Atomic=51, Bool=52, Complex=53,
Generic=54, Imaginary=55, Noreturn=56, StaticAssert=57, ThreadLocal=58,
LeftParen=59, RightParen=60, LeftBracket=61, RightBracket=62, LeftBrace=63,
RightBrace=64, Less=65, LessEqual=66, Greater=67, GreaterEqual=68, LeftShift=69,
RightShift=70, Plus=71, PlusPlus=72, Minus=73, MinusMinus=74, Star=75,
Div=76, Mod=77, And=78, Or=79, AndAnd=80, OrOr=81, Caret=82, Not=83, Tilde=84,
Question=85, Colon=86, Semi=87, Comma=88, Assign=89, StarAssign=90, DivAssign=91,
ModAssign=92, PlusAssign=93, MinusAssign=94, LeftShiftAssign=95, RightShiftAssign=96,
AndAssign=97, XorAssign=98, OrAssign=99, Equal=100, NotEqual=101, Arrow=102,
Dot=103, Ellipsis=104, Identifier=105, Constant=106, StringLiteral=107,
ComplexDefine=108, AsmBlock=109, LineAfterPreprocessing=110, LineDirective=111,
PragmaDirective=112, Whitespace=113, Newline=114, BlockComment=115, LineComment=116,
Directives=117;
public static String[] modeNames = {
"DEFAULT_MODE"
};
public static final String[] tokenNames = {
"'\\u0000'", "'\\u0001'", "'\\u0002'", "'\\u0003'", "'\\u0004'", "'\\u0005'",
"'\\u0006'", "'\\u0007'", "'\b'", "'\t'", "'\n'", "'\\u000B'", "'\f'",
"'\r'", "'\\u000E'", "'\\u000F'", "'\\u0010'", "'\\u0011'", "'\\u0012'",
"'\\u0013'", "'\\u0014'", "'\\u0015'", "'\\u0016'", "'\\u0017'", "'\\u0018'",
"'\\u0019'", "'\\u001A'", "'\\u001B'", "'\\u001C'", "'\\u001D'", "'\\u001E'",
"'\\u001F'", "' '", "'!'", "'\"'", "'#'", "'$'", "'%'", "'&'", "'''",
"'('", "')'", "'*'", "'+'", "','", "'-'", "'.'", "'/'", "'0'", "'1'",
"'2'", "'3'", "'4'", "'5'", "'6'", "'7'", "'8'", "'9'", "':'", "';'",
"'<'", "'='", "'>'", "'?'", "'@'", "'A'", "'B'", "'C'", "'D'", "'E'",
"'F'", "'G'", "'H'", "'I'", "'J'", "'K'", "'L'", "'M'", "'N'", "'O'",
"'P'", "'Q'", "'R'", "'S'", "'T'", "'U'", "'V'", "'W'", "'X'", "'Y'",
"'Z'", "'['", "'\\'", "']'", "'^'", "'_'", "'`'", "'a'", "'b'", "'c'",
"'d'", "'e'", "'f'", "'g'", "'h'", "'i'", "'j'", "'k'", "'l'", "'m'",
"'n'", "'o'", "'p'", "'q'", "'r'", "'s'", "'t'", "'u'"
};
public static final String[] ruleNames = {
"T__13", "T__12", "T__11", "T__10", "T__9", "T__8", "T__7", "T__6", "T__5",
"T__4", "T__3", "T__2", "T__1", "T__0", "Auto", "Break", "Case", "Char",
"Const", "Continue", "Default", "Do", "Double", "Else", "Enum", "Extern",
"Float", "For", "Goto", "If", "Inline", "Int", "Long", "Register", "Restrict",
"Return", "Short", "Signed", "Sizeof", "Static", "Struct", "Switch", "Typedef",
"Union", "Unsigned", "Void", "Volatile", "While", "Alignas", "Alignof",
"Atomic", "Bool", "Complex", "Generic", "Imaginary", "Noreturn", "StaticAssert",
"ThreadLocal", "LeftParen", "RightParen", "LeftBracket", "RightBracket",
"LeftBrace", "RightBrace", "Less", "LessEqual", "Greater", "GreaterEqual",
"LeftShift", "RightShift", "Plus", "PlusPlus", "Minus", "MinusMinus",
"Star", "Div", "Mod", "And", "Or", "AndAnd", "OrOr", "Caret", "Not", "Tilde",
"Question", "Colon", "Semi", "Comma", "Assign", "StarAssign", "DivAssign",
"ModAssign", "PlusAssign", "MinusAssign", "LeftShiftAssign", "RightShiftAssign",
"AndAssign", "XorAssign", "OrAssign", "Equal", "NotEqual", "Arrow", "Dot",
"Ellipsis", "Identifier", "IdentifierNondigit", "Nondigit", "Digit", "UniversalCharacterName",
"HexQuad", "Constant", "IntegerConstant", "BinaryConstant", "DecimalConstant",
"OctalConstant", "HexadecimalConstant", "HexadecimalPrefix", "NonzeroDigit",
"OctalDigit", "HexadecimalDigit", "IntegerSuffix", "UnsignedSuffix", "LongSuffix",
"LongLongSuffix", "FloatingConstant", "DecimalFloatingConstant", "HexadecimalFloatingConstant",
"FractionalConstant", "ExponentPart", "Sign", "DigitSequence", "HexadecimalFractionalConstant",
"BinaryExponentPart", "HexadecimalDigitSequence", "FloatingSuffix", "CharacterConstant",
"CCharSequence", "CChar", "EscapeSequence", "SimpleEscapeSequence", "OctalEscapeSequence",
"HexadecimalEscapeSequence", "StringLiteral", "EncodingPrefix", "SCharSequence",
"SChar", "ComplexDefine", "AsmBlock", "LineAfterPreprocessing", "LineDirective",
"PragmaDirective", "Whitespace", "Newline", "BlockComment", "LineComment",
"Directives"
};
public CLexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "C.g4"; }
@Override
public String[] getTokenNames() { return tokenNames; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String getSerializedATN() { return _serializedATN; }
@Override
public String[] getModeNames() { return modeNames; }
@Override
public ATN getATN() { return _ATN; }
public static final String _serializedATN =
"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2w\u0543\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+
",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+
"\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t="+
"\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+
"\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+
"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
"`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k\t"+
"k\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv\4"+
"w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\4\177\t\177\4\u0080\t\u0080"+
"\4\u0081\t\u0081\4\u0082\t\u0082\4\u0083\t\u0083\4\u0084\t\u0084\4\u0085"+
"\t\u0085\4\u0086\t\u0086\4\u0087\t\u0087\4\u0088\t\u0088\4\u0089\t\u0089"+
"\4\u008a\t\u008a\4\u008b\t\u008b\4\u008c\t\u008c\4\u008d\t\u008d\4\u008e"+
"\t\u008e\4\u008f\t\u008f\4\u0090\t\u0090\4\u0091\t\u0091\4\u0092\t\u0092"+
"\4\u0093\t\u0093\4\u0094\t\u0094\4\u0095\t\u0095\4\u0096\t\u0096\4\u0097"+
"\t\u0097\4\u0098\t\u0098\4\u0099\t\u0099\4\u009a\t\u009a\4\u009b\t\u009b"+
"\4\u009c\t\u009c\4\u009d\t\u009d\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3"+
"\2\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3"+
"\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+
"\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7"+
"\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3"+
"\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+
"\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3"+
"\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r"+
"\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17"+
"\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20"+
"\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22"+
"\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25"+
"\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+
"\3\26\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31"+
"\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
"\3\34\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36"+
"\3\36\3\37\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3!\3!\3!\3!\3\"\3\"\3\"\3\""+
"\3\"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3$\3$\3$\3$\3%\3%\3%\3"+
"%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3(\3(\3(\3(\3"+
"(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3*\3*\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3+\3"+
"+\3,\3,\3,\3,\3,\3,\3,\3,\3-\3-\3-\3-\3-\3-\3.\3.\3.\3.\3.\3.\3.\3.\3"+
".\3/\3/\3/\3/\3/\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\61\3\61"+
"\3\61\3\61\3\61\3\61\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3\63"+
"\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\64"+
"\3\64\3\64\3\65\3\65\3\65\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\66\3\66"+
"\3\66\3\66\3\66\3\67\3\67\3\67\3\67\3\67\3\67\3\67\3\67\3\67\38\38\38"+
"\38\38\38\38\38\38\38\38\39\39\39\39\39\39\39\39\39\39\3:\3:\3:\3:\3:"+
"\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;"+
"\3;\3<\3<\3=\3=\3>\3>\3?\3?\3@\3@\3A\3A\3B\3B\3C\3C\3C\3D\3D\3E\3E\3E"+
"\3F\3F\3F\3G\3G\3G\3H\3H\3I\3I\3I\3J\3J\3K\3K\3K\3L\3L\3M\3M\3N\3N\3O"+
"\3O\3P\3P\3Q\3Q\3Q\3R\3R\3R\3S\3S\3T\3T\3U\3U\3V\3V\3W\3W\3X\3X\3Y\3Y"+
"\3Z\3Z\3[\3[\3[\3\\\3\\\3\\\3]\3]\3]\3^\3^\3^\3_\3_\3_\3`\3`\3`\3`\3a"+
"\3a\3a\3a\3b\3b\3b\3c\3c\3c\3d\3d\3d\3e\3e\3e\3f\3f\3f\3g\3g\3g\3h\3h"+
"\3i\3i\3i\3i\3j\3j\3j\7j\u038b\nj\fj\16j\u038e\13j\3k\3k\5k\u0392\nk\3"+
"l\3l\3m\3m\3n\3n\3n\3n\3n\3n\3n\3n\3n\3n\5n\u03a2\nn\3o\3o\3o\3o\3o\3"+
"p\3p\3p\5p\u03ac\np\3q\3q\5q\u03b0\nq\3q\3q\5q\u03b4\nq\3q\3q\5q\u03b8"+
"\nq\3q\5q\u03bb\nq\3r\3r\3r\6r\u03c0\nr\rr\16r\u03c1\3s\3s\7s\u03c6\n"+
"s\fs\16s\u03c9\13s\3t\3t\7t\u03cd\nt\ft\16t\u03d0\13t\3u\3u\6u\u03d4\n"+
"u\ru\16u\u03d5\3v\3v\3v\3w\3w\3x\3x\3y\3y\3z\3z\5z\u03e3\nz\3z\3z\3z\3"+
"z\3z\5z\u03ea\nz\3z\3z\5z\u03ee\nz\5z\u03f0\nz\3{\3{\3|\3|\3}\3}\3}\3"+
"}\5}\u03fa\n}\3~\3~\5~\u03fe\n~\3\177\3\177\5\177\u0402\n\177\3\177\5"+
"\177\u0405\n\177\3\177\3\177\3\177\5\177\u040a\n\177\5\177\u040c\n\177"+
"\3\u0080\3\u0080\3\u0080\3\u0080\5\u0080\u0412\n\u0080\3\u0080\3\u0080"+
"\3\u0080\3\u0080\5\u0080\u0418\n\u0080\5\u0080\u041a\n\u0080\3\u0081\5"+
"\u0081\u041d\n\u0081\3\u0081\3\u0081\3\u0081\3\u0081\3\u0081\5\u0081\u0424"+
"\n\u0081\3\u0082\3\u0082\5\u0082\u0428\n\u0082\3\u0082\3\u0082\3\u0082"+
"\5\u0082\u042d\n\u0082\3\u0082\5\u0082\u0430\n\u0082\3\u0083\3\u0083\3"+
"\u0084\6\u0084\u0435\n\u0084\r\u0084\16\u0084\u0436\3\u0085\5\u0085\u043a"+
"\n\u0085\3\u0085\3\u0085\3\u0085\3\u0085\3\u0085\5\u0085\u0441\n\u0085"+
"\3\u0086\3\u0086\5\u0086\u0445\n\u0086\3\u0086\3\u0086\3\u0086\5\u0086"+
"\u044a\n\u0086\3\u0086\5\u0086\u044d\n\u0086\3\u0087\6\u0087\u0450\n\u0087"+
"\r\u0087\16\u0087\u0451\3\u0088\3\u0088\3\u0089\3\u0089\3\u0089\3\u0089"+
"\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089"+
"\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089"+
"\5\u0089\u046c\n\u0089\3\u008a\6\u008a\u046f\n\u008a\r\u008a\16\u008a"+
"\u0470\3\u008b\3\u008b\5\u008b\u0475\n\u008b\3\u008c\3\u008c\3\u008c\3"+
"\u008c\5\u008c\u047b\n\u008c\3\u008d\3\u008d\3\u008d\3\u008e\3\u008e\3"+
"\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e"+
"\5\u008e\u048b\n\u008e\3\u008f\3\u008f\3\u008f\3\u008f\6\u008f\u0491\n"+
"\u008f\r\u008f\16\u008f\u0492\3\u0090\5\u0090\u0496\n\u0090\3\u0090\3"+
"\u0090\5\u0090\u049a\n\u0090\3\u0090\3\u0090\3\u0091\3\u0091\3\u0091\5"+
"\u0091\u04a1\n\u0091\3\u0092\6\u0092\u04a4\n\u0092\r\u0092\16\u0092\u04a5"+
"\3\u0093\3\u0093\3\u0093\3\u0093\3\u0093\3\u0093\3\u0093\5\u0093\u04af"+
"\n\u0093\3\u0094\3\u0094\5\u0094\u04b3\n\u0094\3\u0094\3\u0094\3\u0094"+
"\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094\7\u0094\u04bd\n\u0094\f\u0094"+
"\16\u0094\u04c0\13\u0094\3\u0094\3\u0094\3\u0095\3\u0095\3\u0095\3\u0095"+
"\3\u0095\7\u0095\u04c9\n\u0095\f\u0095\16\u0095\u04cc\13\u0095\3\u0095"+
"\3\u0095\7\u0095\u04d0\n\u0095\f\u0095\16\u0095\u04d3\13\u0095\3\u0095"+
"\3\u0095\3\u0095\3\u0095\3\u0096\3\u0096\3\u0096\3\u0096\3\u0096\3\u0096"+
"\3\u0096\7\u0096\u04e0\n\u0096\f\u0096\16\u0096\u04e3\13\u0096\3\u0096"+
"\7\u0096\u04e6\n\u0096\f\u0096\16\u0096\u04e9\13\u0096\3\u0096\3\u0096"+
"\3\u0097\3\u0097\5\u0097\u04ef\n\u0097\3\u0097\3\u0097\5\u0097\u04f3\n"+
"\u0097\3\u0097\3\u0097\7\u0097\u04f7\n\u0097\f\u0097\16\u0097\u04fa\13"+
"\u0097\3\u0097\3\u0097\3\u0098\3\u0098\5\u0098\u0500\n\u0098\3\u0098\3"+
"\u0098\3\u0098\3\u0098\3\u0098\3\u0098\3\u0098\3\u0098\3\u0098\7\u0098"+
"\u050b\n\u0098\f\u0098\16\u0098\u050e\13\u0098\3\u0098\3\u0098\3\u0099"+
"\6\u0099\u0513\n\u0099\r\u0099\16\u0099\u0514\3\u0099\3\u0099\3\u009a"+
"\3\u009a\5\u009a\u051b\n\u009a\3\u009a\5\u009a\u051e\n\u009a\3\u009a\3"+
"\u009a\3\u009b\3\u009b\3\u009b\3\u009b\7\u009b\u0526\n\u009b\f\u009b\16"+
"\u009b\u0529\13\u009b\3\u009b\3\u009b\3\u009b\3\u009b\3\u009b\3\u009c"+
"\3\u009c\3\u009c\3\u009c\7\u009c\u0534\n\u009c\f\u009c\16\u009c\u0537"+
"\13\u009c\3\u009c\3\u009c\3\u009d\3\u009d\7\u009d\u053d\n\u009d\f\u009d"+
"\16\u009d\u0540\13\u009d\3\u009d\3\u009d\3\u0527\2\u009e\3\3\5\4\7\5\t"+
"\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23"+
"%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G"+
"%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{"+
"?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091"+
"J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5"+
"T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9"+
"^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9f\u00cbg\u00cd"+
"h\u00cfi\u00d1j\u00d3k\u00d5\2\u00d7\2\u00d9\2\u00db\2\u00dd\2\u00dfl"+
"\u00e1\2\u00e3\2\u00e5\2\u00e7\2\u00e9\2\u00eb\2\u00ed\2\u00ef\2\u00f1"+
"\2\u00f3\2\u00f5\2\u00f7\2\u00f9\2\u00fb\2\u00fd\2\u00ff\2\u0101\2\u0103"+
"\2\u0105\2\u0107\2\u0109\2\u010b\2\u010d\2\u010f\2\u0111\2\u0113\2\u0115"+
"\2\u0117\2\u0119\2\u011b\2\u011d\2\u011fm\u0121\2\u0123\2\u0125\2\u0127"+
"n\u0129o\u012bp\u012dq\u012fr\u0131s\u0133t\u0135u\u0137v\u0139w\3\2\27"+
"\5\2C\\aac|\3\2\62;\4\2DDdd\3\2\62\63\4\2ZZzz\3\2\63;\3\2\629\5\2\62;"+
"CHch\4\2WWww\4\2NNnn\4\2--//\6\2HHNNhhnn\6\2\f\f\17\17))^^\f\2$$))AA^"+
"^cdhhppttvvxx\5\2NNWWww\6\2\f\f\17\17$$^^\3\2%%\3\2}}\3\2\177\177\4\2"+
"\f\f\17\17\4\2\13\13\"\"\u0569\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t"+
"\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2"+
"\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2"+
"\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2"+
"+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2"+
"\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2"+
"C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3"+
"\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2"+
"\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2"+
"i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3"+
"\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081"+
"\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2"+
"\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093"+
"\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2"+
"\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5"+
"\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2"+
"\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7"+
"\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2"+
"\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9"+
"\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2"+
"\2\2\u00d3\3\2\2\2\2\u00df\3\2\2\2\2\u011f\3\2\2\2\2\u0127\3\2\2\2\2\u0129"+
"\3\2\2\2\2\u012b\3\2\2\2\2\u012d\3\2\2\2\2\u012f\3\2\2\2\2\u0131\3\2\2"+
"\2\2\u0133\3\2\2\2\2\u0135\3\2\2\2\2\u0137\3\2\2\2\2\u0139\3\2\2\2\3\u013b"+
"\3\2\2\2\5\u0149\3\2\2\2\7\u0156\3\2\2\2\t\u0160\3\2\2\2\13\u0168\3\2"+
"\2\2\r\u0173\3\2\2\2\17\u0184\3\2\2\2\21\u018f\3\2\2\2\23\u0195\3\2\2"+
"\2\25\u019d\3\2\2\2\27\u01a5\3\2\2\2\31\u01b3\3\2\2\2\33\u01be\3\2\2\2"+
"\35\u01c5\3\2\2\2\37\u01d8\3\2\2\2!\u01dd\3\2\2\2#\u01e3\3\2\2\2%\u01e8"+
"\3\2\2\2\'\u01ed\3\2\2\2)\u01f3\3\2\2\2+\u01fc\3\2\2\2-\u0204\3\2\2\2"+
"/\u0207\3\2\2\2\61\u020e\3\2\2\2\63\u0213\3\2\2\2\65\u0218\3\2\2\2\67"+
"\u021f\3\2\2\29\u0225\3\2\2\2;\u0229\3\2\2\2=\u022e\3\2\2\2?\u0231\3\2"+
"\2\2A\u0238\3\2\2\2C\u023c\3\2\2\2E\u0241\3\2\2\2G\u024a\3\2\2\2I\u0253"+
"\3\2\2\2K\u025a\3\2\2\2M\u0260\3\2\2\2O\u0267\3\2\2\2Q\u026e\3\2\2\2S"+
"\u0275\3\2\2\2U\u027c\3\2\2\2W\u0283\3\2\2\2Y\u028b\3\2\2\2[\u0291\3\2"+
"\2\2]\u029a\3\2\2\2_\u029f\3\2\2\2a\u02a8\3\2\2\2c\u02ae\3\2\2\2e\u02b7"+
"\3\2\2\2g\u02c0\3\2\2\2i\u02c8\3\2\2\2k\u02ce\3\2\2\2m\u02d7\3\2\2\2o"+
"\u02e0\3\2\2\2q\u02eb\3\2\2\2s\u02f5\3\2\2\2u\u0304\3\2\2\2w\u0312\3\2"+
"\2\2y\u0314\3\2\2\2{\u0316\3\2\2\2}\u0318\3\2\2\2\177\u031a\3\2\2\2\u0081"+
"\u031c\3\2\2\2\u0083\u031e\3\2\2\2\u0085\u0320\3\2\2\2\u0087\u0323\3\2"+
"\2\2\u0089\u0325\3\2\2\2\u008b\u0328\3\2\2\2\u008d\u032b\3\2\2\2\u008f"+
"\u032e\3\2\2\2\u0091\u0330\3\2\2\2\u0093\u0333\3\2\2\2\u0095\u0335\3\2"+
"\2\2\u0097\u0338\3\2\2\2\u0099\u033a\3\2\2\2\u009b\u033c\3\2\2\2\u009d"+
"\u033e\3\2\2\2\u009f\u0340\3\2\2\2\u00a1\u0342\3\2\2\2\u00a3\u0345\3\2"+
"\2\2\u00a5\u0348\3\2\2\2\u00a7\u034a\3\2\2\2\u00a9\u034c\3\2\2\2\u00ab"+
"\u034e\3\2\2\2\u00ad\u0350\3\2\2\2\u00af\u0352\3\2\2\2\u00b1\u0354\3\2"+
"\2\2\u00b3\u0356\3\2\2\2\u00b5\u0358\3\2\2\2\u00b7\u035b\3\2\2\2\u00b9"+
"\u035e\3\2\2\2\u00bb\u0361\3\2\2\2\u00bd\u0364\3\2\2\2\u00bf\u0367\3\2"+
"\2\2\u00c1\u036b\3\2\2\2\u00c3\u036f\3\2\2\2\u00c5\u0372\3\2\2\2\u00c7"+
"\u0375\3\2\2\2\u00c9\u0378\3\2\2\2\u00cb\u037b\3\2\2\2\u00cd\u037e\3\2"+
"\2\2\u00cf\u0381\3\2\2\2\u00d1\u0383\3\2\2\2\u00d3\u0387\3\2\2\2\u00d5"+
"\u0391\3\2\2\2\u00d7\u0393\3\2\2\2\u00d9\u0395\3\2\2\2\u00db\u03a1\3\2"+
"\2\2\u00dd\u03a3\3\2\2\2\u00df\u03ab\3\2\2\2\u00e1\u03ba\3\2\2\2\u00e3"+
"\u03bc\3\2\2\2\u00e5\u03c3\3\2\2\2\u00e7\u03ca\3\2\2\2\u00e9\u03d1\3\2"+
"\2\2\u00eb\u03d7\3\2\2\2\u00ed\u03da\3\2\2\2\u00ef\u03dc\3\2\2\2\u00f1"+
"\u03de\3\2\2\2\u00f3\u03ef\3\2\2\2\u00f5\u03f1\3\2\2\2\u00f7\u03f3\3\2"+
"\2\2\u00f9\u03f9\3\2\2\2\u00fb\u03fd\3\2\2\2\u00fd\u040b\3\2\2\2\u00ff"+
"\u0419\3\2\2\2\u0101\u0423\3\2\2\2\u0103\u042f\3\2\2\2\u0105\u0431\3\2"+
"\2\2\u0107\u0434\3\2\2\2\u0109\u0440\3\2\2\2\u010b\u044c\3\2\2\2\u010d"+
"\u044f\3\2\2\2\u010f\u0453\3\2\2\2\u0111\u046b\3\2\2\2\u0113\u046e\3\2"+
"\2\2\u0115\u0474\3\2\2\2\u0117\u047a\3\2\2\2\u0119\u047c\3\2\2\2\u011b"+
"\u048a\3\2\2\2\u011d\u048c\3\2\2\2\u011f\u0495\3\2\2\2\u0121\u04a0\3\2"+
"\2\2\u0123\u04a3\3\2\2\2\u0125\u04ae\3\2\2\2\u0127\u04b0\3\2\2\2\u0129"+
"\u04c3\3\2\2\2\u012b\u04d8\3\2\2\2\u012d\u04ec\3\2\2\2\u012f\u04fd\3\2"+
"\2\2\u0131\u0512\3\2\2\2\u0133\u051d\3\2\2\2\u0135\u0521\3\2\2\2\u0137"+
"\u052f\3\2\2\2\u0139\u053a\3\2\2\2\u013b\u013c\7a\2\2\u013c\u013d\7a\2"+
"\2\u013d\u013e\7g\2\2\u013e\u013f\7z\2\2\u013f\u0140\7v\2\2\u0140\u0141"+
"\7g\2\2\u0141\u0142\7p\2\2\u0142\u0143\7u\2\2\u0143\u0144\7k\2\2\u0144"+
"\u0145\7q\2\2\u0145\u0146\7p\2\2\u0146\u0147\7a\2\2\u0147\u0148\7a\2\2"+
"\u0148\4\3\2\2\2\u0149\u014a\7a\2\2\u014a\u014b\7a\2\2\u014b\u014c\7x"+
"\2\2\u014c\u014d\7q\2\2\u014d\u014e\7n\2\2\u014e\u014f\7c\2\2\u014f\u0150"+
"\7v\2\2\u0150\u0151\7k\2\2\u0151\u0152\7n\2\2\u0152\u0153\7g\2\2\u0153"+
"\u0154\7a\2\2\u0154\u0155\7a\2\2\u0155\6\3\2\2\2\u0156\u0157\7a\2\2\u0157"+
"\u0158\7a\2\2\u0158\u0159\7u\2\2\u0159\u015a\7v\2\2\u015a\u015b\7f\2\2"+
"\u015b\u015c\7e\2\2\u015c\u015d\7c\2\2\u015d\u015e\7n\2\2\u015e\u015f"+
"\7n\2\2\u015f\b\3\2\2\2\u0160\u0161\7a\2\2\u0161\u0162\7a\2\2\u0162\u0163"+
"\7c\2\2\u0163\u0164\7u\2\2\u0164\u0165\7o\2\2\u0165\u0166\7a\2\2\u0166"+
"\u0167\7a\2\2\u0167\n\3\2\2\2\u0168\u0169\7a\2\2\u0169\u016a\7a\2\2\u016a"+
"\u016b\7f\2\2\u016b\u016c\7g\2\2\u016c\u016d\7e\2\2\u016d\u016e\7n\2\2"+
"\u016e\u016f\7u\2\2\u016f\u0170\7r\2\2\u0170\u0171\7g\2\2\u0171\u0172"+
"\7e\2\2\u0172\f\3\2\2\2\u0173\u0174\7a\2\2\u0174\u0175\7a\2\2\u0175\u0176"+
"\7d\2\2\u0176\u0177\7w\2\2\u0177\u0178\7k\2\2\u0178\u0179\7n\2\2\u0179"+
"\u017a\7v\2\2\u017a\u017b\7k\2\2\u017b\u017c\7p\2\2\u017c\u017d\7a\2\2"+
"\u017d\u017e\7x\2\2\u017e\u017f\7c\2\2\u017f\u0180\7a\2\2\u0180\u0181"+
"\7c\2\2\u0181\u0182\7t\2\2\u0182\u0183\7i\2\2\u0183\16\3\2\2\2\u0184\u0185"+
"\7a\2\2\u0185\u0186\7a\2\2\u0186\u0187\7v\2\2\u0187\u0188\7{\2\2\u0188"+
"\u0189\7r\2\2\u0189\u018a\7g\2\2\u018a\u018b\7q\2\2\u018b\u018c\7h\2\2"+
"\u018c\u018d\7a\2\2\u018d\u018e\7a\2\2\u018e\20\3\2\2\2\u018f\u0190\7"+
"a\2\2\u0190\u0191\7a\2\2\u0191\u0192\7c\2\2\u0192\u0193\7u\2\2\u0193\u0194"+
"\7o\2\2\u0194\22\3\2\2\2\u0195\u0196\7a\2\2\u0196\u0197\7a\2\2\u0197\u0198"+
"\7o\2\2\u0198\u0199\7\63\2\2\u0199\u019a\7\64\2\2\u019a\u019b\7:\2\2\u019b"+
"\u019c\7f\2\2\u019c\24\3\2\2\2\u019d\u019e\7a\2\2\u019e\u019f\7a\2\2\u019f"+
"\u01a0\7o\2\2\u01a0\u01a1\7\63\2\2\u01a1\u01a2\7\64\2\2\u01a2\u01a3\7"+
":\2\2\u01a3\u01a4\7k\2\2\u01a4\26\3\2\2\2\u01a5\u01a6\7a\2\2\u01a6\u01a7"+
"\7a\2\2\u01a7\u01a8\7c\2\2\u01a8\u01a9\7v\2\2\u01a9\u01aa\7v\2\2\u01aa"+
"\u01ab\7t\2\2\u01ab\u01ac\7k\2\2\u01ac\u01ad\7d\2\2\u01ad\u01ae\7w\2\2"+
"\u01ae\u01af\7v\2\2\u01af\u01b0\7g\2\2\u01b0\u01b1\7a\2\2\u01b1\u01b2"+
"\7a\2\2\u01b2\30\3\2\2\2\u01b3\u01b4\7a\2\2\u01b4\u01b5\7a\2\2\u01b5\u01b6"+
"\7k\2\2\u01b6\u01b7\7p\2\2\u01b7\u01b8\7n\2\2\u01b8\u01b9\7k\2\2\u01b9"+
"\u01ba\7p\2\2\u01ba\u01bb\7g\2\2\u01bb\u01bc\7a\2\2\u01bc\u01bd\7a\2\2"+
"\u01bd\32\3\2\2\2\u01be\u01bf\7a\2\2\u01bf\u01c0\7a\2\2\u01c0\u01c1\7"+
"o\2\2\u01c1\u01c2\7\63\2\2\u01c2\u01c3\7\64\2\2\u01c3\u01c4\7:\2\2\u01c4"+
"\34\3\2\2\2\u01c5\u01c6\7a\2\2\u01c6\u01c7\7a\2\2\u01c7\u01c8\7d\2\2\u01c8"+
"\u01c9\7w\2\2\u01c9\u01ca\7k\2\2\u01ca\u01cb\7n\2\2\u01cb\u01cc\7v\2\2"+
"\u01cc\u01cd\7k\2\2\u01cd\u01ce\7p\2\2\u01ce\u01cf\7a\2\2\u01cf\u01d0"+
"\7q\2\2\u01d0\u01d1\7h\2\2\u01d1\u01d2\7h\2\2\u01d2\u01d3\7u\2\2\u01d3"+
"\u01d4\7g\2\2\u01d4\u01d5\7v\2\2\u01d5\u01d6\7q\2\2\u01d6\u01d7\7h\2\2"+
"\u01d7\36\3\2\2\2\u01d8\u01d9\7c\2\2\u01d9\u01da\7w\2\2\u01da\u01db\7"+
"v\2\2\u01db\u01dc\7q\2\2\u01dc \3\2\2\2\u01dd\u01de\7d\2\2\u01de\u01df"+
"\7t\2\2\u01df\u01e0\7g\2\2\u01e0\u01e1\7c\2\2\u01e1\u01e2\7m\2\2\u01e2"+
"\"\3\2\2\2\u01e3\u01e4\7e\2\2\u01e4\u01e5\7c\2\2\u01e5\u01e6\7u\2\2\u01e6"+
"\u01e7\7g\2\2\u01e7$\3\2\2\2\u01e8\u01e9\7e\2\2\u01e9\u01ea\7j\2\2\u01ea"+
"\u01eb\7c\2\2\u01eb\u01ec\7t\2\2\u01ec&\3\2\2\2\u01ed\u01ee\7e\2\2\u01ee"+
"\u01ef\7q\2\2\u01ef\u01f0\7p\2\2\u01f0\u01f1\7u\2\2\u01f1\u01f2\7v\2\2"+
"\u01f2(\3\2\2\2\u01f3\u01f4\7e\2\2\u01f4\u01f5\7q\2\2\u01f5\u01f6\7p\2"+
"\2\u01f6\u01f7\7v\2\2\u01f7\u01f8\7k\2\2\u01f8\u01f9\7p\2\2\u01f9\u01fa"+
"\7w\2\2\u01fa\u01fb\7g\2\2\u01fb*\3\2\2\2\u01fc\u01fd\7f\2\2\u01fd\u01fe"+
"\7g\2\2\u01fe\u01ff\7h\2\2\u01ff\u0200\7c\2\2\u0200\u0201\7w\2\2\u0201"+
"\u0202\7n\2\2\u0202\u0203\7v\2\2\u0203,\3\2\2\2\u0204\u0205\7f\2\2\u0205"+
"\u0206\7q\2\2\u0206.\3\2\2\2\u0207\u0208\7f\2\2\u0208\u0209\7q\2\2\u0209"+
"\u020a\7w\2\2\u020a\u020b\7d\2\2\u020b\u020c\7n\2\2\u020c\u020d\7g\2\2"+
"\u020d\60\3\2\2\2\u020e\u020f\7g\2\2\u020f\u0210\7n\2\2\u0210\u0211\7"+
"u\2\2\u0211\u0212\7g\2\2\u0212\62\3\2\2\2\u0213\u0214\7g\2\2\u0214\u0215"+
"\7p\2\2\u0215\u0216\7w\2\2\u0216\u0217\7o\2\2\u0217\64\3\2\2\2\u0218\u0219"+
"\7g\2\2\u0219\u021a\7z\2\2\u021a\u021b\7v\2\2\u021b\u021c\7g\2\2\u021c"+
"\u021d\7t\2\2\u021d\u021e\7p\2\2\u021e\66\3\2\2\2\u021f\u0220\7h\2\2\u0220"+
"\u0221\7n\2\2\u0221\u0222\7q\2\2\u0222\u0223\7c\2\2\u0223\u0224\7v\2\2"+
"\u02248\3\2\2\2\u0225\u0226\7h\2\2\u0226\u0227\7q\2\2\u0227\u0228\7t\2"+
"\2\u0228:\3\2\2\2\u0229\u022a\7i\2\2\u022a\u022b\7q\2\2\u022b\u022c\7"+
"v\2\2\u022c\u022d\7q\2\2\u022d<\3\2\2\2\u022e\u022f\7k\2\2\u022f\u0230"+
"\7h\2\2\u0230>\3\2\2\2\u0231\u0232\7k\2\2\u0232\u0233\7p\2\2\u0233\u0234"+
"\7n\2\2\u0234\u0235\7k\2\2\u0235\u0236\7p\2\2\u0236\u0237\7g\2\2\u0237"+
"@\3\2\2\2\u0238\u0239\7k\2\2\u0239\u023a\7p\2\2\u023a\u023b\7v\2\2\u023b"+
"B\3\2\2\2\u023c\u023d\7n\2\2\u023d\u023e\7q\2\2\u023e\u023f\7p\2\2\u023f"+
"\u0240\7i\2\2\u0240D\3\2\2\2\u0241\u0242\7t\2\2\u0242\u0243\7g\2\2\u0243"+
"\u0244\7i\2\2\u0244\u0245\7k\2\2\u0245\u0246\7u\2\2\u0246\u0247\7v\2\2"+
"\u0247\u0248\7g\2\2\u0248\u0249\7t\2\2\u0249F\3\2\2\2\u024a\u024b\7t\2"+
"\2\u024b\u024c\7g\2\2\u024c\u024d\7u\2\2\u024d\u024e\7v\2\2\u024e\u024f"+
"\7t\2\2\u024f\u0250\7k\2\2\u0250\u0251\7e\2\2\u0251\u0252\7v\2\2\u0252"+
"H\3\2\2\2\u0253\u0254\7t\2\2\u0254\u0255\7g\2\2\u0255\u0256\7v\2\2\u0256"+
"\u0257\7w\2\2\u0257\u0258\7t\2\2\u0258\u0259\7p\2\2\u0259J\3\2\2\2\u025a"+
"\u025b\7u\2\2\u025b\u025c\7j\2\2\u025c\u025d\7q\2\2\u025d\u025e\7t\2\2"+
"\u025e\u025f\7v\2\2\u025fL\3\2\2\2\u0260\u0261\7u\2\2\u0261\u0262\7k\2"+
"\2\u0262\u0263\7i\2\2\u0263\u0264\7p\2\2\u0264\u0265\7g\2\2\u0265\u0266"+
"\7f\2\2\u0266N\3\2\2\2\u0267\u0268\7u\2\2\u0268\u0269\7k\2\2\u0269\u026a"+
"\7|\2\2\u026a\u026b\7g\2\2\u026b\u026c\7q\2\2\u026c\u026d\7h\2\2\u026d"+
"P\3\2\2\2\u026e\u026f\7u\2\2\u026f\u0270\7v\2\2\u0270\u0271\7c\2\2\u0271"+
"\u0272\7v\2\2\u0272\u0273\7k\2\2\u0273\u0274\7e\2\2\u0274R\3\2\2\2\u0275"+
"\u0276\7u\2\2\u0276\u0277\7v\2\2\u0277\u0278\7t\2\2\u0278\u0279\7w\2\2"+
"\u0279\u027a\7e\2\2\u027a\u027b\7v\2\2\u027bT\3\2\2\2\u027c\u027d\7u\2"+
"\2\u027d\u027e\7y\2\2\u027e\u027f\7k\2\2\u027f\u0280\7v\2\2\u0280\u0281"+
"\7e\2\2\u0281\u0282\7j\2\2\u0282V\3\2\2\2\u0283\u0284\7v\2\2\u0284\u0285"+
"\7{\2\2\u0285\u0286\7r\2\2\u0286\u0287\7g\2\2\u0287\u0288\7f\2\2\u0288"+
"\u0289\7g\2\2\u0289\u028a\7h\2\2\u028aX\3\2\2\2\u028b\u028c\7w\2\2\u028c"+
"\u028d\7p\2\2\u028d\u028e\7k\2\2\u028e\u028f\7q\2\2\u028f\u0290\7p\2\2"+
"\u0290Z\3\2\2\2\u0291\u0292\7w\2\2\u0292\u0293\7p\2\2\u0293\u0294\7u\2"+
"\2\u0294\u0295\7k\2\2\u0295\u0296\7i\2\2\u0296\u0297\7p\2\2\u0297\u0298"+
"\7g\2\2\u0298\u0299\7f\2\2\u0299\\\3\2\2\2\u029a\u029b\7x\2\2\u029b\u029c"+
"\7q\2\2\u029c\u029d\7k\2\2\u029d\u029e\7f\2\2\u029e^\3\2\2\2\u029f\u02a0"+
"\7x\2\2\u02a0\u02a1\7q\2\2\u02a1\u02a2\7n\2\2\u02a2\u02a3\7c\2\2\u02a3"+
"\u02a4\7v\2\2\u02a4\u02a5\7k\2\2\u02a5\u02a6\7n\2\2\u02a6\u02a7\7g\2\2"+
"\u02a7`\3\2\2\2\u02a8\u02a9\7y\2\2\u02a9\u02aa\7j\2\2\u02aa\u02ab\7k\2"+
"\2\u02ab\u02ac\7n\2\2\u02ac\u02ad\7g\2\2\u02adb\3\2\2\2\u02ae\u02af\7"+
"a\2\2\u02af\u02b0\7C\2\2\u02b0\u02b1\7n\2\2\u02b1\u02b2\7k\2\2\u02b2\u02b3"+
"\7i\2\2\u02b3\u02b4\7p\2\2\u02b4\u02b5\7c\2\2\u02b5\u02b6\7u\2\2\u02b6"+
"d\3\2\2\2\u02b7\u02b8\7a\2\2\u02b8\u02b9\7C\2\2\u02b9\u02ba\7n\2\2\u02ba"+
"\u02bb\7k\2\2\u02bb\u02bc\7i\2\2\u02bc\u02bd\7p\2\2\u02bd\u02be\7q\2\2"+
"\u02be\u02bf\7h\2\2\u02bff\3\2\2\2\u02c0\u02c1\7a\2\2\u02c1\u02c2\7C\2"+
"\2\u02c2\u02c3\7v\2\2\u02c3\u02c4\7q\2\2\u02c4\u02c5\7o\2\2\u02c5\u02c6"+
"\7k\2\2\u02c6\u02c7\7e\2\2\u02c7h\3\2\2\2\u02c8\u02c9\7a\2\2\u02c9\u02ca"+
"\7D\2\2\u02ca\u02cb\7q\2\2\u02cb\u02cc\7q\2\2\u02cc\u02cd\7n\2\2\u02cd"+
"j\3\2\2\2\u02ce\u02cf\7a\2\2\u02cf\u02d0\7E\2\2\u02d0\u02d1\7q\2\2\u02d1"+
"\u02d2\7o\2\2\u02d2\u02d3\7r\2\2\u02d3\u02d4\7n\2\2\u02d4\u02d5\7g\2\2"+
"\u02d5\u02d6\7z\2\2\u02d6l\3\2\2\2\u02d7\u02d8\7a\2\2\u02d8\u02d9\7I\2"+
"\2\u02d9\u02da\7g\2\2\u02da\u02db\7p\2\2\u02db\u02dc\7g\2\2\u02dc\u02dd"+
"\7t\2\2\u02dd\u02de\7k\2\2\u02de\u02df\7e\2\2\u02dfn\3\2\2\2\u02e0\u02e1"+
"\7a\2\2\u02e1\u02e2\7K\2\2\u02e2\u02e3\7o\2\2\u02e3\u02e4\7c\2\2\u02e4"+
"\u02e5\7i\2\2\u02e5\u02e6\7k\2\2\u02e6\u02e7\7p\2\2\u02e7\u02e8\7c\2\2"+
"\u02e8\u02e9\7t\2\2\u02e9\u02ea\7{\2\2\u02eap\3\2\2\2\u02eb\u02ec\7a\2"+
"\2\u02ec\u02ed\7P\2\2\u02ed\u02ee\7q\2\2\u02ee\u02ef\7t\2\2\u02ef\u02f0"+
"\7g\2\2\u02f0\u02f1\7v\2\2\u02f1\u02f2\7w\2\2\u02f2\u02f3\7t\2\2\u02f3"+
"\u02f4\7p\2\2\u02f4r\3\2\2\2\u02f5\u02f6\7a\2\2\u02f6\u02f7\7U\2\2\u02f7"+
"\u02f8\7v\2\2\u02f8\u02f9\7c\2\2\u02f9\u02fa\7v\2\2\u02fa\u02fb\7k\2\2"+
"\u02fb\u02fc\7e\2\2\u02fc\u02fd\7a\2\2\u02fd\u02fe\7c\2\2\u02fe\u02ff"+
"\7u\2\2\u02ff\u0300\7u\2\2\u0300\u0301\7g\2\2\u0301\u0302\7t\2\2\u0302"+
"\u0303\7v\2\2\u0303t\3\2\2\2\u0304\u0305\7a\2\2\u0305\u0306\7V\2\2\u0306"+
"\u0307\7j\2\2\u0307\u0308\7t\2\2\u0308\u0309\7g\2\2\u0309\u030a\7c\2\2"+
"\u030a\u030b\7f\2\2\u030b\u030c\7a\2\2\u030c\u030d\7n\2\2\u030d\u030e"+
"\7q\2\2\u030e\u030f\7e\2\2\u030f\u0310\7c\2\2\u0310\u0311\7n\2\2\u0311"+
"v\3\2\2\2\u0312\u0313\7*\2\2\u0313x\3\2\2\2\u0314\u0315\7+\2\2\u0315z"+
"\3\2\2\2\u0316\u0317\7]\2\2\u0317|\3\2\2\2\u0318\u0319\7_\2\2\u0319~\3"+
"\2\2\2\u031a\u031b\7}\2\2\u031b\u0080\3\2\2\2\u031c\u031d\7\177\2\2\u031d"+
"\u0082\3\2\2\2\u031e\u031f\7>\2\2\u031f\u0084\3\2\2\2\u0320\u0321\7>\2"+
"\2\u0321\u0322\7?\2\2\u0322\u0086\3\2\2\2\u0323\u0324\7@\2\2\u0324\u0088"+
"\3\2\2\2\u0325\u0326\7@\2\2\u0326\u0327\7?\2\2\u0327\u008a\3\2\2\2\u0328"+
"\u0329\7>\2\2\u0329\u032a\7>\2\2\u032a\u008c\3\2\2\2\u032b\u032c\7@\2"+
"\2\u032c\u032d\7@\2\2\u032d\u008e\3\2\2\2\u032e\u032f\7-\2\2\u032f\u0090"+
"\3\2\2\2\u0330\u0331\7-\2\2\u0331\u0332\7-\2\2\u0332\u0092\3\2\2\2\u0333"+
"\u0334\7/\2\2\u0334\u0094\3\2\2\2\u0335\u0336\7/\2\2\u0336\u0337\7/\2"+
"\2\u0337\u0096\3\2\2\2\u0338\u0339\7,\2\2\u0339\u0098\3\2\2\2\u033a\u033b"+
"\7\61\2\2\u033b\u009a\3\2\2\2\u033c\u033d\7\'\2\2\u033d\u009c\3\2\2\2"+
"\u033e\u033f\7(\2\2\u033f\u009e\3\2\2\2\u0340\u0341\7~\2\2\u0341\u00a0"+
"\3\2\2\2\u0342\u0343\7(\2\2\u0343\u0344\7(\2\2\u0344\u00a2\3\2\2\2\u0345"+
"\u0346\7~\2\2\u0346\u0347\7~\2\2\u0347\u00a4\3\2\2\2\u0348\u0349\7`\2"+
"\2\u0349\u00a6\3\2\2\2\u034a\u034b\7#\2\2\u034b\u00a8\3\2\2\2\u034c\u034d"+
"\7\u0080\2\2\u034d\u00aa\3\2\2\2\u034e\u034f\7A\2\2\u034f\u00ac\3\2\2"+
"\2\u0350\u0351\7<\2\2\u0351\u00ae\3\2\2\2\u0352\u0353\7=\2\2\u0353\u00b0"+
"\3\2\2\2\u0354\u0355\7.\2\2\u0355\u00b2\3\2\2\2\u0356\u0357\7?\2\2\u0357"+
"\u00b4\3\2\2\2\u0358\u0359\7,\2\2\u0359\u035a\7?\2\2\u035a\u00b6\3\2\2"+
"\2\u035b\u035c\7\61\2\2\u035c\u035d\7?\2\2\u035d\u00b8\3\2\2\2\u035e\u035f"+
"\7\'\2\2\u035f\u0360\7?\2\2\u0360\u00ba\3\2\2\2\u0361\u0362\7-\2\2\u0362"+
"\u0363\7?\2\2\u0363\u00bc\3\2\2\2\u0364\u0365\7/\2\2\u0365\u0366\7?\2"+
"\2\u0366\u00be\3\2\2\2\u0367\u0368\7>\2\2\u0368\u0369\7>\2\2\u0369\u036a"+
"\7?\2\2\u036a\u00c0\3\2\2\2\u036b\u036c\7@\2\2\u036c\u036d\7@\2\2\u036d"+
"\u036e\7?\2\2\u036e\u00c2\3\2\2\2\u036f\u0370\7(\2\2\u0370\u0371\7?\2"+
"\2\u0371\u00c4\3\2\2\2\u0372\u0373\7`\2\2\u0373\u0374\7?\2\2\u0374\u00c6"+
"\3\2\2\2\u0375\u0376\7~\2\2\u0376\u0377\7?\2\2\u0377\u00c8\3\2\2\2\u0378"+
"\u0379\7?\2\2\u0379\u037a\7?\2\2\u037a\u00ca\3\2\2\2\u037b\u037c\7#\2"+
"\2\u037c\u037d\7?\2\2\u037d\u00cc\3\2\2\2\u037e\u037f\7/\2\2\u037f\u0380"+
"\7@\2\2\u0380\u00ce\3\2\2\2\u0381\u0382\7\60\2\2\u0382\u00d0\3\2\2\2\u0383"+
"\u0384\7\60\2\2\u0384\u0385\7\60\2\2\u0385\u0386\7\60\2\2\u0386\u00d2"+
"\3\2\2\2\u0387\u038c\5\u00d5k\2\u0388\u038b\5\u00d5k\2\u0389\u038b\5\u00d9"+
"m\2\u038a\u0388\3\2\2\2\u038a\u0389\3\2\2\2\u038b\u038e\3\2\2\2\u038c"+
"\u038a\3\2\2\2\u038c\u038d\3\2\2\2\u038d\u00d4\3\2\2\2\u038e\u038c\3\2"+
"\2\2\u038f\u0392\5\u00d7l\2\u0390\u0392\5\u00dbn\2\u0391\u038f\3\2\2\2"+
"\u0391\u0390\3\2\2\2\u0392\u00d6\3\2\2\2\u0393\u0394\t\2\2\2\u0394\u00d8"+
"\3\2\2\2\u0395\u0396\t\3\2\2\u0396\u00da\3\2\2\2\u0397\u0398\7^\2\2\u0398"+
"\u0399\7w\2\2\u0399\u039a\3\2\2\2\u039a\u03a2\5\u00ddo\2\u039b\u039c\7"+
"^\2\2\u039c\u039d\7W\2\2\u039d\u039e\3\2\2\2\u039e\u039f\5\u00ddo\2\u039f"+
"\u03a0\5\u00ddo\2\u03a0\u03a2\3\2\2\2\u03a1\u0397\3\2\2\2\u03a1\u039b"+
"\3\2\2\2\u03a2\u00dc\3\2\2\2\u03a3\u03a4\5\u00f1y\2\u03a4\u03a5\5\u00f1"+
"y\2\u03a5\u03a6\5\u00f1y\2\u03a6\u03a7\5\u00f1y\2\u03a7\u00de\3\2\2\2"+
"\u03a8\u03ac\5\u00e1q\2\u03a9\u03ac\5\u00fb~\2\u03aa\u03ac\5\u0111\u0089"+
"\2\u03ab\u03a8\3\2\2\2\u03ab\u03a9\3\2\2\2\u03ab\u03aa\3\2\2\2\u03ac\u00e0"+
"\3\2\2\2\u03ad\u03af\5\u00e5s\2\u03ae\u03b0\5\u00f3z\2\u03af\u03ae\3\2"+
"\2\2\u03af\u03b0\3\2\2\2\u03b0\u03bb\3\2\2\2\u03b1\u03b3\5\u00e7t\2\u03b2"+
"\u03b4\5\u00f3z\2\u03b3\u03b2\3\2\2\2\u03b3\u03b4\3\2\2\2\u03b4\u03bb"+
"\3\2\2\2\u03b5\u03b7\5\u00e9u\2\u03b6\u03b8\5\u00f3z\2\u03b7\u03b6\3\2"+
"\2\2\u03b7\u03b8\3\2\2\2\u03b8\u03bb\3\2\2\2\u03b9\u03bb\5\u00e3r\2\u03ba"+
"\u03ad\3\2\2\2\u03ba\u03b1\3\2\2\2\u03ba\u03b5\3\2\2\2\u03ba\u03b9\3\2"+
"\2\2\u03bb\u00e2\3\2\2\2\u03bc\u03bd\7\62\2\2\u03bd\u03bf\t\4\2\2\u03be"+
"\u03c0\t\5\2\2\u03bf\u03be\3\2\2\2\u03c0\u03c1\3\2\2\2\u03c1\u03bf\3\2"+
"\2\2\u03c1\u03c2\3\2\2\2\u03c2\u00e4\3\2\2\2\u03c3\u03c7\5\u00edw\2\u03c4"+
"\u03c6\5\u00d9m\2\u03c5\u03c4\3\2\2\2\u03c6\u03c9\3\2\2\2\u03c7\u03c5"+
"\3\2\2\2\u03c7\u03c8\3\2\2\2\u03c8\u00e6\3\2\2\2\u03c9\u03c7\3\2\2\2\u03ca"+
"\u03ce\7\62\2\2\u03cb\u03cd\5\u00efx\2\u03cc\u03cb\3\2\2\2\u03cd\u03d0"+
"\3\2\2\2\u03ce\u03cc\3\2\2\2\u03ce\u03cf\3\2\2\2\u03cf\u00e8\3\2\2\2\u03d0"+
"\u03ce\3\2\2\2\u03d1\u03d3\5\u00ebv\2\u03d2\u03d4\5\u00f1y\2\u03d3\u03d2"+
"\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d5\u03d3\3\2\2\2\u03d5\u03d6\3\2\2\2\u03d6"+
"\u00ea\3\2\2\2\u03d7\u03d8\7\62\2\2\u03d8\u03d9\t\6\2\2\u03d9\u00ec\3"+
"\2\2\2\u03da\u03db\t\7\2\2\u03db\u00ee\3\2\2\2\u03dc\u03dd\t\b\2\2\u03dd"+
"\u00f0\3\2\2\2\u03de\u03df\t\t\2\2\u03df\u00f2\3\2\2\2\u03e0\u03e2\5\u00f5"+
"{\2\u03e1\u03e3\5\u00f7|\2\u03e2\u03e1\3\2\2\2\u03e2\u03e3\3\2\2\2\u03e3"+
"\u03f0\3\2\2\2\u03e4\u03e5\5\u00f5{\2\u03e5\u03e6\5\u00f9}\2\u03e6\u03f0"+
"\3\2\2\2\u03e7\u03e9\5\u00f7|\2\u03e8\u03ea\5\u00f5{\2\u03e9\u03e8\3\2"+
"\2\2\u03e9\u03ea\3\2\2\2\u03ea\u03f0\3\2\2\2\u03eb\u03ed\5\u00f9}\2\u03ec"+
"\u03ee\5\u00f5{\2\u03ed\u03ec\3\2\2\2\u03ed\u03ee\3\2\2\2\u03ee\u03f0"+
"\3\2\2\2\u03ef\u03e0\3\2\2\2\u03ef\u03e4\3\2\2\2\u03ef\u03e7\3\2\2\2\u03ef"+
"\u03eb\3\2\2\2\u03f0\u00f4\3\2\2\2\u03f1\u03f2\t\n\2\2\u03f2\u00f6\3\2"+
"\2\2\u03f3\u03f4\t\13\2\2\u03f4\u00f8\3\2\2\2\u03f5\u03f6\7n\2\2\u03f6"+
"\u03fa\7n\2\2\u03f7\u03f8\7N\2\2\u03f8\u03fa\7N\2\2\u03f9\u03f5\3\2\2"+
"\2\u03f9\u03f7\3\2\2\2\u03fa\u00fa\3\2\2\2\u03fb\u03fe\5\u00fd\177\2\u03fc"+
"\u03fe\5\u00ff\u0080\2\u03fd\u03fb\3\2\2\2\u03fd\u03fc\3\2\2\2\u03fe\u00fc"+
"\3\2\2\2\u03ff\u0401\5\u0101\u0081\2\u0400\u0402\5\u0103\u0082\2\u0401"+
"\u0400\3\2\2\2\u0401\u0402\3\2\2\2\u0402\u0404\3\2\2\2\u0403\u0405\5\u010f"+
"\u0088\2\u0404\u0403\3\2\2\2\u0404\u0405\3\2\2\2\u0405\u040c\3\2\2\2\u0406"+
"\u0407\5\u0107\u0084\2\u0407\u0409\5\u0103\u0082\2\u0408\u040a\5\u010f"+
"\u0088\2\u0409\u0408\3\2\2\2\u0409\u040a\3\2\2\2\u040a\u040c\3\2\2\2\u040b"+
"\u03ff\3\2\2\2\u040b\u0406\3\2\2\2\u040c\u00fe\3\2\2\2\u040d\u040e\5\u00eb"+
"v\2\u040e\u040f\5\u0109\u0085\2\u040f\u0411\5\u010b\u0086\2\u0410\u0412"+
"\5\u010f\u0088\2\u0411\u0410\3\2\2\2\u0411\u0412\3\2\2\2\u0412\u041a\3"+
"\2\2\2\u0413\u0414\5\u00ebv\2\u0414\u0415\5\u010d\u0087\2\u0415\u0417"+
"\5\u010b\u0086\2\u0416\u0418\5\u010f\u0088\2\u0417\u0416\3\2\2\2\u0417"+
"\u0418\3\2\2\2\u0418\u041a\3\2\2\2\u0419\u040d\3\2\2\2\u0419\u0413\3\2"+
"\2\2\u041a\u0100\3\2\2\2\u041b\u041d\5\u0107\u0084\2\u041c\u041b\3\2\2"+
"\2\u041c\u041d\3\2\2\2\u041d\u041e\3\2\2\2\u041e\u041f\7\60\2\2\u041f"+
"\u0424\5\u0107\u0084\2\u0420\u0421\5\u0107\u0084\2\u0421\u0422\7\60\2"+
"\2\u0422\u0424\3\2\2\2\u0423\u041c\3\2\2\2\u0423\u0420\3\2\2\2\u0424\u0102"+
"\3\2\2\2\u0425\u0427\7g\2\2\u0426\u0428\5\u0105\u0083\2\u0427\u0426\3"+
"\2\2\2\u0427\u0428\3\2\2\2\u0428\u0429\3\2\2\2\u0429\u0430\5\u0107\u0084"+
"\2\u042a\u042c\7G\2\2\u042b\u042d\5\u0105\u0083\2\u042c\u042b\3\2\2\2"+
"\u042c\u042d\3\2\2\2\u042d\u042e\3\2\2\2\u042e\u0430\5\u0107\u0084\2\u042f"+
"\u0425\3\2\2\2\u042f\u042a\3\2\2\2\u0430\u0104\3\2\2\2\u0431\u0432\t\f"+
"\2\2\u0432\u0106\3\2\2\2\u0433\u0435\5\u00d9m\2\u0434\u0433\3\2\2\2\u0435"+
"\u0436\3\2\2\2\u0436\u0434\3\2\2\2\u0436\u0437\3\2\2\2\u0437\u0108\3\2"+
"\2\2\u0438\u043a\5\u010d\u0087\2\u0439\u0438\3\2\2\2\u0439\u043a\3\2\2"+
"\2\u043a\u043b\3\2\2\2\u043b\u043c\7\60\2\2\u043c\u0441\5\u010d\u0087"+
"\2\u043d\u043e\5\u010d\u0087\2\u043e\u043f\7\60\2\2\u043f\u0441\3\2\2"+
"\2\u0440\u0439\3\2\2\2\u0440\u043d\3\2\2\2\u0441\u010a\3\2\2\2\u0442\u0444"+
"\7r\2\2\u0443\u0445\5\u0105\u0083\2\u0444\u0443\3\2\2\2\u0444\u0445\3"+
"\2\2\2\u0445\u0446\3\2\2\2\u0446\u044d\5\u0107\u0084\2\u0447\u0449\7R"+
"\2\2\u0448\u044a\5\u0105\u0083\2\u0449\u0448\3\2\2\2\u0449\u044a\3\2\2"+
"\2\u044a\u044b\3\2\2\2\u044b\u044d\5\u0107\u0084\2\u044c\u0442\3\2\2\2"+
"\u044c\u0447\3\2\2\2\u044d\u010c\3\2\2\2\u044e\u0450\5\u00f1y\2\u044f"+
"\u044e\3\2\2\2\u0450\u0451\3\2\2\2\u0451\u044f\3\2\2\2\u0451\u0452\3\2"+
"\2\2\u0452\u010e\3\2\2\2\u0453\u0454\t\r\2\2\u0454\u0110\3\2\2\2\u0455"+
"\u0456\7)\2\2\u0456\u0457\5\u0113\u008a\2\u0457\u0458\7)\2\2\u0458\u046c"+
"\3\2\2\2\u0459\u045a\7N\2\2\u045a\u045b\7)\2\2\u045b\u045c\3\2\2\2\u045c"+
"\u045d\5\u0113\u008a\2\u045d\u045e\7)\2\2\u045e\u046c\3\2\2\2\u045f\u0460"+
"\7w\2\2\u0460\u0461\7)\2\2\u0461\u0462\3\2\2\2\u0462\u0463\5\u0113\u008a"+
"\2\u0463\u0464\7)\2\2\u0464\u046c\3\2\2\2\u0465\u0466\7W\2\2\u0466\u0467"+
"\7)\2\2\u0467\u0468\3\2\2\2\u0468\u0469\5\u0113\u008a\2\u0469\u046a\7"+
")\2\2\u046a\u046c\3\2\2\2\u046b\u0455\3\2\2\2\u046b\u0459\3\2\2\2\u046b"+
"\u045f\3\2\2\2\u046b\u0465\3\2\2\2\u046c\u0112\3\2\2\2\u046d\u046f\5\u0115"+
"\u008b\2\u046e\u046d\3\2\2\2\u046f\u0470\3\2\2\2\u0470\u046e\3\2\2\2\u0470"+
"\u0471\3\2\2\2\u0471\u0114\3\2\2\2\u0472\u0475\n\16\2\2\u0473\u0475\5"+
"\u0117\u008c\2\u0474\u0472\3\2\2\2\u0474\u0473\3\2\2\2\u0475\u0116\3\2"+
"\2\2\u0476\u047b\5\u0119\u008d\2\u0477\u047b\5\u011b\u008e\2\u0478\u047b"+
"\5\u011d\u008f\2\u0479\u047b\5\u00dbn\2\u047a\u0476\3\2\2\2\u047a\u0477"+
"\3\2\2\2\u047a\u0478\3\2\2\2\u047a\u0479\3\2\2\2\u047b\u0118\3\2\2\2\u047c"+
"\u047d\7^\2\2\u047d\u047e\t\17\2\2\u047e\u011a\3\2\2\2\u047f\u0480\7^"+
"\2\2\u0480\u048b\5\u00efx\2\u0481\u0482\7^\2\2\u0482\u0483\5\u00efx\2"+
"\u0483\u0484\5\u00efx\2\u0484\u048b\3\2\2\2\u0485\u0486\7^\2\2\u0486\u0487"+
"\5\u00efx\2\u0487\u0488\5\u00efx\2\u0488\u0489\5\u00efx\2\u0489\u048b"+
"\3\2\2\2\u048a\u047f\3\2\2\2\u048a\u0481\3\2\2\2\u048a\u0485\3\2\2\2\u048b"+
"\u011c\3\2\2\2\u048c\u048d\7^\2\2\u048d\u048e\7z\2\2\u048e\u0490\3\2\2"+
"\2\u048f\u0491\5\u00f1y\2\u0490\u048f\3\2\2\2\u0491\u0492\3\2\2\2\u0492"+
"\u0490\3\2\2\2\u0492\u0493\3\2\2\2\u0493\u011e\3\2\2\2\u0494\u0496\5\u0121"+
"\u0091\2\u0495\u0494\3\2\2\2\u0495\u0496\3\2\2\2\u0496\u0497\3\2\2\2\u0497"+
"\u0499\7$\2\2\u0498\u049a\5\u0123\u0092\2\u0499\u0498\3\2\2\2\u0499\u049a"+
"\3\2\2\2\u049a\u049b\3\2\2\2\u049b\u049c\7$\2\2\u049c\u0120\3\2\2\2\u049d"+
"\u049e\7w\2\2\u049e\u04a1\7:\2\2\u049f\u04a1\t\20\2\2\u04a0\u049d\3\2"+
"\2\2\u04a0\u049f\3\2\2\2\u04a1\u0122\3\2\2\2\u04a2\u04a4\5\u0125\u0093"+
"\2\u04a3\u04a2\3\2\2\2\u04a4\u04a5\3\2\2\2\u04a5\u04a3\3\2\2\2\u04a5\u04a6"+
"\3\2\2\2\u04a6\u0124\3\2\2\2\u04a7\u04af\n\21\2\2\u04a8\u04af\5\u0117"+
"\u008c\2\u04a9\u04aa\7^\2\2\u04aa\u04af\7\f\2\2\u04ab\u04ac\7^\2\2\u04ac"+
"\u04ad\7\17\2\2\u04ad\u04af\7\f\2\2\u04ae\u04a7\3\2\2\2\u04ae\u04a8\3"+
"\2\2\2\u04ae\u04a9\3\2\2\2\u04ae\u04ab\3\2\2\2\u04af\u0126\3\2\2\2\u04b0"+
"\u04b2\7%\2\2\u04b1\u04b3\5\u0131\u0099\2\u04b2\u04b1\3\2\2\2\u04b2\u04b3"+
"\3\2\2\2\u04b3\u04b4\3\2\2\2\u04b4\u04b5\7f\2\2\u04b5\u04b6\7g\2\2\u04b6"+
"\u04b7\7h\2\2\u04b7\u04b8\7k\2\2\u04b8\u04b9\7p\2\2\u04b9\u04ba\7g\2\2"+
"\u04ba\u04be\3\2\2\2\u04bb\u04bd\n\22\2\2\u04bc\u04bb\3\2\2\2\u04bd\u04c0"+
"\3\2\2\2\u04be\u04bc\3\2\2\2\u04be\u04bf\3\2\2\2\u04bf\u04c1\3\2\2\2\u04c0"+
"\u04be\3\2\2\2\u04c1\u04c2\b\u0094\2\2\u04c2\u0128\3\2\2\2\u04c3\u04c4"+
"\7c\2\2\u04c4\u04c5\7u\2\2\u04c5\u04c6\7o\2\2\u04c6\u04ca\3\2\2\2\u04c7"+
"\u04c9\n\23\2\2\u04c8\u04c7\3\2\2\2\u04c9\u04cc\3\2\2\2\u04ca\u04c8\3"+
"\2\2\2\u04ca\u04cb\3\2\2\2\u04cb\u04cd\3\2\2\2\u04cc\u04ca\3\2\2\2\u04cd"+
"\u04d1\7}\2\2\u04ce\u04d0\n\24\2\2\u04cf\u04ce\3\2\2\2\u04d0\u04d3\3\2"+
"\2\2\u04d1\u04cf\3\2\2\2\u04d1\u04d2\3\2\2\2\u04d2\u04d4\3\2\2\2\u04d3"+
"\u04d1\3\2\2\2\u04d4\u04d5\7\177\2\2\u04d5\u04d6\3\2\2\2\u04d6\u04d7\b"+
"\u0095\2\2\u04d7\u012a\3\2\2\2\u04d8\u04d9\7%\2\2\u04d9\u04da\7n\2\2\u04da"+
"\u04db\7k\2\2\u04db\u04dc\7p\2\2\u04dc\u04dd\7g\2\2\u04dd\u04e1\3\2\2"+
"\2\u04de\u04e0\5\u0131\u0099\2\u04df\u04de\3\2\2\2\u04e0\u04e3\3\2\2\2"+
"\u04e1\u04df\3\2\2\2\u04e1\u04e2\3\2\2\2\u04e2\u04e7\3\2\2\2\u04e3\u04e1"+
"\3\2\2\2\u04e4\u04e6\n\25\2\2\u04e5\u04e4\3\2\2\2\u04e6\u04e9\3\2\2\2"+
"\u04e7\u04e5\3\2\2\2\u04e7\u04e8\3\2\2\2\u04e8\u04ea\3\2\2\2\u04e9\u04e7"+
"\3\2\2\2\u04ea\u04eb\b\u0096\2\2\u04eb\u012c\3\2\2\2\u04ec\u04ee\7%\2"+
"\2\u04ed\u04ef\5\u0131\u0099\2\u04ee\u04ed\3\2\2\2\u04ee\u04ef\3\2\2\2"+
"\u04ef\u04f0\3\2\2\2\u04f0\u04f2\5\u00e5s\2\u04f1\u04f3\5\u0131\u0099"+
"\2\u04f2\u04f1\3\2\2\2\u04f2\u04f3\3\2\2\2\u04f3\u04f4\3\2\2\2\u04f4\u04f8"+
"\5\u011f\u0090\2\u04f5\u04f7\n\25\2\2\u04f6\u04f5\3\2\2\2\u04f7\u04fa"+
"\3\2\2\2\u04f8\u04f6\3\2\2\2\u04f8\u04f9\3\2\2\2\u04f9\u04fb\3\2\2\2\u04fa"+
"\u04f8\3\2\2\2\u04fb\u04fc\b\u0097\2\2\u04fc\u012e\3\2\2\2\u04fd\u04ff"+
"\7%\2\2\u04fe\u0500\5\u0131\u0099\2\u04ff\u04fe\3\2\2\2\u04ff\u0500\3"+
"\2\2\2\u0500\u0501\3\2\2\2\u0501\u0502\7r\2\2\u0502\u0503\7t\2\2\u0503"+
"\u0504\7c\2\2\u0504\u0505\7i\2\2\u0505\u0506\7o\2\2\u0506\u0507\7c\2\2"+
"\u0507\u0508\3\2\2\2\u0508\u050c\5\u0131\u0099\2\u0509\u050b\n\25\2\2"+
"\u050a\u0509\3\2\2\2\u050b\u050e\3\2\2\2\u050c\u050a\3\2\2\2\u050c\u050d"+
"\3\2\2\2\u050d\u050f\3\2\2\2\u050e\u050c\3\2\2\2\u050f\u0510\b\u0098\2"+
"\2\u0510\u0130\3\2\2\2\u0511\u0513\t\26\2\2\u0512\u0511\3\2\2\2\u0513"+
"\u0514\3\2\2\2\u0514\u0512\3\2\2\2\u0514\u0515\3\2\2\2\u0515\u0516\3\2"+
"\2\2\u0516\u0517\b\u0099\2\2\u0517\u0132\3\2\2\2\u0518\u051a\7\17\2\2"+
"\u0519\u051b\7\f\2\2\u051a\u0519\3\2\2\2\u051a\u051b\3\2\2\2\u051b\u051e"+
"\3\2\2\2\u051c\u051e\7\f\2\2\u051d\u0518\3\2\2\2\u051d\u051c\3\2\2\2\u051e"+
"\u051f\3\2\2\2\u051f\u0520\b\u009a\2\2\u0520\u0134\3\2\2\2\u0521\u0522"+
"\7\61\2\2\u0522\u0523\7,\2\2\u0523\u0527\3\2\2\2\u0524\u0526\13\2\2\2"+
"\u0525\u0524\3\2\2\2\u0526\u0529\3\2\2\2\u0527\u0528\3\2\2\2\u0527\u0525"+
"\3\2\2\2\u0528\u052a\3\2\2\2\u0529\u0527\3\2\2\2\u052a\u052b\7,\2\2\u052b"+
"\u052c\7\61\2\2\u052c\u052d\3\2\2\2\u052d\u052e\b\u009b\2\2\u052e\u0136"+
"\3\2\2\2\u052f\u0530\7\61\2\2\u0530\u0531\7\61\2\2\u0531\u0535\3\2\2\2"+
"\u0532\u0534\n\25\2\2\u0533\u0532\3\2\2\2\u0534\u0537\3\2\2\2\u0535\u0533"+
"\3\2\2\2\u0535\u0536\3\2\2\2\u0536\u0538\3\2\2\2\u0537\u0535\3\2\2\2\u0538"+
"\u0539\b\u009c\2\2\u0539\u0138\3\2\2\2\u053a\u053e\7%\2\2\u053b\u053d"+
"\n\25\2\2\u053c\u053b\3\2\2\2\u053d\u0540\3\2\2\2\u053e\u053c\3\2\2\2"+
"\u053e\u053f\3\2\2\2\u053f\u0541\3\2\2\2\u0540\u053e\3\2\2\2\u0541\u0542"+
"\b\u009d\2\2\u0542\u013a\3\2\2\2E\2\u038a\u038c\u0391\u03a1\u03ab\u03af"+
"\u03b3\u03b7\u03ba\u03c1\u03c7\u03ce\u03d5\u03e2\u03e9\u03ed\u03ef\u03f9"+
"\u03fd\u0401\u0404\u0409\u040b\u0411\u0417\u0419\u041c\u0423\u0427\u042c"+
"\u042f\u0436\u0439\u0440\u0444\u0449\u044c\u0451\u046b\u0470\u0474\u047a"+
"\u048a\u0492\u0495\u0499\u04a0\u04a5\u04ae\u04b2\u04be\u04ca\u04d1\u04e1"+
"\u04e7\u04ee\u04f2\u04f8\u04ff\u050c\u0514\u051a\u051d\u0527\u0535\u053e"+
"\3\b\2\2";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}

View File

@ -0,0 +1,221 @@
Enum=25
AndAssign=97
Or=79
Break=16
LeftShift=69
GreaterEqual=68
Bool=52
ThreadLocal=58
LeftBracket=61
RightBrace=64
Equal=100
Directives=117
Restrict=35
Sizeof=39
StarAssign=90
Arrow=102
NotEqual=101
LessEqual=66
Dot=103
RightParen=60
XorAssign=98
Float=27
Switch=42
Typedef=43
StringLiteral=107
If=30
Minus=73
MinusAssign=94
LeftParen=59
Newline=114
Union=44
Case=17
Extern=26
Complex=53
RightShiftAssign=96
Comma=88
Star=75
Char=18
ComplexDefine=108
T__3=11
T__2=12
T__1=13
Question=85
T__0=14
OrOr=81
LineAfterPreprocessing=110
Inline=31
Default=21
Alignas=49
Div=76
RightBracket=62
Register=34
Else=24
Assign=89
AndAnd=80
LineDirective=111
LineComment=116
RightShift=70
LeftShiftAssign=95
Identifier=105
T__11=3
T__12=2
T__13=1
Void=46
Plus=71
AsmBlock=109
StaticAssert=57
Less=65
Short=37
T__10=4
BlockComment=115
T__9=5
Goto=29
T__8=6
T__7=7
T__6=8
T__5=9
Signed=38
T__4=10
Const=19
Imaginary=55
For=28
Semi=87
OrAssign=99
Do=22
Double=23
Not=83
And=78
Long=33
Static=40
Caret=82
Alignof=50
Generic=54
Constant=106
Atomic=51
Continue=20
Int=32
MinusMinus=74
Whitespace=113
Struct=41
Auto=15
PlusPlus=72
PlusAssign=93
Colon=86
DivAssign=91
LeftBrace=63
Return=36
Mod=77
Ellipsis=104
Tilde=84
PragmaDirective=112
While=48
Noreturn=56
Volatile=47
ModAssign=92
Unsigned=45
Greater=67
'-'=73
'typedef'=43
'else'=24
'_Static_assert'=57
'%'=77
'__builtin_offsetof'=14
'>'=67
'--'=74
'=='=100
'_Complex'=53
'...'=104
'case'=17
'->'=102
'.'=103
'_Thread_local'=58
'__m128'=13
'&'=78
'__inline__'=12
'double'=23
'break'=16
'short'=37
'<='=66
'enum'=25
'?'=85
'__attribute__'=11
'if'=30
'_Generic'=54
'goto'=29
'<<'=69
'inline'=31
'||'=81
'return'=36
'__m128i'=10
'_Imaginary'=55
'unsigned'=45
'continue'=20
'/'=76
'_Bool'=52
'__m128d'=9
'signed'=38
'__asm'=8
'register'=34
'sizeof'=39
'static'=40
'__typeof__'=7
'++'=72
'__builtin_va_arg'=6
'const'=19
'volatile'=47
'/='=91
'__declspec'=5
'do'=22
'('=59
'|='=99
'for'=28
'void'=46
'{'=63
'float'=27
'+='=93
')'=60
'__asm__'=4
'auto'=15
'!'=83
'|'=79
'['=61
':'=86
'_Atomic'=51
'*'=75
'switch'=42
'_Alignas'=49
'_Alignof'=50
'__stdcall'=3
'}'=64
';'=87
'>>='=96
'&='=97
'*='=90
'struct'=41
'+'=71
'~'=84
']'=62
'<'=65
'_Noreturn'=56
'>='=68
'long'=33
','=88
'-='=94
'union'=44
'int'=32
'__volatile__'=2
'^'=82
'<<='=95
'='=89
'restrict'=35
'>>'=70
'&&'=80
'^='=98
'while'=48
'!='=101
'__extension__'=1
'char'=18
'%='=92
'extern'=26
'default'=21

View File

@ -0,0 +1,852 @@
// Generated from C.g4 by ANTLR 4.4
package it.unitn.repoman.core.lang.parsers.c;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.tree.ParseTreeListener;
/**
* This interface defines a complete listener for a parse tree produced by
* {@link CParser}.
*/
public interface CListener extends ParseTreeListener {
/**
* Enter a parse tree produced by {@link CParser#structDeclarationList}.
* @param ctx the parse tree
*/
void enterStructDeclarationList(@NotNull CParser.StructDeclarationListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#structDeclarationList}.
* @param ctx the parse tree
*/
void exitStructDeclarationList(@NotNull CParser.StructDeclarationListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#unaryOperator}.
* @param ctx the parse tree
*/
void enterUnaryOperator(@NotNull CParser.UnaryOperatorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#unaryOperator}.
* @param ctx the parse tree
*/
void exitUnaryOperator(@NotNull CParser.UnaryOperatorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#structOrUnionSpecifier}.
* @param ctx the parse tree
*/
void enterStructOrUnionSpecifier(@NotNull CParser.StructOrUnionSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#structOrUnionSpecifier}.
* @param ctx the parse tree
*/
void exitStructOrUnionSpecifier(@NotNull CParser.StructOrUnionSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#assignmentOperator}.
* @param ctx the parse tree
*/
void enterAssignmentOperator(@NotNull CParser.AssignmentOperatorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#assignmentOperator}.
* @param ctx the parse tree
*/
void exitAssignmentOperator(@NotNull CParser.AssignmentOperatorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#compoundStatement}.
* @param ctx the parse tree
*/
void enterCompoundStatement(@NotNull CParser.CompoundStatementContext ctx);
/**
* Exit a parse tree produced by {@link CParser#compoundStatement}.
* @param ctx the parse tree
*/
void exitCompoundStatement(@NotNull CParser.CompoundStatementContext ctx);
/**
* Enter a parse tree produced by {@link CParser#declarationSpecifier}.
* @param ctx the parse tree
*/
void enterDeclarationSpecifier(@NotNull CParser.DeclarationSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#declarationSpecifier}.
* @param ctx the parse tree
*/
void exitDeclarationSpecifier(@NotNull CParser.DeclarationSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#declarationList}.
* @param ctx the parse tree
*/
void enterDeclarationList(@NotNull CParser.DeclarationListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#declarationList}.
* @param ctx the parse tree
*/
void exitDeclarationList(@NotNull CParser.DeclarationListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#directDeclarator}.
* @param ctx the parse tree
*/
void enterDirectDeclarator(@NotNull CParser.DirectDeclaratorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#directDeclarator}.
* @param ctx the parse tree
*/
void exitDirectDeclarator(@NotNull CParser.DirectDeclaratorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#parameterTypeList}.
* @param ctx the parse tree
*/
void enterParameterTypeList(@NotNull CParser.ParameterTypeListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#parameterTypeList}.
* @param ctx the parse tree
*/
void exitParameterTypeList(@NotNull CParser.ParameterTypeListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#designatorList}.
* @param ctx the parse tree
*/
void enterDesignatorList(@NotNull CParser.DesignatorListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#designatorList}.
* @param ctx the parse tree
*/
void exitDesignatorList(@NotNull CParser.DesignatorListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#functionSpecifier}.
* @param ctx the parse tree
*/
void enterFunctionSpecifier(@NotNull CParser.FunctionSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#functionSpecifier}.
* @param ctx the parse tree
*/
void exitFunctionSpecifier(@NotNull CParser.FunctionSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#staticAssertDeclaration}.
* @param ctx the parse tree
*/
void enterStaticAssertDeclaration(@NotNull CParser.StaticAssertDeclarationContext ctx);
/**
* Exit a parse tree produced by {@link CParser#staticAssertDeclaration}.
* @param ctx the parse tree
*/
void exitStaticAssertDeclaration(@NotNull CParser.StaticAssertDeclarationContext ctx);
/**
* Enter a parse tree produced by {@link CParser#castExpression}.
* @param ctx the parse tree
*/
void enterCastExpression(@NotNull CParser.CastExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#castExpression}.
* @param ctx the parse tree
*/
void exitCastExpression(@NotNull CParser.CastExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#initDeclarator}.
* @param ctx the parse tree
*/
void enterInitDeclarator(@NotNull CParser.InitDeclaratorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#initDeclarator}.
* @param ctx the parse tree
*/
void exitInitDeclarator(@NotNull CParser.InitDeclaratorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#declarationSpecifiers2}.
* @param ctx the parse tree
*/
void enterDeclarationSpecifiers2(@NotNull CParser.DeclarationSpecifiers2Context ctx);
/**
* Exit a parse tree produced by {@link CParser#declarationSpecifiers2}.
* @param ctx the parse tree
*/
void exitDeclarationSpecifiers2(@NotNull CParser.DeclarationSpecifiers2Context ctx);
/**
* Enter a parse tree produced by {@link CParser#externalDeclaration}.
* @param ctx the parse tree
*/
void enterExternalDeclaration(@NotNull CParser.ExternalDeclarationContext ctx);
/**
* Exit a parse tree produced by {@link CParser#externalDeclaration}.
* @param ctx the parse tree
*/
void exitExternalDeclaration(@NotNull CParser.ExternalDeclarationContext ctx);
/**
* Enter a parse tree produced by {@link CParser#logicalAndExpression}.
* @param ctx the parse tree
*/
void enterLogicalAndExpression(@NotNull CParser.LogicalAndExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#logicalAndExpression}.
* @param ctx the parse tree
*/
void exitLogicalAndExpression(@NotNull CParser.LogicalAndExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#gccAttributeList}.
* @param ctx the parse tree
*/
void enterGccAttributeList(@NotNull CParser.GccAttributeListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#gccAttributeList}.
* @param ctx the parse tree
*/
void exitGccAttributeList(@NotNull CParser.GccAttributeListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#expressionStatement}.
* @param ctx the parse tree
*/
void enterExpressionStatement(@NotNull CParser.ExpressionStatementContext ctx);
/**
* Exit a parse tree produced by {@link CParser#expressionStatement}.
* @param ctx the parse tree
*/
void exitExpressionStatement(@NotNull CParser.ExpressionStatementContext ctx);
/**
* Enter a parse tree produced by {@link CParser#unaryExpression}.
* @param ctx the parse tree
*/
void enterUnaryExpression(@NotNull CParser.UnaryExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#unaryExpression}.
* @param ctx the parse tree
*/
void exitUnaryExpression(@NotNull CParser.UnaryExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#typedefName}.
* @param ctx the parse tree
*/
void enterTypedefName(@NotNull CParser.TypedefNameContext ctx);
/**
* Exit a parse tree produced by {@link CParser#typedefName}.
* @param ctx the parse tree
*/
void exitTypedefName(@NotNull CParser.TypedefNameContext ctx);
/**
* Enter a parse tree produced by {@link CParser#pointer}.
* @param ctx the parse tree
*/
void enterPointer(@NotNull CParser.PointerContext ctx);
/**
* Exit a parse tree produced by {@link CParser#pointer}.
* @param ctx the parse tree
*/
void exitPointer(@NotNull CParser.PointerContext ctx);
/**
* Enter a parse tree produced by {@link CParser#identifierList}.
* @param ctx the parse tree
*/
void enterIdentifierList(@NotNull CParser.IdentifierListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#identifierList}.
* @param ctx the parse tree
*/
void exitIdentifierList(@NotNull CParser.IdentifierListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#shiftExpression}.
* @param ctx the parse tree
*/
void enterShiftExpression(@NotNull CParser.ShiftExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#shiftExpression}.
* @param ctx the parse tree
*/
void exitShiftExpression(@NotNull CParser.ShiftExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#atomicTypeSpecifier}.
* @param ctx the parse tree
*/
void enterAtomicTypeSpecifier(@NotNull CParser.AtomicTypeSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#atomicTypeSpecifier}.
* @param ctx the parse tree
*/
void exitAtomicTypeSpecifier(@NotNull CParser.AtomicTypeSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#iterationStatement}.
* @param ctx the parse tree
*/
void enterIterationStatement(@NotNull CParser.IterationStatementContext ctx);
/**
* Exit a parse tree produced by {@link CParser#iterationStatement}.
* @param ctx the parse tree
*/
void exitIterationStatement(@NotNull CParser.IterationStatementContext ctx);
/**
* Enter a parse tree produced by {@link CParser#enumerationConstant}.
* @param ctx the parse tree
*/
void enterEnumerationConstant(@NotNull CParser.EnumerationConstantContext ctx);
/**
* Exit a parse tree produced by {@link CParser#enumerationConstant}.
* @param ctx the parse tree
*/
void exitEnumerationConstant(@NotNull CParser.EnumerationConstantContext ctx);
/**
* Enter a parse tree produced by {@link CParser#inclusiveOrExpression}.
* @param ctx the parse tree
*/
void enterInclusiveOrExpression(@NotNull CParser.InclusiveOrExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#inclusiveOrExpression}.
* @param ctx the parse tree
*/
void exitInclusiveOrExpression(@NotNull CParser.InclusiveOrExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#assignmentExpression}.
* @param ctx the parse tree
*/
void enterAssignmentExpression(@NotNull CParser.AssignmentExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#assignmentExpression}.
* @param ctx the parse tree
*/
void exitAssignmentExpression(@NotNull CParser.AssignmentExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#directAbstractDeclarator}.
* @param ctx the parse tree
*/
void enterDirectAbstractDeclarator(@NotNull CParser.DirectAbstractDeclaratorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#directAbstractDeclarator}.
* @param ctx the parse tree
*/
void exitDirectAbstractDeclarator(@NotNull CParser.DirectAbstractDeclaratorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#declarationSpecifiers}.
* @param ctx the parse tree
*/
void enterDeclarationSpecifiers(@NotNull CParser.DeclarationSpecifiersContext ctx);
/**
* Exit a parse tree produced by {@link CParser#declarationSpecifiers}.
* @param ctx the parse tree
*/
void exitDeclarationSpecifiers(@NotNull CParser.DeclarationSpecifiersContext ctx);
/**
* Enter a parse tree produced by {@link CParser#alignmentSpecifier}.
* @param ctx the parse tree
*/
void enterAlignmentSpecifier(@NotNull CParser.AlignmentSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#alignmentSpecifier}.
* @param ctx the parse tree
*/
void exitAlignmentSpecifier(@NotNull CParser.AlignmentSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#structOrUnion}.
* @param ctx the parse tree
*/
void enterStructOrUnion(@NotNull CParser.StructOrUnionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#structOrUnion}.
* @param ctx the parse tree
*/
void exitStructOrUnion(@NotNull CParser.StructOrUnionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#translationUnit}.
* @param ctx the parse tree
*/
void enterTranslationUnit(@NotNull CParser.TranslationUnitContext ctx);
/**
* Exit a parse tree produced by {@link CParser#translationUnit}.
* @param ctx the parse tree
*/
void exitTranslationUnit(@NotNull CParser.TranslationUnitContext ctx);
/**
* Enter a parse tree produced by {@link CParser#compilationUnit}.
* @param ctx the parse tree
*/
void enterCompilationUnit(@NotNull CParser.CompilationUnitContext ctx);
/**
* Exit a parse tree produced by {@link CParser#compilationUnit}.
* @param ctx the parse tree
*/
void exitCompilationUnit(@NotNull CParser.CompilationUnitContext ctx);
/**
* Enter a parse tree produced by {@link CParser#blockItemList}.
* @param ctx the parse tree
*/
void enterBlockItemList(@NotNull CParser.BlockItemListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#blockItemList}.
* @param ctx the parse tree
*/
void exitBlockItemList(@NotNull CParser.BlockItemListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#exclusiveOrExpression}.
* @param ctx the parse tree
*/
void enterExclusiveOrExpression(@NotNull CParser.ExclusiveOrExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#exclusiveOrExpression}.
* @param ctx the parse tree
*/
void exitExclusiveOrExpression(@NotNull CParser.ExclusiveOrExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#genericAssocList}.
* @param ctx the parse tree
*/
void enterGenericAssocList(@NotNull CParser.GenericAssocListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#genericAssocList}.
* @param ctx the parse tree
*/
void exitGenericAssocList(@NotNull CParser.GenericAssocListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#equalityExpression}.
* @param ctx the parse tree
*/
void enterEqualityExpression(@NotNull CParser.EqualityExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#equalityExpression}.
* @param ctx the parse tree
*/
void exitEqualityExpression(@NotNull CParser.EqualityExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#parameterList}.
* @param ctx the parse tree
*/
void enterParameterList(@NotNull CParser.ParameterListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#parameterList}.
* @param ctx the parse tree
*/
void exitParameterList(@NotNull CParser.ParameterListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#parameterDeclaration}.
* @param ctx the parse tree
*/
void enterParameterDeclaration(@NotNull CParser.ParameterDeclarationContext ctx);
/**
* Exit a parse tree produced by {@link CParser#parameterDeclaration}.
* @param ctx the parse tree
*/
void exitParameterDeclaration(@NotNull CParser.ParameterDeclarationContext ctx);
/**
* Enter a parse tree produced by {@link CParser#designation}.
* @param ctx the parse tree
*/
void enterDesignation(@NotNull CParser.DesignationContext ctx);
/**
* Exit a parse tree produced by {@link CParser#designation}.
* @param ctx the parse tree
*/
void exitDesignation(@NotNull CParser.DesignationContext ctx);
/**
* Enter a parse tree produced by {@link CParser#blockItem}.
* @param ctx the parse tree
*/
void enterBlockItem(@NotNull CParser.BlockItemContext ctx);
/**
* Exit a parse tree produced by {@link CParser#blockItem}.
* @param ctx the parse tree
*/
void exitBlockItem(@NotNull CParser.BlockItemContext ctx);
/**
* Enter a parse tree produced by {@link CParser#initDeclaratorList}.
* @param ctx the parse tree
*/
void enterInitDeclaratorList(@NotNull CParser.InitDeclaratorListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#initDeclaratorList}.
* @param ctx the parse tree
*/
void exitInitDeclaratorList(@NotNull CParser.InitDeclaratorListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#structDeclaration}.
* @param ctx the parse tree
*/
void enterStructDeclaration(@NotNull CParser.StructDeclarationContext ctx);
/**
* Exit a parse tree produced by {@link CParser#structDeclaration}.
* @param ctx the parse tree
*/
void exitStructDeclaration(@NotNull CParser.StructDeclarationContext ctx);
/**
* Enter a parse tree produced by {@link CParser#structDeclaratorList}.
* @param ctx the parse tree
*/
void enterStructDeclaratorList(@NotNull CParser.StructDeclaratorListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#structDeclaratorList}.
* @param ctx the parse tree
*/
void exitStructDeclaratorList(@NotNull CParser.StructDeclaratorListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#additiveExpression}.
* @param ctx the parse tree
*/
void enterAdditiveExpression(@NotNull CParser.AdditiveExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#additiveExpression}.
* @param ctx the parse tree
*/
void exitAdditiveExpression(@NotNull CParser.AdditiveExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#relationalExpression}.
* @param ctx the parse tree
*/
void enterRelationalExpression(@NotNull CParser.RelationalExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#relationalExpression}.
* @param ctx the parse tree
*/
void exitRelationalExpression(@NotNull CParser.RelationalExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#enumeratorList}.
* @param ctx the parse tree
*/
void enterEnumeratorList(@NotNull CParser.EnumeratorListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#enumeratorList}.
* @param ctx the parse tree
*/
void exitEnumeratorList(@NotNull CParser.EnumeratorListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#typeName}.
* @param ctx the parse tree
*/
void enterTypeName(@NotNull CParser.TypeNameContext ctx);
/**
* Exit a parse tree produced by {@link CParser#typeName}.
* @param ctx the parse tree
*/
void exitTypeName(@NotNull CParser.TypeNameContext ctx);
/**
* Enter a parse tree produced by {@link CParser#selectionStatement}.
* @param ctx the parse tree
*/
void enterSelectionStatement(@NotNull CParser.SelectionStatementContext ctx);
/**
* Exit a parse tree produced by {@link CParser#selectionStatement}.
* @param ctx the parse tree
*/
void exitSelectionStatement(@NotNull CParser.SelectionStatementContext ctx);
/**
* Enter a parse tree produced by {@link CParser#genericSelection}.
* @param ctx the parse tree
*/
void enterGenericSelection(@NotNull CParser.GenericSelectionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#genericSelection}.
* @param ctx the parse tree
*/
void exitGenericSelection(@NotNull CParser.GenericSelectionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#storageClassSpecifier}.
* @param ctx the parse tree
*/
void enterStorageClassSpecifier(@NotNull CParser.StorageClassSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#storageClassSpecifier}.
* @param ctx the parse tree
*/
void exitStorageClassSpecifier(@NotNull CParser.StorageClassSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#nestedParenthesesBlock}.
* @param ctx the parse tree
*/
void enterNestedParenthesesBlock(@NotNull CParser.NestedParenthesesBlockContext ctx);
/**
* Exit a parse tree produced by {@link CParser#nestedParenthesesBlock}.
* @param ctx the parse tree
*/
void exitNestedParenthesesBlock(@NotNull CParser.NestedParenthesesBlockContext ctx);
/**
* Enter a parse tree produced by {@link CParser#designator}.
* @param ctx the parse tree
*/
void enterDesignator(@NotNull CParser.DesignatorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#designator}.
* @param ctx the parse tree
*/
void exitDesignator(@NotNull CParser.DesignatorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#andExpression}.
* @param ctx the parse tree
*/
void enterAndExpression(@NotNull CParser.AndExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#andExpression}.
* @param ctx the parse tree
*/
void exitAndExpression(@NotNull CParser.AndExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#labeledStatement}.
* @param ctx the parse tree
*/
void enterLabeledStatement(@NotNull CParser.LabeledStatementContext ctx);
/**
* Exit a parse tree produced by {@link CParser#labeledStatement}.
* @param ctx the parse tree
*/
void exitLabeledStatement(@NotNull CParser.LabeledStatementContext ctx);
/**
* Enter a parse tree produced by {@link CParser#argumentExpressionList}.
* @param ctx the parse tree
*/
void enterArgumentExpressionList(@NotNull CParser.ArgumentExpressionListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#argumentExpressionList}.
* @param ctx the parse tree
*/
void exitArgumentExpressionList(@NotNull CParser.ArgumentExpressionListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#gccAttributeSpecifier}.
* @param ctx the parse tree
*/
void enterGccAttributeSpecifier(@NotNull CParser.GccAttributeSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#gccAttributeSpecifier}.
* @param ctx the parse tree
*/
void exitGccAttributeSpecifier(@NotNull CParser.GccAttributeSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#statement}.
* @param ctx the parse tree
*/
void enterStatement(@NotNull CParser.StatementContext ctx);
/**
* Exit a parse tree produced by {@link CParser#statement}.
* @param ctx the parse tree
*/
void exitStatement(@NotNull CParser.StatementContext ctx);
/**
* Enter a parse tree produced by {@link CParser#enumerator}.
* @param ctx the parse tree
*/
void enterEnumerator(@NotNull CParser.EnumeratorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#enumerator}.
* @param ctx the parse tree
*/
void exitEnumerator(@NotNull CParser.EnumeratorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#abstractDeclarator}.
* @param ctx the parse tree
*/
void enterAbstractDeclarator(@NotNull CParser.AbstractDeclaratorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#abstractDeclarator}.
* @param ctx the parse tree
*/
void exitAbstractDeclarator(@NotNull CParser.AbstractDeclaratorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#postfixExpression}.
* @param ctx the parse tree
*/
void enterPostfixExpression(@NotNull CParser.PostfixExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#postfixExpression}.
* @param ctx the parse tree
*/
void exitPostfixExpression(@NotNull CParser.PostfixExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#gccAttribute}.
* @param ctx the parse tree
*/
void enterGccAttribute(@NotNull CParser.GccAttributeContext ctx);
/**
* Exit a parse tree produced by {@link CParser#gccAttribute}.
* @param ctx the parse tree
*/
void exitGccAttribute(@NotNull CParser.GccAttributeContext ctx);
/**
* Enter a parse tree produced by {@link CParser#primaryExpression}.
* @param ctx the parse tree
*/
void enterPrimaryExpression(@NotNull CParser.PrimaryExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#primaryExpression}.
* @param ctx the parse tree
*/
void exitPrimaryExpression(@NotNull CParser.PrimaryExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#typeQualifierList}.
* @param ctx the parse tree
*/
void enterTypeQualifierList(@NotNull CParser.TypeQualifierListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#typeQualifierList}.
* @param ctx the parse tree
*/
void exitTypeQualifierList(@NotNull CParser.TypeQualifierListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#expression}.
* @param ctx the parse tree
*/
void enterExpression(@NotNull CParser.ExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#expression}.
* @param ctx the parse tree
*/
void exitExpression(@NotNull CParser.ExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#constantExpression}.
* @param ctx the parse tree
*/
void enterConstantExpression(@NotNull CParser.ConstantExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#constantExpression}.
* @param ctx the parse tree
*/
void exitConstantExpression(@NotNull CParser.ConstantExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#conditionalExpression}.
* @param ctx the parse tree
*/
void enterConditionalExpression(@NotNull CParser.ConditionalExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#conditionalExpression}.
* @param ctx the parse tree
*/
void exitConditionalExpression(@NotNull CParser.ConditionalExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#functionDefinition}.
* @param ctx the parse tree
*/
void enterFunctionDefinition(@NotNull CParser.FunctionDefinitionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#functionDefinition}.
* @param ctx the parse tree
*/
void exitFunctionDefinition(@NotNull CParser.FunctionDefinitionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#specifierQualifierList}.
* @param ctx the parse tree
*/
void enterSpecifierQualifierList(@NotNull CParser.SpecifierQualifierListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#specifierQualifierList}.
* @param ctx the parse tree
*/
void exitSpecifierQualifierList(@NotNull CParser.SpecifierQualifierListContext ctx);
/**
* Enter a parse tree produced by {@link CParser#gccDeclaratorExtension}.
* @param ctx the parse tree
*/
void enterGccDeclaratorExtension(@NotNull CParser.GccDeclaratorExtensionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#gccDeclaratorExtension}.
* @param ctx the parse tree
*/
void exitGccDeclaratorExtension(@NotNull CParser.GccDeclaratorExtensionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#typeSpecifier}.
* @param ctx the parse tree
*/
void enterTypeSpecifier(@NotNull CParser.TypeSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#typeSpecifier}.
* @param ctx the parse tree
*/
void exitTypeSpecifier(@NotNull CParser.TypeSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#multiplicativeExpression}.
* @param ctx the parse tree
*/
void enterMultiplicativeExpression(@NotNull CParser.MultiplicativeExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#multiplicativeExpression}.
* @param ctx the parse tree
*/
void exitMultiplicativeExpression(@NotNull CParser.MultiplicativeExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#logicalOrExpression}.
* @param ctx the parse tree
*/
void enterLogicalOrExpression(@NotNull CParser.LogicalOrExpressionContext ctx);
/**
* Exit a parse tree produced by {@link CParser#logicalOrExpression}.
* @param ctx the parse tree
*/
void exitLogicalOrExpression(@NotNull CParser.LogicalOrExpressionContext ctx);
/**
* Enter a parse tree produced by {@link CParser#declaration}.
* @param ctx the parse tree
*/
void enterDeclaration(@NotNull CParser.DeclarationContext ctx);
/**
* Exit a parse tree produced by {@link CParser#declaration}.
* @param ctx the parse tree
*/
void exitDeclaration(@NotNull CParser.DeclarationContext ctx);
/**
* Enter a parse tree produced by {@link CParser#declarator}.
* @param ctx the parse tree
*/
void enterDeclarator(@NotNull CParser.DeclaratorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#declarator}.
* @param ctx the parse tree
*/
void exitDeclarator(@NotNull CParser.DeclaratorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#initializer}.
* @param ctx the parse tree
*/
void enterInitializer(@NotNull CParser.InitializerContext ctx);
/**
* Exit a parse tree produced by {@link CParser#initializer}.
* @param ctx the parse tree
*/
void exitInitializer(@NotNull CParser.InitializerContext ctx);
/**
* Enter a parse tree produced by {@link CParser#genericAssociation}.
* @param ctx the parse tree
*/
void enterGenericAssociation(@NotNull CParser.GenericAssociationContext ctx);
/**
* Exit a parse tree produced by {@link CParser#genericAssociation}.
* @param ctx the parse tree
*/
void exitGenericAssociation(@NotNull CParser.GenericAssociationContext ctx);
/**
* Enter a parse tree produced by {@link CParser#structDeclarator}.
* @param ctx the parse tree
*/
void enterStructDeclarator(@NotNull CParser.StructDeclaratorContext ctx);
/**
* Exit a parse tree produced by {@link CParser#structDeclarator}.
* @param ctx the parse tree
*/
void exitStructDeclarator(@NotNull CParser.StructDeclaratorContext ctx);
/**
* Enter a parse tree produced by {@link CParser#enumSpecifier}.
* @param ctx the parse tree
*/
void enterEnumSpecifier(@NotNull CParser.EnumSpecifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#enumSpecifier}.
* @param ctx the parse tree
*/
void exitEnumSpecifier(@NotNull CParser.EnumSpecifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#jumpStatement}.
* @param ctx the parse tree
*/
void enterJumpStatement(@NotNull CParser.JumpStatementContext ctx);
/**
* Exit a parse tree produced by {@link CParser#jumpStatement}.
* @param ctx the parse tree
*/
void exitJumpStatement(@NotNull CParser.JumpStatementContext ctx);
/**
* Enter a parse tree produced by {@link CParser#typeQualifier}.
* @param ctx the parse tree
*/
void enterTypeQualifier(@NotNull CParser.TypeQualifierContext ctx);
/**
* Exit a parse tree produced by {@link CParser#typeQualifier}.
* @param ctx the parse tree
*/
void exitTypeQualifier(@NotNull CParser.TypeQualifierContext ctx);
/**
* Enter a parse tree produced by {@link CParser#initializerList}.
* @param ctx the parse tree
*/
void enterInitializerList(@NotNull CParser.InitializerListContext ctx);
/**
* Exit a parse tree produced by {@link CParser#initializerList}.
* @param ctx the parse tree
*/
void exitInitializerList(@NotNull CParser.InitializerListContext ctx);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,201 @@
ABSTRACT=1
ASSERT=2
BOOLEAN=3
BREAK=4
BYTE=5
CASE=6
CATCH=7
CHAR=8
CLASS=9
CONST=10
CONTINUE=11
DEFAULT=12
DO=13
DOUBLE=14
ELSE=15
ENUM=16
EXTENDS=17
FINAL=18
FINALLY=19
FLOAT=20
FOR=21
IF=22
GOTO=23
IMPLEMENTS=24
IMPORT=25
INSTANCEOF=26
INT=27
INTERFACE=28
LONG=29
NATIVE=30
NEW=31
PACKAGE=32
PRIVATE=33
PROTECTED=34
PUBLIC=35
RETURN=36
SHORT=37
STATIC=38
STRICTFP=39
SUPER=40
SWITCH=41
SYNCHRONIZED=42
THIS=43
THROW=44
THROWS=45
TRANSIENT=46
TRY=47
VOID=48
VOLATILE=49
WHILE=50
IntegerLiteral=51
FloatingPointLiteral=52
BooleanLiteral=53
CharacterLiteral=54
StringLiteral=55
NullLiteral=56
LPAREN=57
RPAREN=58
LBRACE=59
RBRACE=60
LBRACK=61
RBRACK=62
SEMI=63
COMMA=64
DOT=65
ASSIGN=66
GT=67
LT=68
BANG=69
TILDE=70
QUESTION=71
COLON=72
EQUAL=73
LE=74
GE=75
NOTEQUAL=76
AND=77
OR=78
INC=79
DEC=80
ADD=81
SUB=82
MUL=83
DIV=84
BITAND=85
BITOR=86
CARET=87
MOD=88
ADD_ASSIGN=89
SUB_ASSIGN=90
MUL_ASSIGN=91
DIV_ASSIGN=92
AND_ASSIGN=93
OR_ASSIGN=94
XOR_ASSIGN=95
MOD_ASSIGN=96
LSHIFT_ASSIGN=97
RSHIFT_ASSIGN=98
URSHIFT_ASSIGN=99
Identifier=100
AT=101
ELLIPSIS=102
WS=103
COMMENT=104
LINE_COMMENT=105
'abstract'=1
'assert'=2
'boolean'=3
'break'=4
'byte'=5
'case'=6
'catch'=7
'char'=8
'class'=9
'const'=10
'continue'=11
'default'=12
'do'=13
'double'=14
'else'=15
'enum'=16
'extends'=17
'final'=18
'finally'=19
'float'=20
'for'=21
'if'=22
'goto'=23
'implements'=24
'import'=25
'instanceof'=26
'int'=27
'interface'=28
'long'=29
'native'=30
'new'=31
'package'=32
'private'=33
'protected'=34
'public'=35
'return'=36
'short'=37
'static'=38
'strictfp'=39
'super'=40
'switch'=41
'synchronized'=42
'this'=43
'throw'=44
'throws'=45
'transient'=46
'try'=47
'void'=48
'volatile'=49
'while'=50
'null'=56
'('=57
')'=58
'{'=59
'}'=60
'['=61
']'=62
';'=63
','=64
'.'=65
'='=66
'>'=67
'<'=68
'!'=69
'~'=70
'?'=71
':'=72
'=='=73
'<='=74
'>='=75
'!='=76
'&&'=77
'||'=78
'++'=79
'--'=80
'+'=81
'-'=82
'*'=83
'/'=84
'&'=85
'|'=86
'^'=87
'%'=88
'+='=89
'-='=90
'*='=91
'/='=92
'&='=93
'|='=94
'^='=95
'%='=96
'<<='=97
'>>='=98
'>>>='=99
'@'=101
'...'=102

View File

@ -0,0 +1,545 @@
// Generated from Java.g4 by ANTLR 4.7
package it.unitn.repoman.core.lang.parsers.java;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class JavaLexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
ABSTRACT=1, ASSERT=2, BOOLEAN=3, BREAK=4, BYTE=5, CASE=6, CATCH=7, CHAR=8,
CLASS=9, CONST=10, CONTINUE=11, DEFAULT=12, DO=13, DOUBLE=14, ELSE=15,
ENUM=16, EXTENDS=17, FINAL=18, FINALLY=19, FLOAT=20, FOR=21, IF=22, GOTO=23,
IMPLEMENTS=24, IMPORT=25, INSTANCEOF=26, INT=27, INTERFACE=28, LONG=29,
NATIVE=30, NEW=31, PACKAGE=32, PRIVATE=33, PROTECTED=34, PUBLIC=35, RETURN=36,
SHORT=37, STATIC=38, STRICTFP=39, SUPER=40, SWITCH=41, SYNCHRONIZED=42,
THIS=43, THROW=44, THROWS=45, TRANSIENT=46, TRY=47, VOID=48, VOLATILE=49,
WHILE=50, IntegerLiteral=51, FloatingPointLiteral=52, BooleanLiteral=53,
CharacterLiteral=54, StringLiteral=55, NullLiteral=56, LPAREN=57, RPAREN=58,
LBRACE=59, RBRACE=60, LBRACK=61, RBRACK=62, SEMI=63, COMMA=64, DOT=65,
ASSIGN=66, GT=67, LT=68, BANG=69, TILDE=70, QUESTION=71, COLON=72, EQUAL=73,
LE=74, GE=75, NOTEQUAL=76, AND=77, OR=78, INC=79, DEC=80, ADD=81, SUB=82,
MUL=83, DIV=84, BITAND=85, BITOR=86, CARET=87, MOD=88, ADD_ASSIGN=89,
SUB_ASSIGN=90, MUL_ASSIGN=91, DIV_ASSIGN=92, AND_ASSIGN=93, OR_ASSIGN=94,
XOR_ASSIGN=95, MOD_ASSIGN=96, LSHIFT_ASSIGN=97, RSHIFT_ASSIGN=98, URSHIFT_ASSIGN=99,
Identifier=100, AT=101, ELLIPSIS=102, WS=103, COMMENT=104, LINE_COMMENT=105;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
public static String[] modeNames = {
"DEFAULT_MODE"
};
public static final String[] ruleNames = {
"ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", "CATCH", "CHAR",
"CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", "ELSE", "ENUM",
"EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "IF", "GOTO", "IMPLEMENTS",
"IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", "NATIVE", "NEW", "PACKAGE",
"PRIVATE", "PROTECTED", "PUBLIC", "RETURN", "SHORT", "STATIC", "STRICTFP",
"SUPER", "SWITCH", "SYNCHRONIZED", "THIS", "THROW", "THROWS", "TRANSIENT",
"TRY", "VOID", "VOLATILE", "WHILE", "IntegerLiteral", "DecimalIntegerLiteral",
"HexIntegerLiteral", "OctalIntegerLiteral", "BinaryIntegerLiteral", "IntegerTypeSuffix",
"DecimalNumeral", "Digits", "Digit", "NonZeroDigit", "DigitOrUnderscore",
"Underscores", "HexNumeral", "HexDigits", "HexDigit", "HexDigitOrUnderscore",
"OctalNumeral", "OctalDigits", "OctalDigit", "OctalDigitOrUnderscore",
"BinaryNumeral", "BinaryDigits", "BinaryDigit", "BinaryDigitOrUnderscore",
"FloatingPointLiteral", "DecimalFloatingPointLiteral", "ExponentPart",
"ExponentIndicator", "SignedInteger", "Sign", "FloatTypeSuffix", "HexadecimalFloatingPointLiteral",
"HexSignificand", "BinaryExponent", "BinaryExponentIndicator", "BooleanLiteral",
"CharacterLiteral", "SingleCharacter", "StringLiteral", "StringCharacters",
"StringCharacter", "EscapeSequence", "OctalEscape", "UnicodeEscape", "ZeroToThree",
"NullLiteral", "LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK",
"SEMI", "COMMA", "DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION",
"COLON", "EQUAL", "LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", "ADD",
"SUB", "MUL", "DIV", "BITAND", "BITOR", "CARET", "MOD", "ADD_ASSIGN",
"SUB_ASSIGN", "MUL_ASSIGN", "DIV_ASSIGN", "AND_ASSIGN", "OR_ASSIGN", "XOR_ASSIGN",
"MOD_ASSIGN", "LSHIFT_ASSIGN", "RSHIFT_ASSIGN", "URSHIFT_ASSIGN", "Identifier",
"JavaLetter", "JavaLetterOrDigit", "AT", "ELLIPSIS", "WS", "COMMENT",
"LINE_COMMENT"
};
private static final String[] _LITERAL_NAMES = {
null, "'abstract'", "'assert'", "'boolean'", "'break'", "'byte'", "'case'",
"'catch'", "'char'", "'class'", "'const'", "'continue'", "'default'",
"'do'", "'double'", "'else'", "'enum'", "'extends'", "'final'", "'finally'",
"'float'", "'for'", "'if'", "'goto'", "'implements'", "'import'", "'instanceof'",
"'int'", "'interface'", "'long'", "'native'", "'new'", "'package'", "'private'",
"'protected'", "'public'", "'return'", "'short'", "'static'", "'strictfp'",
"'super'", "'switch'", "'synchronized'", "'this'", "'throw'", "'throws'",
"'transient'", "'try'", "'void'", "'volatile'", "'while'", null, null,
null, null, null, "'null'", "'('", "')'", "'{'", "'}'", "'['", "']'",
"';'", "','", "'.'", "'='", "'>'", "'<'", "'!'", "'~'", "'?'", "':'",
"'=='", "'<='", "'>='", "'!='", "'&&'", "'||'", "'++'", "'--'", "'+'",
"'-'", "'*'", "'/'", "'&'", "'|'", "'^'", "'%'", "'+='", "'-='", "'*='",
"'/='", "'&='", "'|='", "'^='", "'%='", "'<<='", "'>>='", "'>>>='", null,
"'@'", "'...'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, "ABSTRACT", "ASSERT", "BOOLEAN", "BREAK", "BYTE", "CASE", "CATCH",
"CHAR", "CLASS", "CONST", "CONTINUE", "DEFAULT", "DO", "DOUBLE", "ELSE",
"ENUM", "EXTENDS", "FINAL", "FINALLY", "FLOAT", "FOR", "IF", "GOTO", "IMPLEMENTS",
"IMPORT", "INSTANCEOF", "INT", "INTERFACE", "LONG", "NATIVE", "NEW", "PACKAGE",
"PRIVATE", "PROTECTED", "PUBLIC", "RETURN", "SHORT", "STATIC", "STRICTFP",
"SUPER", "SWITCH", "SYNCHRONIZED", "THIS", "THROW", "THROWS", "TRANSIENT",
"TRY", "VOID", "VOLATILE", "WHILE", "IntegerLiteral", "FloatingPointLiteral",
"BooleanLiteral", "CharacterLiteral", "StringLiteral", "NullLiteral",
"LPAREN", "RPAREN", "LBRACE", "RBRACE", "LBRACK", "RBRACK", "SEMI", "COMMA",
"DOT", "ASSIGN", "GT", "LT", "BANG", "TILDE", "QUESTION", "COLON", "EQUAL",
"LE", "GE", "NOTEQUAL", "AND", "OR", "INC", "DEC", "ADD", "SUB", "MUL",
"DIV", "BITAND", "BITOR", "CARET", "MOD", "ADD_ASSIGN", "SUB_ASSIGN",
"MUL_ASSIGN", "DIV_ASSIGN", "AND_ASSIGN", "OR_ASSIGN", "XOR_ASSIGN", "MOD_ASSIGN",
"LSHIFT_ASSIGN", "RSHIFT_ASSIGN", "URSHIFT_ASSIGN", "Identifier", "AT",
"ELLIPSIS", "WS", "COMMENT", "LINE_COMMENT"
};
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
/**
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated
public static final String[] tokenNames;
static {
tokenNames = new String[_SYMBOLIC_NAMES.length];
for (int i = 0; i < tokenNames.length; i++) {
tokenNames[i] = VOCABULARY.getLiteralName(i);
if (tokenNames[i] == null) {
tokenNames[i] = VOCABULARY.getSymbolicName(i);
}
if (tokenNames[i] == null) {
tokenNames[i] = "<INVALID>";
}
}
}
@Override
@Deprecated
public String[] getTokenNames() {
return tokenNames;
}
@Override
public Vocabulary getVocabulary() {
return VOCABULARY;
}
public JavaLexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "Java.g4"; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String getSerializedATN() { return _serializedATN; }
@Override
public String[] getChannelNames() { return channelNames; }
@Override
public String[] getModeNames() { return modeNames; }
@Override
public ATN getATN() { return _ATN; }
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2k\u042a\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+
",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+
"\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t="+
"\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+
"\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+
"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
"`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k\t"+
"k\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv\4"+
"w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\4\177\t\177\4\u0080\t\u0080"+
"\4\u0081\t\u0081\4\u0082\t\u0082\4\u0083\t\u0083\4\u0084\t\u0084\4\u0085"+
"\t\u0085\4\u0086\t\u0086\4\u0087\t\u0087\4\u0088\t\u0088\4\u0089\t\u0089"+
"\4\u008a\t\u008a\4\u008b\t\u008b\4\u008c\t\u008c\4\u008d\t\u008d\4\u008e"+
"\t\u008e\4\u008f\t\u008f\4\u0090\t\u0090\4\u0091\t\u0091\4\u0092\t\u0092"+
"\4\u0093\t\u0093\4\u0094\t\u0094\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3"+
"\3\3\3\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5"+
"\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3"+
"\b\3\b\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13"+
"\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r"+
"\3\r\3\r\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3"+
"\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3"+
"\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3"+
"\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\27\3\27\3"+
"\27\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3"+
"\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3"+
"\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3"+
"\35\3\35\3\35\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3"+
"\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3!\3!\3!\3!\3!\3!\3!\3!\3\"\3\"\3"+
"\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3"+
"$\3$\3%\3%\3%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3\'\3"+
"\'\3(\3(\3(\3(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3*\3*\3*\3*\3*\3*\3*\3"+
"+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3,\3,\3,\3,\3,\3-\3-\3-\3-\3-\3"+
"-\3.\3.\3.\3.\3.\3.\3.\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3\60\3\60\3\60\3"+
"\60\3\61\3\61\3\61\3\61\3\61\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3"+
"\62\3\63\3\63\3\63\3\63\3\63\3\63\3\64\3\64\3\64\3\64\5\64\u0281\n\64"+
"\3\65\3\65\5\65\u0285\n\65\3\66\3\66\5\66\u0289\n\66\3\67\3\67\5\67\u028d"+
"\n\67\38\38\58\u0291\n8\39\39\3:\3:\3:\5:\u0298\n:\3:\3:\3:\5:\u029d\n"+
":\5:\u029f\n:\3;\3;\7;\u02a3\n;\f;\16;\u02a6\13;\3;\5;\u02a9\n;\3<\3<"+
"\5<\u02ad\n<\3=\3=\3>\3>\5>\u02b3\n>\3?\6?\u02b6\n?\r?\16?\u02b7\3@\3"+
"@\3@\3@\3A\3A\7A\u02c0\nA\fA\16A\u02c3\13A\3A\5A\u02c6\nA\3B\3B\3C\3C"+
"\5C\u02cc\nC\3D\3D\5D\u02d0\nD\3D\3D\3E\3E\7E\u02d6\nE\fE\16E\u02d9\13"+
"E\3E\5E\u02dc\nE\3F\3F\3G\3G\5G\u02e2\nG\3H\3H\3H\3H\3I\3I\7I\u02ea\n"+
"I\fI\16I\u02ed\13I\3I\5I\u02f0\nI\3J\3J\3K\3K\5K\u02f6\nK\3L\3L\5L\u02fa"+
"\nL\3M\3M\3M\5M\u02ff\nM\3M\5M\u0302\nM\3M\5M\u0305\nM\3M\3M\3M\5M\u030a"+
"\nM\3M\5M\u030d\nM\3M\3M\3M\5M\u0312\nM\3M\3M\3M\5M\u0317\nM\3N\3N\3N"+
"\3O\3O\3P\5P\u031f\nP\3P\3P\3Q\3Q\3R\3R\3S\3S\3S\5S\u032a\nS\3T\3T\5T"+
"\u032e\nT\3T\3T\3T\5T\u0333\nT\3T\3T\5T\u0337\nT\3U\3U\3U\3V\3V\3W\3W"+
"\3W\3W\3W\3W\3W\3W\3W\5W\u0347\nW\3X\3X\3X\3X\3X\3X\3X\3X\5X\u0351\nX"+
"\3Y\3Y\3Z\3Z\5Z\u0357\nZ\3Z\3Z\3[\6[\u035c\n[\r[\16[\u035d\3\\\3\\\5\\"+
"\u0362\n\\\3]\3]\3]\3]\5]\u0368\n]\3^\3^\3^\3^\3^\3^\3^\3^\3^\3^\3^\5"+
"^\u0375\n^\3_\3_\3_\3_\3_\3_\3_\3`\3`\3a\3a\3a\3a\3a\3b\3b\3c\3c\3d\3"+
"d\3e\3e\3f\3f\3g\3g\3h\3h\3i\3i\3j\3j\3k\3k\3l\3l\3m\3m\3n\3n\3o\3o\3"+
"p\3p\3q\3q\3r\3r\3r\3s\3s\3s\3t\3t\3t\3u\3u\3u\3v\3v\3v\3w\3w\3w\3x\3"+
"x\3x\3y\3y\3y\3z\3z\3{\3{\3|\3|\3}\3}\3~\3~\3\177\3\177\3\u0080\3\u0080"+
"\3\u0081\3\u0081\3\u0082\3\u0082\3\u0082\3\u0083\3\u0083\3\u0083\3\u0084"+
"\3\u0084\3\u0084\3\u0085\3\u0085\3\u0085\3\u0086\3\u0086\3\u0086\3\u0087"+
"\3\u0087\3\u0087\3\u0088\3\u0088\3\u0088\3\u0089\3\u0089\3\u0089\3\u008a"+
"\3\u008a\3\u008a\3\u008a\3\u008b\3\u008b\3\u008b\3\u008b\3\u008c\3\u008c"+
"\3\u008c\3\u008c\3\u008c\3\u008d\3\u008d\7\u008d\u03f4\n\u008d\f\u008d"+
"\16\u008d\u03f7\13\u008d\3\u008e\3\u008e\3\u008e\3\u008e\5\u008e\u03fd"+
"\n\u008e\3\u008f\3\u008f\3\u008f\3\u008f\5\u008f\u0403\n\u008f\3\u0090"+
"\3\u0090\3\u0091\3\u0091\3\u0091\3\u0091\3\u0092\6\u0092\u040c\n\u0092"+
"\r\u0092\16\u0092\u040d\3\u0092\3\u0092\3\u0093\3\u0093\3\u0093\3\u0093"+
"\7\u0093\u0416\n\u0093\f\u0093\16\u0093\u0419\13\u0093\3\u0093\3\u0093"+
"\3\u0093\3\u0093\3\u0093\3\u0094\3\u0094\3\u0094\3\u0094\7\u0094\u0424"+
"\n\u0094\f\u0094\16\u0094\u0427\13\u0094\3\u0094\3\u0094\3\u0417\2\u0095"+
"\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20"+
"\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37"+
"= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\2k\2m\2o\2"+
"q\2s\2u\2w\2y\2{\2}\2\177\2\u0081\2\u0083\2\u0085\2\u0087\2\u0089\2\u008b"+
"\2\u008d\2\u008f\2\u0091\2\u0093\2\u0095\2\u0097\66\u0099\2\u009b\2\u009d"+
"\2\u009f\2\u00a1\2\u00a3\2\u00a5\2\u00a7\2\u00a9\2\u00ab\2\u00ad\67\u00af"+
"8\u00b1\2\u00b39\u00b5\2\u00b7\2\u00b9\2\u00bb\2\u00bd\2\u00bf\2\u00c1"+
":\u00c3;\u00c5<\u00c7=\u00c9>\u00cb?\u00cd@\u00cfA\u00d1B\u00d3C\u00d5"+
"D\u00d7E\u00d9F\u00dbG\u00ddH\u00dfI\u00e1J\u00e3K\u00e5L\u00e7M\u00e9"+
"N\u00ebO\u00edP\u00efQ\u00f1R\u00f3S\u00f5T\u00f7U\u00f9V\u00fbW\u00fd"+
"X\u00ffY\u0101Z\u0103[\u0105\\\u0107]\u0109^\u010b_\u010d`\u010fa\u0111"+
"b\u0113c\u0115d\u0117e\u0119f\u011b\2\u011d\2\u011fg\u0121h\u0123i\u0125"+
"j\u0127k\3\2\30\4\2NNnn\3\2\63;\4\2ZZzz\5\2\62;CHch\3\2\629\4\2DDdd\3"+
"\2\62\63\4\2GGgg\4\2--//\6\2FFHHffhh\4\2RRrr\6\2\f\f\17\17))^^\4\2$$^"+
"^\n\2$$))^^ddhhppttvv\3\2\62\65\6\2&&C\\aac|\4\2\2\u0081\ud802\udc01\3"+
"\2\ud802\udc01\3\2\udc02\ue001\7\2&&\62;C\\aac|\5\2\13\f\16\17\"\"\4\2"+
"\f\f\17\17\2\u0438\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13"+
"\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2"+
"\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2"+
"!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3"+
"\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2"+
"\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E"+
"\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2"+
"\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2"+
"\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2\u0097\3\2\2"+
"\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b3\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3"+
"\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2"+
"\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5"+
"\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2"+
"\2\2\u00df\3\2\2\2\2\u00e1\3\2\2\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2\2\2\u00e7"+
"\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2\2\2\u00ef\3\2\2"+
"\2\2\u00f1\3\2\2\2\2\u00f3\3\2\2\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9"+
"\3\2\2\2\2\u00fb\3\2\2\2\2\u00fd\3\2\2\2\2\u00ff\3\2\2\2\2\u0101\3\2\2"+
"\2\2\u0103\3\2\2\2\2\u0105\3\2\2\2\2\u0107\3\2\2\2\2\u0109\3\2\2\2\2\u010b"+
"\3\2\2\2\2\u010d\3\2\2\2\2\u010f\3\2\2\2\2\u0111\3\2\2\2\2\u0113\3\2\2"+
"\2\2\u0115\3\2\2\2\2\u0117\3\2\2\2\2\u0119\3\2\2\2\2\u011f\3\2\2\2\2\u0121"+
"\3\2\2\2\2\u0123\3\2\2\2\2\u0125\3\2\2\2\2\u0127\3\2\2\2\3\u0129\3\2\2"+
"\2\5\u0132\3\2\2\2\7\u0139\3\2\2\2\t\u0141\3\2\2\2\13\u0147\3\2\2\2\r"+
"\u014c\3\2\2\2\17\u0151\3\2\2\2\21\u0157\3\2\2\2\23\u015c\3\2\2\2\25\u0162"+
"\3\2\2\2\27\u0168\3\2\2\2\31\u0171\3\2\2\2\33\u0179\3\2\2\2\35\u017c\3"+
"\2\2\2\37\u0183\3\2\2\2!\u0188\3\2\2\2#\u018d\3\2\2\2%\u0195\3\2\2\2\'"+
"\u019b\3\2\2\2)\u01a3\3\2\2\2+\u01a9\3\2\2\2-\u01ad\3\2\2\2/\u01b0\3\2"+
"\2\2\61\u01b5\3\2\2\2\63\u01c0\3\2\2\2\65\u01c7\3\2\2\2\67\u01d2\3\2\2"+
"\29\u01d6\3\2\2\2;\u01e0\3\2\2\2=\u01e5\3\2\2\2?\u01ec\3\2\2\2A\u01f0"+
"\3\2\2\2C\u01f8\3\2\2\2E\u0200\3\2\2\2G\u020a\3\2\2\2I\u0211\3\2\2\2K"+
"\u0218\3\2\2\2M\u021e\3\2\2\2O\u0225\3\2\2\2Q\u022e\3\2\2\2S\u0234\3\2"+
"\2\2U\u023b\3\2\2\2W\u0248\3\2\2\2Y\u024d\3\2\2\2[\u0253\3\2\2\2]\u025a"+
"\3\2\2\2_\u0264\3\2\2\2a\u0268\3\2\2\2c\u026d\3\2\2\2e\u0276\3\2\2\2g"+
"\u0280\3\2\2\2i\u0282\3\2\2\2k\u0286\3\2\2\2m\u028a\3\2\2\2o\u028e\3\2"+
"\2\2q\u0292\3\2\2\2s\u029e\3\2\2\2u\u02a0\3\2\2\2w\u02ac\3\2\2\2y\u02ae"+
"\3\2\2\2{\u02b2\3\2\2\2}\u02b5\3\2\2\2\177\u02b9\3\2\2\2\u0081\u02bd\3"+
"\2\2\2\u0083\u02c7\3\2\2\2\u0085\u02cb\3\2\2\2\u0087\u02cd\3\2\2\2\u0089"+
"\u02d3\3\2\2\2\u008b\u02dd\3\2\2\2\u008d\u02e1\3\2\2\2\u008f\u02e3\3\2"+
"\2\2\u0091\u02e7\3\2\2\2\u0093\u02f1\3\2\2\2\u0095\u02f5\3\2\2\2\u0097"+
"\u02f9\3\2\2\2\u0099\u0316\3\2\2\2\u009b\u0318\3\2\2\2\u009d\u031b\3\2"+
"\2\2\u009f\u031e\3\2\2\2\u00a1\u0322\3\2\2\2\u00a3\u0324\3\2\2\2\u00a5"+
"\u0326\3\2\2\2\u00a7\u0336\3\2\2\2\u00a9\u0338\3\2\2\2\u00ab\u033b\3\2"+
"\2\2\u00ad\u0346\3\2\2\2\u00af\u0350\3\2\2\2\u00b1\u0352\3\2\2\2\u00b3"+
"\u0354\3\2\2\2\u00b5\u035b\3\2\2\2\u00b7\u0361\3\2\2\2\u00b9\u0367\3\2"+
"\2\2\u00bb\u0374\3\2\2\2\u00bd\u0376\3\2\2\2\u00bf\u037d\3\2\2\2\u00c1"+
"\u037f\3\2\2\2\u00c3\u0384\3\2\2\2\u00c5\u0386\3\2\2\2\u00c7\u0388\3\2"+
"\2\2\u00c9\u038a\3\2\2\2\u00cb\u038c\3\2\2\2\u00cd\u038e\3\2\2\2\u00cf"+
"\u0390\3\2\2\2\u00d1\u0392\3\2\2\2\u00d3\u0394\3\2\2\2\u00d5\u0396\3\2"+
"\2\2\u00d7\u0398\3\2\2\2\u00d9\u039a\3\2\2\2\u00db\u039c\3\2\2\2\u00dd"+
"\u039e\3\2\2\2\u00df\u03a0\3\2\2\2\u00e1\u03a2\3\2\2\2\u00e3\u03a4\3\2"+
"\2\2\u00e5\u03a7\3\2\2\2\u00e7\u03aa\3\2\2\2\u00e9\u03ad\3\2\2\2\u00eb"+
"\u03b0\3\2\2\2\u00ed\u03b3\3\2\2\2\u00ef\u03b6\3\2\2\2\u00f1\u03b9\3\2"+
"\2\2\u00f3\u03bc\3\2\2\2\u00f5\u03be\3\2\2\2\u00f7\u03c0\3\2\2\2\u00f9"+
"\u03c2\3\2\2\2\u00fb\u03c4\3\2\2\2\u00fd\u03c6\3\2\2\2\u00ff\u03c8\3\2"+
"\2\2\u0101\u03ca\3\2\2\2\u0103\u03cc\3\2\2\2\u0105\u03cf\3\2\2\2\u0107"+
"\u03d2\3\2\2\2\u0109\u03d5\3\2\2\2\u010b\u03d8\3\2\2\2\u010d\u03db\3\2"+
"\2\2\u010f\u03de\3\2\2\2\u0111\u03e1\3\2\2\2\u0113\u03e4\3\2\2\2\u0115"+
"\u03e8\3\2\2\2\u0117\u03ec\3\2\2\2\u0119\u03f1\3\2\2\2\u011b\u03fc\3\2"+
"\2\2\u011d\u0402\3\2\2\2\u011f\u0404\3\2\2\2\u0121\u0406\3\2\2\2\u0123"+
"\u040b\3\2\2\2\u0125\u0411\3\2\2\2\u0127\u041f\3\2\2\2\u0129\u012a\7c"+
"\2\2\u012a\u012b\7d\2\2\u012b\u012c\7u\2\2\u012c\u012d\7v\2\2\u012d\u012e"+
"\7t\2\2\u012e\u012f\7c\2\2\u012f\u0130\7e\2\2\u0130\u0131\7v\2\2\u0131"+
"\4\3\2\2\2\u0132\u0133\7c\2\2\u0133\u0134\7u\2\2\u0134\u0135\7u\2\2\u0135"+
"\u0136\7g\2\2\u0136\u0137\7t\2\2\u0137\u0138\7v\2\2\u0138\6\3\2\2\2\u0139"+
"\u013a\7d\2\2\u013a\u013b\7q\2\2\u013b\u013c\7q\2\2\u013c\u013d\7n\2\2"+
"\u013d\u013e\7g\2\2\u013e\u013f\7c\2\2\u013f\u0140\7p\2\2\u0140\b\3\2"+
"\2\2\u0141\u0142\7d\2\2\u0142\u0143\7t\2\2\u0143\u0144\7g\2\2\u0144\u0145"+
"\7c\2\2\u0145\u0146\7m\2\2\u0146\n\3\2\2\2\u0147\u0148\7d\2\2\u0148\u0149"+
"\7{\2\2\u0149\u014a\7v\2\2\u014a\u014b\7g\2\2\u014b\f\3\2\2\2\u014c\u014d"+
"\7e\2\2\u014d\u014e\7c\2\2\u014e\u014f\7u\2\2\u014f\u0150\7g\2\2\u0150"+
"\16\3\2\2\2\u0151\u0152\7e\2\2\u0152\u0153\7c\2\2\u0153\u0154\7v\2\2\u0154"+
"\u0155\7e\2\2\u0155\u0156\7j\2\2\u0156\20\3\2\2\2\u0157\u0158\7e\2\2\u0158"+
"\u0159\7j\2\2\u0159\u015a\7c\2\2\u015a\u015b\7t\2\2\u015b\22\3\2\2\2\u015c"+
"\u015d\7e\2\2\u015d\u015e\7n\2\2\u015e\u015f\7c\2\2\u015f\u0160\7u\2\2"+
"\u0160\u0161\7u\2\2\u0161\24\3\2\2\2\u0162\u0163\7e\2\2\u0163\u0164\7"+
"q\2\2\u0164\u0165\7p\2\2\u0165\u0166\7u\2\2\u0166\u0167\7v\2\2\u0167\26"+
"\3\2\2\2\u0168\u0169\7e\2\2\u0169\u016a\7q\2\2\u016a\u016b\7p\2\2\u016b"+
"\u016c\7v\2\2\u016c\u016d\7k\2\2\u016d\u016e\7p\2\2\u016e\u016f\7w\2\2"+
"\u016f\u0170\7g\2\2\u0170\30\3\2\2\2\u0171\u0172\7f\2\2\u0172\u0173\7"+
"g\2\2\u0173\u0174\7h\2\2\u0174\u0175\7c\2\2\u0175\u0176\7w\2\2\u0176\u0177"+
"\7n\2\2\u0177\u0178\7v\2\2\u0178\32\3\2\2\2\u0179\u017a\7f\2\2\u017a\u017b"+
"\7q\2\2\u017b\34\3\2\2\2\u017c\u017d\7f\2\2\u017d\u017e\7q\2\2\u017e\u017f"+
"\7w\2\2\u017f\u0180\7d\2\2\u0180\u0181\7n\2\2\u0181\u0182\7g\2\2\u0182"+
"\36\3\2\2\2\u0183\u0184\7g\2\2\u0184\u0185\7n\2\2\u0185\u0186\7u\2\2\u0186"+
"\u0187\7g\2\2\u0187 \3\2\2\2\u0188\u0189\7g\2\2\u0189\u018a\7p\2\2\u018a"+
"\u018b\7w\2\2\u018b\u018c\7o\2\2\u018c\"\3\2\2\2\u018d\u018e\7g\2\2\u018e"+
"\u018f\7z\2\2\u018f\u0190\7v\2\2\u0190\u0191\7g\2\2\u0191\u0192\7p\2\2"+
"\u0192\u0193\7f\2\2\u0193\u0194\7u\2\2\u0194$\3\2\2\2\u0195\u0196\7h\2"+
"\2\u0196\u0197\7k\2\2\u0197\u0198\7p\2\2\u0198\u0199\7c\2\2\u0199\u019a"+
"\7n\2\2\u019a&\3\2\2\2\u019b\u019c\7h\2\2\u019c\u019d\7k\2\2\u019d\u019e"+
"\7p\2\2\u019e\u019f\7c\2\2\u019f\u01a0\7n\2\2\u01a0\u01a1\7n\2\2\u01a1"+
"\u01a2\7{\2\2\u01a2(\3\2\2\2\u01a3\u01a4\7h\2\2\u01a4\u01a5\7n\2\2\u01a5"+
"\u01a6\7q\2\2\u01a6\u01a7\7c\2\2\u01a7\u01a8\7v\2\2\u01a8*\3\2\2\2\u01a9"+
"\u01aa\7h\2\2\u01aa\u01ab\7q\2\2\u01ab\u01ac\7t\2\2\u01ac,\3\2\2\2\u01ad"+
"\u01ae\7k\2\2\u01ae\u01af\7h\2\2\u01af.\3\2\2\2\u01b0\u01b1\7i\2\2\u01b1"+
"\u01b2\7q\2\2\u01b2\u01b3\7v\2\2\u01b3\u01b4\7q\2\2\u01b4\60\3\2\2\2\u01b5"+
"\u01b6\7k\2\2\u01b6\u01b7\7o\2\2\u01b7\u01b8\7r\2\2\u01b8\u01b9\7n\2\2"+
"\u01b9\u01ba\7g\2\2\u01ba\u01bb\7o\2\2\u01bb\u01bc\7g\2\2\u01bc\u01bd"+
"\7p\2\2\u01bd\u01be\7v\2\2\u01be\u01bf\7u\2\2\u01bf\62\3\2\2\2\u01c0\u01c1"+
"\7k\2\2\u01c1\u01c2\7o\2\2\u01c2\u01c3\7r\2\2\u01c3\u01c4\7q\2\2\u01c4"+
"\u01c5\7t\2\2\u01c5\u01c6\7v\2\2\u01c6\64\3\2\2\2\u01c7\u01c8\7k\2\2\u01c8"+
"\u01c9\7p\2\2\u01c9\u01ca\7u\2\2\u01ca\u01cb\7v\2\2\u01cb\u01cc\7c\2\2"+
"\u01cc\u01cd\7p\2\2\u01cd\u01ce\7e\2\2\u01ce\u01cf\7g\2\2\u01cf\u01d0"+
"\7q\2\2\u01d0\u01d1\7h\2\2\u01d1\66\3\2\2\2\u01d2\u01d3\7k\2\2\u01d3\u01d4"+
"\7p\2\2\u01d4\u01d5\7v\2\2\u01d58\3\2\2\2\u01d6\u01d7\7k\2\2\u01d7\u01d8"+
"\7p\2\2\u01d8\u01d9\7v\2\2\u01d9\u01da\7g\2\2\u01da\u01db\7t\2\2\u01db"+
"\u01dc\7h\2\2\u01dc\u01dd\7c\2\2\u01dd\u01de\7e\2\2\u01de\u01df\7g\2\2"+
"\u01df:\3\2\2\2\u01e0\u01e1\7n\2\2\u01e1\u01e2\7q\2\2\u01e2\u01e3\7p\2"+
"\2\u01e3\u01e4\7i\2\2\u01e4<\3\2\2\2\u01e5\u01e6\7p\2\2\u01e6\u01e7\7"+
"c\2\2\u01e7\u01e8\7v\2\2\u01e8\u01e9\7k\2\2\u01e9\u01ea\7x\2\2\u01ea\u01eb"+
"\7g\2\2\u01eb>\3\2\2\2\u01ec\u01ed\7p\2\2\u01ed\u01ee\7g\2\2\u01ee\u01ef"+
"\7y\2\2\u01ef@\3\2\2\2\u01f0\u01f1\7r\2\2\u01f1\u01f2\7c\2\2\u01f2\u01f3"+
"\7e\2\2\u01f3\u01f4\7m\2\2\u01f4\u01f5\7c\2\2\u01f5\u01f6\7i\2\2\u01f6"+
"\u01f7\7g\2\2\u01f7B\3\2\2\2\u01f8\u01f9\7r\2\2\u01f9\u01fa\7t\2\2\u01fa"+
"\u01fb\7k\2\2\u01fb\u01fc\7x\2\2\u01fc\u01fd\7c\2\2\u01fd\u01fe\7v\2\2"+
"\u01fe\u01ff\7g\2\2\u01ffD\3\2\2\2\u0200\u0201\7r\2\2\u0201\u0202\7t\2"+
"\2\u0202\u0203\7q\2\2\u0203\u0204\7v\2\2\u0204\u0205\7g\2\2\u0205\u0206"+
"\7e\2\2\u0206\u0207\7v\2\2\u0207\u0208\7g\2\2\u0208\u0209\7f\2\2\u0209"+
"F\3\2\2\2\u020a\u020b\7r\2\2\u020b\u020c\7w\2\2\u020c\u020d\7d\2\2\u020d"+
"\u020e\7n\2\2\u020e\u020f\7k\2\2\u020f\u0210\7e\2\2\u0210H\3\2\2\2\u0211"+
"\u0212\7t\2\2\u0212\u0213\7g\2\2\u0213\u0214\7v\2\2\u0214\u0215\7w\2\2"+
"\u0215\u0216\7t\2\2\u0216\u0217\7p\2\2\u0217J\3\2\2\2\u0218\u0219\7u\2"+
"\2\u0219\u021a\7j\2\2\u021a\u021b\7q\2\2\u021b\u021c\7t\2\2\u021c\u021d"+
"\7v\2\2\u021dL\3\2\2\2\u021e\u021f\7u\2\2\u021f\u0220\7v\2\2\u0220\u0221"+
"\7c\2\2\u0221\u0222\7v\2\2\u0222\u0223\7k\2\2\u0223\u0224\7e\2\2\u0224"+
"N\3\2\2\2\u0225\u0226\7u\2\2\u0226\u0227\7v\2\2\u0227\u0228\7t\2\2\u0228"+
"\u0229\7k\2\2\u0229\u022a\7e\2\2\u022a\u022b\7v\2\2\u022b\u022c\7h\2\2"+
"\u022c\u022d\7r\2\2\u022dP\3\2\2\2\u022e\u022f\7u\2\2\u022f\u0230\7w\2"+
"\2\u0230\u0231\7r\2\2\u0231\u0232\7g\2\2\u0232\u0233\7t\2\2\u0233R\3\2"+
"\2\2\u0234\u0235\7u\2\2\u0235\u0236\7y\2\2\u0236\u0237\7k\2\2\u0237\u0238"+
"\7v\2\2\u0238\u0239\7e\2\2\u0239\u023a\7j\2\2\u023aT\3\2\2\2\u023b\u023c"+
"\7u\2\2\u023c\u023d\7{\2\2\u023d\u023e\7p\2\2\u023e\u023f\7e\2\2\u023f"+
"\u0240\7j\2\2\u0240\u0241\7t\2\2\u0241\u0242\7q\2\2\u0242\u0243\7p\2\2"+
"\u0243\u0244\7k\2\2\u0244\u0245\7|\2\2\u0245\u0246\7g\2\2\u0246\u0247"+
"\7f\2\2\u0247V\3\2\2\2\u0248\u0249\7v\2\2\u0249\u024a\7j\2\2\u024a\u024b"+
"\7k\2\2\u024b\u024c\7u\2\2\u024cX\3\2\2\2\u024d\u024e\7v\2\2\u024e\u024f"+
"\7j\2\2\u024f\u0250\7t\2\2\u0250\u0251\7q\2\2\u0251\u0252\7y\2\2\u0252"+
"Z\3\2\2\2\u0253\u0254\7v\2\2\u0254\u0255\7j\2\2\u0255\u0256\7t\2\2\u0256"+
"\u0257\7q\2\2\u0257\u0258\7y\2\2\u0258\u0259\7u\2\2\u0259\\\3\2\2\2\u025a"+
"\u025b\7v\2\2\u025b\u025c\7t\2\2\u025c\u025d\7c\2\2\u025d\u025e\7p\2\2"+
"\u025e\u025f\7u\2\2\u025f\u0260\7k\2\2\u0260\u0261\7g\2\2\u0261\u0262"+
"\7p\2\2\u0262\u0263\7v\2\2\u0263^\3\2\2\2\u0264\u0265\7v\2\2\u0265\u0266"+
"\7t\2\2\u0266\u0267\7{\2\2\u0267`\3\2\2\2\u0268\u0269\7x\2\2\u0269\u026a"+
"\7q\2\2\u026a\u026b\7k\2\2\u026b\u026c\7f\2\2\u026cb\3\2\2\2\u026d\u026e"+
"\7x\2\2\u026e\u026f\7q\2\2\u026f\u0270\7n\2\2\u0270\u0271\7c\2\2\u0271"+
"\u0272\7v\2\2\u0272\u0273\7k\2\2\u0273\u0274\7n\2\2\u0274\u0275\7g\2\2"+
"\u0275d\3\2\2\2\u0276\u0277\7y\2\2\u0277\u0278\7j\2\2\u0278\u0279\7k\2"+
"\2\u0279\u027a\7n\2\2\u027a\u027b\7g\2\2\u027bf\3\2\2\2\u027c\u0281\5"+
"i\65\2\u027d\u0281\5k\66\2\u027e\u0281\5m\67\2\u027f\u0281\5o8\2\u0280"+
"\u027c\3\2\2\2\u0280\u027d\3\2\2\2\u0280\u027e\3\2\2\2\u0280\u027f\3\2"+
"\2\2\u0281h\3\2\2\2\u0282\u0284\5s:\2\u0283\u0285\5q9\2\u0284\u0283\3"+
"\2\2\2\u0284\u0285\3\2\2\2\u0285j\3\2\2\2\u0286\u0288\5\177@\2\u0287\u0289"+
"\5q9\2\u0288\u0287\3\2\2\2\u0288\u0289\3\2\2\2\u0289l\3\2\2\2\u028a\u028c"+
"\5\u0087D\2\u028b\u028d\5q9\2\u028c\u028b\3\2\2\2\u028c\u028d\3\2\2\2"+
"\u028dn\3\2\2\2\u028e\u0290\5\u008fH\2\u028f\u0291\5q9\2\u0290\u028f\3"+
"\2\2\2\u0290\u0291\3\2\2\2\u0291p\3\2\2\2\u0292\u0293\t\2\2\2\u0293r\3"+
"\2\2\2\u0294\u029f\7\62\2\2\u0295\u029c\5y=\2\u0296\u0298\5u;\2\u0297"+
"\u0296\3\2\2\2\u0297\u0298\3\2\2\2\u0298\u029d\3\2\2\2\u0299\u029a\5}"+
"?\2\u029a\u029b\5u;\2\u029b\u029d\3\2\2\2\u029c\u0297\3\2\2\2\u029c\u0299"+
"\3\2\2\2\u029d\u029f\3\2\2\2\u029e\u0294\3\2\2\2\u029e\u0295\3\2\2\2\u029f"+
"t\3\2\2\2\u02a0\u02a8\5w<\2\u02a1\u02a3\5{>\2\u02a2\u02a1\3\2\2\2\u02a3"+
"\u02a6\3\2\2\2\u02a4\u02a2\3\2\2\2\u02a4\u02a5\3\2\2\2\u02a5\u02a7\3\2"+
"\2\2\u02a6\u02a4\3\2\2\2\u02a7\u02a9\5w<\2\u02a8\u02a4\3\2\2\2\u02a8\u02a9"+
"\3\2\2\2\u02a9v\3\2\2\2\u02aa\u02ad\7\62\2\2\u02ab\u02ad\5y=\2\u02ac\u02aa"+
"\3\2\2\2\u02ac\u02ab\3\2\2\2\u02adx\3\2\2\2\u02ae\u02af\t\3\2\2\u02af"+
"z\3\2\2\2\u02b0\u02b3\5w<\2\u02b1\u02b3\7a\2\2\u02b2\u02b0\3\2\2\2\u02b2"+
"\u02b1\3\2\2\2\u02b3|\3\2\2\2\u02b4\u02b6\7a\2\2\u02b5\u02b4\3\2\2\2\u02b6"+
"\u02b7\3\2\2\2\u02b7\u02b5\3\2\2\2\u02b7\u02b8\3\2\2\2\u02b8~\3\2\2\2"+
"\u02b9\u02ba\7\62\2\2\u02ba\u02bb\t\4\2\2\u02bb\u02bc\5\u0081A\2\u02bc"+
"\u0080\3\2\2\2\u02bd\u02c5\5\u0083B\2\u02be\u02c0\5\u0085C\2\u02bf\u02be"+
"\3\2\2\2\u02c0\u02c3\3\2\2\2\u02c1\u02bf\3\2\2\2\u02c1\u02c2\3\2\2\2\u02c2"+
"\u02c4\3\2\2\2\u02c3\u02c1\3\2\2\2\u02c4\u02c6\5\u0083B\2\u02c5\u02c1"+
"\3\2\2\2\u02c5\u02c6\3\2\2\2\u02c6\u0082\3\2\2\2\u02c7\u02c8\t\5\2\2\u02c8"+
"\u0084\3\2\2\2\u02c9\u02cc\5\u0083B\2\u02ca\u02cc\7a\2\2\u02cb\u02c9\3"+
"\2\2\2\u02cb\u02ca\3\2\2\2\u02cc\u0086\3\2\2\2\u02cd\u02cf\7\62\2\2\u02ce"+
"\u02d0\5}?\2\u02cf\u02ce\3\2\2\2\u02cf\u02d0\3\2\2\2\u02d0\u02d1\3\2\2"+
"\2\u02d1\u02d2\5\u0089E\2\u02d2\u0088\3\2\2\2\u02d3\u02db\5\u008bF\2\u02d4"+
"\u02d6\5\u008dG\2\u02d5\u02d4\3\2\2\2\u02d6\u02d9\3\2\2\2\u02d7\u02d5"+
"\3\2\2\2\u02d7\u02d8\3\2\2\2\u02d8\u02da\3\2\2\2\u02d9\u02d7\3\2\2\2\u02da"+
"\u02dc\5\u008bF\2\u02db\u02d7\3\2\2\2\u02db\u02dc\3\2\2\2\u02dc\u008a"+
"\3\2\2\2\u02dd\u02de\t\6\2\2\u02de\u008c\3\2\2\2\u02df\u02e2\5\u008bF"+
"\2\u02e0\u02e2\7a\2\2\u02e1\u02df\3\2\2\2\u02e1\u02e0\3\2\2\2\u02e2\u008e"+
"\3\2\2\2\u02e3\u02e4\7\62\2\2\u02e4\u02e5\t\7\2\2\u02e5\u02e6\5\u0091"+
"I\2\u02e6\u0090\3\2\2\2\u02e7\u02ef\5\u0093J\2\u02e8\u02ea\5\u0095K\2"+
"\u02e9\u02e8\3\2\2\2\u02ea\u02ed\3\2\2\2\u02eb\u02e9\3\2\2\2\u02eb\u02ec"+
"\3\2\2\2\u02ec\u02ee\3\2\2\2\u02ed\u02eb\3\2\2\2\u02ee\u02f0\5\u0093J"+
"\2\u02ef\u02eb\3\2\2\2\u02ef\u02f0\3\2\2\2\u02f0\u0092\3\2\2\2\u02f1\u02f2"+
"\t\b\2\2\u02f2\u0094\3\2\2\2\u02f3\u02f6\5\u0093J\2\u02f4\u02f6\7a\2\2"+
"\u02f5\u02f3\3\2\2\2\u02f5\u02f4\3\2\2\2\u02f6\u0096\3\2\2\2\u02f7\u02fa"+
"\5\u0099M\2\u02f8\u02fa\5\u00a5S\2\u02f9\u02f7\3\2\2\2\u02f9\u02f8\3\2"+
"\2\2\u02fa\u0098\3\2\2\2\u02fb\u02fc\5u;\2\u02fc\u02fe\7\60\2\2\u02fd"+
"\u02ff\5u;\2\u02fe\u02fd\3\2\2\2\u02fe\u02ff\3\2\2\2\u02ff\u0301\3\2\2"+
"\2\u0300\u0302\5\u009bN\2\u0301\u0300\3\2\2\2\u0301\u0302\3\2\2\2\u0302"+
"\u0304\3\2\2\2\u0303\u0305\5\u00a3R\2\u0304\u0303\3\2\2\2\u0304\u0305"+
"\3\2\2\2\u0305\u0317\3\2\2\2\u0306\u0307\7\60\2\2\u0307\u0309\5u;\2\u0308"+
"\u030a\5\u009bN\2\u0309\u0308\3\2\2\2\u0309\u030a\3\2\2\2\u030a\u030c"+
"\3\2\2\2\u030b\u030d\5\u00a3R\2\u030c\u030b\3\2\2\2\u030c\u030d\3\2\2"+
"\2\u030d\u0317\3\2\2\2\u030e\u030f\5u;\2\u030f\u0311\5\u009bN\2\u0310"+
"\u0312\5\u00a3R\2\u0311\u0310\3\2\2\2\u0311\u0312\3\2\2\2\u0312\u0317"+
"\3\2\2\2\u0313\u0314\5u;\2\u0314\u0315\5\u00a3R\2\u0315\u0317\3\2\2\2"+
"\u0316\u02fb\3\2\2\2\u0316\u0306\3\2\2\2\u0316\u030e\3\2\2\2\u0316\u0313"+
"\3\2\2\2\u0317\u009a\3\2\2\2\u0318\u0319\5\u009dO\2\u0319\u031a\5\u009f"+
"P\2\u031a\u009c\3\2\2\2\u031b\u031c\t\t\2\2\u031c\u009e\3\2\2\2\u031d"+
"\u031f\5\u00a1Q\2\u031e\u031d\3\2\2\2\u031e\u031f\3\2\2\2\u031f\u0320"+
"\3\2\2\2\u0320\u0321\5u;\2\u0321\u00a0\3\2\2\2\u0322\u0323\t\n\2\2\u0323"+
"\u00a2\3\2\2\2\u0324\u0325\t\13\2\2\u0325\u00a4\3\2\2\2\u0326\u0327\5"+
"\u00a7T\2\u0327\u0329\5\u00a9U\2\u0328\u032a\5\u00a3R\2\u0329\u0328\3"+
"\2\2\2\u0329\u032a\3\2\2\2\u032a\u00a6\3\2\2\2\u032b\u032d\5\177@\2\u032c"+
"\u032e\7\60\2\2\u032d\u032c\3\2\2\2\u032d\u032e\3\2\2\2\u032e\u0337\3"+
"\2\2\2\u032f\u0330\7\62\2\2\u0330\u0332\t\4\2\2\u0331\u0333\5\u0081A\2"+
"\u0332\u0331\3\2\2\2\u0332\u0333\3\2\2\2\u0333\u0334\3\2\2\2\u0334\u0335"+
"\7\60\2\2\u0335\u0337\5\u0081A\2\u0336\u032b\3\2\2\2\u0336\u032f\3\2\2"+
"\2\u0337\u00a8\3\2\2\2\u0338\u0339\5\u00abV\2\u0339\u033a\5\u009fP\2\u033a"+
"\u00aa\3\2\2\2\u033b\u033c\t\f\2\2\u033c\u00ac\3\2\2\2\u033d\u033e\7v"+
"\2\2\u033e\u033f\7t\2\2\u033f\u0340\7w\2\2\u0340\u0347\7g\2\2\u0341\u0342"+
"\7h\2\2\u0342\u0343\7c\2\2\u0343\u0344\7n\2\2\u0344\u0345\7u\2\2\u0345"+
"\u0347\7g\2\2\u0346\u033d\3\2\2\2\u0346\u0341\3\2\2\2\u0347\u00ae\3\2"+
"\2\2\u0348\u0349\7)\2\2\u0349\u034a\5\u00b1Y\2\u034a\u034b\7)\2\2\u034b"+
"\u0351\3\2\2\2\u034c\u034d\7)\2\2\u034d\u034e\5\u00b9]\2\u034e\u034f\7"+
")\2\2\u034f\u0351\3\2\2\2\u0350\u0348\3\2\2\2\u0350\u034c\3\2\2\2\u0351"+
"\u00b0\3\2\2\2\u0352\u0353\n\r\2\2\u0353\u00b2\3\2\2\2\u0354\u0356\7$"+
"\2\2\u0355\u0357\5\u00b5[\2\u0356\u0355\3\2\2\2\u0356\u0357\3\2\2\2\u0357"+
"\u0358\3\2\2\2\u0358\u0359\7$\2\2\u0359\u00b4\3\2\2\2\u035a\u035c\5\u00b7"+
"\\\2\u035b\u035a\3\2\2\2\u035c\u035d\3\2\2\2\u035d\u035b\3\2\2\2\u035d"+
"\u035e\3\2\2\2\u035e\u00b6\3\2\2\2\u035f\u0362\n\16\2\2\u0360\u0362\5"+
"\u00b9]\2\u0361\u035f\3\2\2\2\u0361\u0360\3\2\2\2\u0362\u00b8\3\2\2\2"+
"\u0363\u0364\7^\2\2\u0364\u0368\t\17\2\2\u0365\u0368\5\u00bb^\2\u0366"+
"\u0368\5\u00bd_\2\u0367\u0363\3\2\2\2\u0367\u0365\3\2\2\2\u0367\u0366"+
"\3\2\2\2\u0368\u00ba\3\2\2\2\u0369\u036a\7^\2\2\u036a\u0375\5\u008bF\2"+
"\u036b\u036c\7^\2\2\u036c\u036d\5\u008bF\2\u036d\u036e\5\u008bF\2\u036e"+
"\u0375\3\2\2\2\u036f\u0370\7^\2\2\u0370\u0371\5\u00bf`\2\u0371\u0372\5"+
"\u008bF\2\u0372\u0373\5\u008bF\2\u0373\u0375\3\2\2\2\u0374\u0369\3\2\2"+
"\2\u0374\u036b\3\2\2\2\u0374\u036f\3\2\2\2\u0375\u00bc\3\2\2\2\u0376\u0377"+
"\7^\2\2\u0377\u0378\7w\2\2\u0378\u0379\5\u0083B\2\u0379\u037a\5\u0083"+
"B\2\u037a\u037b\5\u0083B\2\u037b\u037c\5\u0083B\2\u037c\u00be\3\2\2\2"+
"\u037d\u037e\t\20\2\2\u037e\u00c0\3\2\2\2\u037f\u0380\7p\2\2\u0380\u0381"+
"\7w\2\2\u0381\u0382\7n\2\2\u0382\u0383\7n\2\2\u0383\u00c2\3\2\2\2\u0384"+
"\u0385\7*\2\2\u0385\u00c4\3\2\2\2\u0386\u0387\7+\2\2\u0387\u00c6\3\2\2"+
"\2\u0388\u0389\7}\2\2\u0389\u00c8\3\2\2\2\u038a\u038b\7\177\2\2\u038b"+
"\u00ca\3\2\2\2\u038c\u038d\7]\2\2\u038d\u00cc\3\2\2\2\u038e\u038f\7_\2"+
"\2\u038f\u00ce\3\2\2\2\u0390\u0391\7=\2\2\u0391\u00d0\3\2\2\2\u0392\u0393"+
"\7.\2\2\u0393\u00d2\3\2\2\2\u0394\u0395\7\60\2\2\u0395\u00d4\3\2\2\2\u0396"+
"\u0397\7?\2\2\u0397\u00d6\3\2\2\2\u0398\u0399\7@\2\2\u0399\u00d8\3\2\2"+
"\2\u039a\u039b\7>\2\2\u039b\u00da\3\2\2\2\u039c\u039d\7#\2\2\u039d\u00dc"+
"\3\2\2\2\u039e\u039f\7\u0080\2\2\u039f\u00de\3\2\2\2\u03a0\u03a1\7A\2"+
"\2\u03a1\u00e0\3\2\2\2\u03a2\u03a3\7<\2\2\u03a3\u00e2\3\2\2\2\u03a4\u03a5"+
"\7?\2\2\u03a5\u03a6\7?\2\2\u03a6\u00e4\3\2\2\2\u03a7\u03a8\7>\2\2\u03a8"+
"\u03a9\7?\2\2\u03a9\u00e6\3\2\2\2\u03aa\u03ab\7@\2\2\u03ab\u03ac\7?\2"+
"\2\u03ac\u00e8\3\2\2\2\u03ad\u03ae\7#\2\2\u03ae\u03af\7?\2\2\u03af\u00ea"+
"\3\2\2\2\u03b0\u03b1\7(\2\2\u03b1\u03b2\7(\2\2\u03b2\u00ec\3\2\2\2\u03b3"+
"\u03b4\7~\2\2\u03b4\u03b5\7~\2\2\u03b5\u00ee\3\2\2\2\u03b6\u03b7\7-\2"+
"\2\u03b7\u03b8\7-\2\2\u03b8\u00f0\3\2\2\2\u03b9\u03ba\7/\2\2\u03ba\u03bb"+
"\7/\2\2\u03bb\u00f2\3\2\2\2\u03bc\u03bd\7-\2\2\u03bd\u00f4\3\2\2\2\u03be"+
"\u03bf\7/\2\2\u03bf\u00f6\3\2\2\2\u03c0\u03c1\7,\2\2\u03c1\u00f8\3\2\2"+
"\2\u03c2\u03c3\7\61\2\2\u03c3\u00fa\3\2\2\2\u03c4\u03c5\7(\2\2\u03c5\u00fc"+
"\3\2\2\2\u03c6\u03c7\7~\2\2\u03c7\u00fe\3\2\2\2\u03c8\u03c9\7`\2\2\u03c9"+
"\u0100\3\2\2\2\u03ca\u03cb\7\'\2\2\u03cb\u0102\3\2\2\2\u03cc\u03cd\7-"+
"\2\2\u03cd\u03ce\7?\2\2\u03ce\u0104\3\2\2\2\u03cf\u03d0\7/\2\2\u03d0\u03d1"+
"\7?\2\2\u03d1\u0106\3\2\2\2\u03d2\u03d3\7,\2\2\u03d3\u03d4\7?\2\2\u03d4"+
"\u0108\3\2\2\2\u03d5\u03d6\7\61\2\2\u03d6\u03d7\7?\2\2\u03d7\u010a\3\2"+
"\2\2\u03d8\u03d9\7(\2\2\u03d9\u03da\7?\2\2\u03da\u010c\3\2\2\2\u03db\u03dc"+
"\7~\2\2\u03dc\u03dd\7?\2\2\u03dd\u010e\3\2\2\2\u03de\u03df\7`\2\2\u03df"+
"\u03e0\7?\2\2\u03e0\u0110\3\2\2\2\u03e1\u03e2\7\'\2\2\u03e2\u03e3\7?\2"+
"\2\u03e3\u0112\3\2\2\2\u03e4\u03e5\7>\2\2\u03e5\u03e6\7>\2\2\u03e6\u03e7"+
"\7?\2\2\u03e7\u0114\3\2\2\2\u03e8\u03e9\7@\2\2\u03e9\u03ea\7@\2\2\u03ea"+
"\u03eb\7?\2\2\u03eb\u0116\3\2\2\2\u03ec\u03ed\7@\2\2\u03ed\u03ee\7@\2"+
"\2\u03ee\u03ef\7@\2\2\u03ef\u03f0\7?\2\2\u03f0\u0118\3\2\2\2\u03f1\u03f5"+
"\5\u011b\u008e\2\u03f2\u03f4\5\u011d\u008f\2\u03f3\u03f2\3\2\2\2\u03f4"+
"\u03f7\3\2\2\2\u03f5\u03f3\3\2\2\2\u03f5\u03f6\3\2\2\2\u03f6\u011a\3\2"+
"\2\2\u03f7\u03f5\3\2\2\2\u03f8\u03fd\t\21\2\2\u03f9\u03fd\n\22\2\2\u03fa"+
"\u03fb\t\23\2\2\u03fb\u03fd\t\24\2\2\u03fc\u03f8\3\2\2\2\u03fc\u03f9\3"+
"\2\2\2\u03fc\u03fa\3\2\2\2\u03fd\u011c\3\2\2\2\u03fe\u0403\t\25\2\2\u03ff"+
"\u0403\n\22\2\2\u0400\u0401\t\23\2\2\u0401\u0403\t\24\2\2\u0402\u03fe"+
"\3\2\2\2\u0402\u03ff\3\2\2\2\u0402\u0400\3\2\2\2\u0403\u011e\3\2\2\2\u0404"+
"\u0405\7B\2\2\u0405\u0120\3\2\2\2\u0406\u0407\7\60\2\2\u0407\u0408\7\60"+
"\2\2\u0408\u0409\7\60\2\2\u0409\u0122\3\2\2\2\u040a\u040c\t\26\2\2\u040b"+
"\u040a\3\2\2\2\u040c\u040d\3\2\2\2\u040d\u040b\3\2\2\2\u040d\u040e\3\2"+
"\2\2\u040e\u040f\3\2\2\2\u040f\u0410\b\u0092\2\2\u0410\u0124\3\2\2\2\u0411"+
"\u0412\7\61\2\2\u0412\u0413\7,\2\2\u0413\u0417\3\2\2\2\u0414\u0416\13"+
"\2\2\2\u0415\u0414\3\2\2\2\u0416\u0419\3\2\2\2\u0417\u0418\3\2\2\2\u0417"+
"\u0415\3\2\2\2\u0418\u041a\3\2\2\2\u0419\u0417\3\2\2\2\u041a\u041b\7,"+
"\2\2\u041b\u041c\7\61\2\2\u041c\u041d\3\2\2\2\u041d\u041e\b\u0093\3\2"+
"\u041e\u0126\3\2\2\2\u041f\u0420\7\61\2\2\u0420\u0421\7\61\2\2\u0421\u0425"+
"\3\2\2\2\u0422\u0424\n\27\2\2\u0423\u0422\3\2\2\2\u0424\u0427\3\2\2\2"+
"\u0425\u0423\3\2\2\2\u0425\u0426\3\2\2\2\u0426\u0428\3\2\2\2\u0427\u0425"+
"\3\2\2\2\u0428\u0429\b\u0094\3\2\u0429\u0128\3\2\2\2\64\2\u0280\u0284"+
"\u0288\u028c\u0290\u0297\u029c\u029e\u02a4\u02a8\u02ac\u02b2\u02b7\u02c1"+
"\u02c5\u02cb\u02cf\u02d7\u02db\u02e1\u02eb\u02ef\u02f5\u02f9\u02fe\u0301"+
"\u0304\u0309\u030c\u0311\u0316\u031e\u0329\u032d\u0332\u0336\u0346\u0350"+
"\u0356\u035d\u0361\u0367\u0374\u03f5\u03fc\u0402\u040d\u0417\u0425\4\b"+
"\2\2\2\3\2";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}

View File

@ -0,0 +1,201 @@
ABSTRACT=1
ASSERT=2
BOOLEAN=3
BREAK=4
BYTE=5
CASE=6
CATCH=7
CHAR=8
CLASS=9
CONST=10
CONTINUE=11
DEFAULT=12
DO=13
DOUBLE=14
ELSE=15
ENUM=16
EXTENDS=17
FINAL=18
FINALLY=19
FLOAT=20
FOR=21
IF=22
GOTO=23
IMPLEMENTS=24
IMPORT=25
INSTANCEOF=26
INT=27
INTERFACE=28
LONG=29
NATIVE=30
NEW=31
PACKAGE=32
PRIVATE=33
PROTECTED=34
PUBLIC=35
RETURN=36
SHORT=37
STATIC=38
STRICTFP=39
SUPER=40
SWITCH=41
SYNCHRONIZED=42
THIS=43
THROW=44
THROWS=45
TRANSIENT=46
TRY=47
VOID=48
VOLATILE=49
WHILE=50
IntegerLiteral=51
FloatingPointLiteral=52
BooleanLiteral=53
CharacterLiteral=54
StringLiteral=55
NullLiteral=56
LPAREN=57
RPAREN=58
LBRACE=59
RBRACE=60
LBRACK=61
RBRACK=62
SEMI=63
COMMA=64
DOT=65
ASSIGN=66
GT=67
LT=68
BANG=69
TILDE=70
QUESTION=71
COLON=72
EQUAL=73
LE=74
GE=75
NOTEQUAL=76
AND=77
OR=78
INC=79
DEC=80
ADD=81
SUB=82
MUL=83
DIV=84
BITAND=85
BITOR=86
CARET=87
MOD=88
ADD_ASSIGN=89
SUB_ASSIGN=90
MUL_ASSIGN=91
DIV_ASSIGN=92
AND_ASSIGN=93
OR_ASSIGN=94
XOR_ASSIGN=95
MOD_ASSIGN=96
LSHIFT_ASSIGN=97
RSHIFT_ASSIGN=98
URSHIFT_ASSIGN=99
Identifier=100
AT=101
ELLIPSIS=102
WS=103
COMMENT=104
LINE_COMMENT=105
'abstract'=1
'assert'=2
'boolean'=3
'break'=4
'byte'=5
'case'=6
'catch'=7
'char'=8
'class'=9
'const'=10
'continue'=11
'default'=12
'do'=13
'double'=14
'else'=15
'enum'=16
'extends'=17
'final'=18
'finally'=19
'float'=20
'for'=21
'if'=22
'goto'=23
'implements'=24
'import'=25
'instanceof'=26
'int'=27
'interface'=28
'long'=29
'native'=30
'new'=31
'package'=32
'private'=33
'protected'=34
'public'=35
'return'=36
'short'=37
'static'=38
'strictfp'=39
'super'=40
'switch'=41
'synchronized'=42
'this'=43
'throw'=44
'throws'=45
'transient'=46
'try'=47
'void'=48
'volatile'=49
'while'=50
'null'=56
'('=57
')'=58
'{'=59
'}'=60
'['=61
']'=62
';'=63
','=64
'.'=65
'='=66
'>'=67
'<'=68
'!'=69
'~'=70
'?'=71
':'=72
'=='=73
'<='=74
'>='=75
'!='=76
'&&'=77
'||'=78
'++'=79
'--'=80
'+'=81
'-'=82
'*'=83
'/'=84
'&'=85
'|'=86
'^'=87
'%'=88
'+='=89
'-='=90
'*='=91
'/='=92
'&='=93
'|='=94
'^='=95
'%='=96
'<<='=97
'>>='=98
'>>>='=99
'@'=101
'...'=102

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
package it.unitn.repoman.core.lang.traversals.c;
import java.util.HashSet;
import java.util.Set;
import it.unitn.repoman.core.lang.traversals.generic.DFSTraversal;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import it.unitn.repoman.core.lang.parsers.c.CParser;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;
public class CMethodCallTraversal extends MethodCallTraversal {
public CMethodCallTraversal(ParseTree node) {
super(node);
}
private class ParamsTraversal extends DFSTraversal {
private Set<ParseTree> params = new HashSet<>();
@Override
public void onEnterNode(ParseTree node) {
if (node instanceof CParser.PrimaryExpressionContext) {
params.add(node);
}
}
}
@Override
public void onEnterNode(ParseTree node) {
skip--;
if (node.getParent() instanceof CParser.InitDeclaratorListContext) {
if (node.getChildCount() == 1) {
try {
this.methodContext = node.getParent().getParent();
this.callNameNode = methodContext.getChild(0);
ParseTree declarator = node.getChild(0).getChild(0);
ParseTree lbrace = declarator.getChild(0);
this.paramsNode = declarator.getChild(1);
ParseTree rbrace = declarator.getChild(2);
if (lbrace.getText().equals("(")) {
if (paramsNode.getText().equals(")")) {
this.isMethodCall = true;
paramsNode = null;
}
else if (rbrace.getText().equals(")")) {
this.isMethodCall = true;
}
}
if (paramsNode != null) {
this.params.add(paramsNode.getChild(0));
}
}
catch (NullPointerException e) {
this.isMethodCall = false;
}
return;
}
else {
skip = 5;
}
}
else if (node.getParent() instanceof CParser.ExpressionStatementContext
&& !(node instanceof TerminalNode)) {
if (node.getChild(0).getChildCount() != 1) {
skip = 7;
}
else {
skip = 1;
}
}
if (skip == 0) {
if (node instanceof CParser.PostfixExpressionContext) {
if (node.getChild(0) instanceof CParser.PrimaryExpressionContext) {
skip = -1;
}
else {
try {
this.methodContext = node;
this.callNameNode = node.getChild(0);
ParseTree lbrace = node.getChild(1);
this.paramsNode = node.getChild(2);
ParseTree rbrace = node.getChild(3);
if (lbrace.getText().equals("(")) {
if (paramsNode.getText().equals(")")) {
this.isMethodCall = true;
paramsNode = null;
}
else if (rbrace.getText().equals(")")) {
this.isMethodCall = true;
}
}
}
catch (NullPointerException e) {
this.isMethodCall = false;
}
if (this.paramsNode != null) {
ParamsTraversal pt = new ParamsTraversal();
pt.traverse(paramsNode);
this.params.addAll(pt.params);
}
}
}
else {
skip++;
}
}
}
}

View File

@ -0,0 +1,56 @@
package it.unitn.repoman.core.lang.traversals.generic;
import java.util.LinkedList;
import java.util.List;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class AssignmentSymbolExtractTraversal extends DFSTraversal {
private ParserRuleContext stmt = null;
private boolean isNextLeft = false;
private ParseTree lhs = null;
private List<ParseTree> rhs = new LinkedList<>();
public AssignmentSymbolExtractTraversal(ParserRuleContext ctx) {
this.stmt = ctx;
traverse();
}
@Override
public void traverse() {
this.traverse(this.stmt);
}
@Override
public void onEnterNode(ParseTree node) {
if (isWithinContext(node)) {
isNextLeft = true;
}
if (isNextLeft) {
if (wrapper.isTerminal(node) && wrapper.isToken(node)) {
isNextLeft = false;
lhs = node;
}
}
else {
SymbolExtractTraversal t = new SymbolExtractTraversal(stmt);
rhs.addAll(t.getSymbols());
rhs.remove(lhs);
terminate();
}
}
@Override
protected boolean isWithinContext(ParseTree node) {
return wrapper.isStatement(node.getParent()) ||
wrapper.isFieldDeclaration(node.getParent());
}
public ParseTree getLhs() {
return lhs;
}
public List<ParseTree> getRhsList() {
return rhs;
}
}

View File

@ -0,0 +1,25 @@
package it.unitn.repoman.core.lang.traversals.generic;
import java.util.Set;
import java.util.HashSet;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class ConditionTraversal extends DFSTraversal {
private Set<ParserRuleContext> innerStmts = new HashSet<>();
public ConditionTraversal(ParserRuleContext cnd) {
traverse(cnd.getParent());
}
@Override
public void onEnterNode(ParseTree node) {
if (wrapper.isStatement(node)) {
innerStmts.add((ParserRuleContext)node);
}
}
public Set<ParserRuleContext> getInnerStatements() {
return this.innerStmts;
}
}

View File

@ -0,0 +1,58 @@
package it.unitn.repoman.core.lang.traversals.generic;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.lang.wrappers.generic.Wrapper;
import java.lang.UnsupportedOperationException;
import org.antlr.v4.runtime.tree.ParseTree;
public class DFSTraversal implements Traversal {
protected boolean isTerminated = false;
protected ParseTree lastNode = null;
protected Wrapper wrapper = LanguageFactory.getWrapper();
@Override
public void traverse(ParseTree root) {
if (root == null) {
return;
}
for (int i=0; i < root.getChildCount(); i++) {
if (isTerminated) {
onTerminate();
break;
}
lastNode = root.getChild(i);
onEnterNode(lastNode);
traverse(lastNode);
onExitNode(lastNode);
}
}
public void traverse() {
throw new UnsupportedOperationException("ERROR: This method is not implemented!");
}
protected boolean isWithinContext(ParseTree node) {
return true;
}
@Override
public void onEnterNode(ParseTree node) {
}
@Override
public void onExitNode(ParseTree node) {
}
protected void onTerminate() {
}
protected void terminate() {
this.isTerminated = true;
}
public ParseTree getLastNode() {
return this.lastNode;
}
}

View File

@ -0,0 +1,51 @@
package it.unitn.repoman.core.lang.traversals.generic;
import org.antlr.v4.runtime.tree.ParseTree;
import java.util.LinkedList;
import java.util.List;
public class DotSymbolTraversal extends DFSTraversal{
private ParseTree rightmostNode = null;
private List<ParseTree> nodes = new LinkedList<>();
public DotSymbolTraversal(ParseTree root) {
traverse(root);
rightmostNode = nodes.get(nodes.size()-1);
}
@Override
public void onEnterNode(ParseTree node) {
if (wrapper.isTerminal(node)) {
if (!node.getText().equals(".")) {
nodes.add(node);
}
}
}
public ParseTree getRightmostNode() {
return rightmostNode;
}
public String getRightmostNodeName() {
return (rightmostNode != null) ? rightmostNode.getText() : "";
}
public List<ParseTree> getLeftNodes() {
List<ParseTree> leftNodes = new LinkedList<>();
leftNodes.addAll(nodes);
if (rightmostNode != null) {
leftNodes.remove(rightmostNode);
}
return leftNodes;
}
public List<String> getLeftNodesNames() {
List<String> leftNodesNames = new LinkedList<>();
for (ParseTree node : getLeftNodes()) {
leftNodesNames.add(node.getText());
}
return leftNodesNames;
}
}

View File

@ -0,0 +1,52 @@
package it.unitn.repoman.core.lang.traversals.generic;
import it.unitn.repoman.core.lang.parsers.java.JavaParser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class FormalParameterTraversal extends DFSTraversal {
private ParseTree type;
private ParseTree variable;
public FormalParameterTraversal(ParserRuleContext ctx) {
if (wrapper.isFormalParameter(ctx)) {
traverse(ctx);
}
}
@Override
public void onEnterNode(ParseTree node) {
if (node.getClass().equals(JavaParser.TypeTypeContext.class)) {
type = node;
}
else if (node.getClass().equals(JavaParser.VariableDeclaratorIdContext.class)) {
variable = node;
}
}
public String getTypeName() {
return type.getText();
}
public String getVariableName() {
return variable.getText();
}
public ParseTree getTypeTerminalNode() {
return type.getChild(0);
}
public ParseTree getTypeNode() {
return type;
}
public ParseTree getVariableTerminalNode() {
return variable.getChild(0);
}
public ParseTree getVariableNode() {
return variable;
}
}

View File

@ -0,0 +1,64 @@
package it.unitn.repoman.core.lang.traversals.generic;
import java.util.LinkedList;
import java.util.List;
import org.antlr.v4.runtime.tree.ParseTree;
public abstract class MethodCallTraversal extends DFSTraversal {
protected boolean isMethodCall = false;
protected ParseTree callNameNode = null;
protected ParseTree paramsNode = null;
protected final List<ParseTree> params = new LinkedList<>();
protected final List<String> paramNames = new LinkedList<>();
protected final int numberOfParams;
protected int skip = -1;
protected ParseTree methodContext = null;
public MethodCallTraversal(ParseTree node) {
traverse(node);
for (ParseTree t : params) {
if (wrapper.isToken(t)) {
paramNames.add(t.getText());
}
}
numberOfParams = params.size();
}
public String getMethodName() {
return (callNameNode != null) ? callNameNode.getText() : "";
}
public int getParamsNumber() {
return numberOfParams;
}
public ParseTree getCallNameNode() {
return this.callNameNode;
}
public List<ParseTree> getParams() {
return this.params;
}
public List<String> getParamNames() {
return paramNames;
}
public ParseTree getParamsNode() {
return this.paramsNode;
}
public boolean isMethodCall() {
return this.isMethodCall;
}
public ParseTree getMethodContextNode() {
return this.methodContext;
}
public String getParamName(int pos) {
return getParamNames().get(pos);
}
}

View File

@ -0,0 +1,69 @@
package it.unitn.repoman.core.lang.traversals.generic;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import java.util.LinkedList;
import java.util.List;
public class MethodDeclarationTraversal extends DFSTraversal {
private ParseTree methodName = null;
private ParseTree returnType = null;
private List<String> paramNames = new LinkedList<>();
private List<ParseTree> paramNodes = new LinkedList<>();
private final List<ParserRuleContext> parameters = new LinkedList<>();
public MethodDeclarationTraversal(ParserRuleContext ctx) {
if (wrapper.isMethodDeclaration(ctx)) {
traverse(ctx);
} // or else throw an exception?
for (ParserRuleContext param : parameters) {
FormalParameterTraversal t = new FormalParameterTraversal(param);
paramNames.add(t.getVariableName());
paramNodes.add(t.getVariableTerminalNode());
}
}
@Override
public void onEnterNode(ParseTree node) {
if (returnType == null && wrapper.isTerminal(node)) {
returnType = node;
}
else if (methodName == null && wrapper.isTerminal(node)) {
methodName = node;
}
else if (methodName != null && returnType != null){
if (wrapper.isFormalParameter(node)) {
parameters.add((ParserRuleContext) node);
}
}
}
public String getMethodName() {
return methodName.getText();
}
public String getReturnType() {
return returnType.getText();
}
public List<String> getParamNames() {
return paramNames;
}
public int getParamsNumber() {
return parameters.size();
}
public String getParamName(int pos) {
return paramNames.get(pos);
}
public ParseTree getParamNode(int pos) {
return paramNodes.get(pos);
}
public ParseTree getParam(int pos) {
return parameters.get(pos);
}
}

View File

@ -0,0 +1,27 @@
package it.unitn.repoman.core.lang.traversals.generic;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class NodeContainmentTraversal extends DFSTraversal {
private boolean isFound = false;
private final ParseTree soughtNode;
public NodeContainmentTraversal(ParserRuleContext root, ParseTree node) {
soughtNode = node;
traverse(root);
}
@Override
public void onEnterNode(ParseTree node) {
if (node.equals(soughtNode)) {
isFound = true;
terminate();
}
}
public boolean isFound() {
return isFound;
}
}

View File

@ -0,0 +1,56 @@
package it.unitn.repoman.core.lang.traversals.generic;
import java.util.Set;
import java.util.HashSet;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class ScopesTraversal extends DFSTraversal {
private Set<ParserRuleContext> fields = new HashSet<>();
private Set<ParserRuleContext> methods = new HashSet<>();
private int currentLine = 0;
private int totalLines = 0;
private final Set<Integer> collectableLines = new HashSet<>();
public ScopesTraversal(ParserRuleContext root) {
traverse(root);
}
@Override
public void onEnterNode(ParseTree node) {
//collect all "collectable" lines
if (wrapper.isCollectable(node)) {
int line = ((ParserRuleContext)node).getStart().getLine();
this.collectableLines.add(line);
}
if (wrapper.isRuleContext(node)) {
int lookupLine = ((ParserRuleContext)node).getStart().getLine();
if (currentLine != lookupLine) {
currentLine = lookupLine;
this.totalLines++;
}
}
if (wrapper.isFieldDeclaration(node)) {
fields.add((ParserRuleContext)node);
}
if (wrapper.isMethodDeclaration(node)) {
methods.add((ParserRuleContext)node);
}
}
public Set<ParserRuleContext> getScopes() {
return this.methods;
}
public Set<ParserRuleContext> getFields() {
return this.fields;
}
public int getTotalLinesCount() {
return this.totalLines;
}
public Set<Integer> getCollectableLines() {
return this.collectableLines;
}
}

View File

@ -0,0 +1,39 @@
package it.unitn.repoman.core.lang.traversals.generic;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import it.unitn.repoman.core.exceptions.InvalidLineException;
public final class SeedTraversal extends DFSTraversal {
private ParserRuleContext seedScope = null;
private ParserRuleContext seedStmt = null;
private int seedLine;
public SeedTraversal(int line) {
this.seedLine = line;
}
@Override
public void onEnterNode(ParseTree node) {
if (wrapper.isMethodDeclaration(node)) {
this.seedScope = (ParserRuleContext)node;
}
if (wrapper.isCollectable(node)) {
ParserRuleContext nodeCtx = (ParserRuleContext)node;
if (this.seedStmt == null && nodeCtx.getStart().getLine() == this.seedLine) {
this.seedStmt = (ParserRuleContext)node;
terminate();
}
}
}
public ParserRuleContext getSeedScope() throws InvalidLineException {
return this.seedScope;
}
public ParserRuleContext getSeedStmt() throws InvalidLineException {
return this.seedStmt;
}
}

View File

@ -0,0 +1,31 @@
package it.unitn.repoman.core.lang.traversals.generic;
import java.util.LinkedHashSet;
import java.util.Set;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class StatementMappingTraversal extends DFSTraversal {
private final Set<ParserRuleContext> methodDeclarations = new LinkedHashSet<>();
private final Set<ParserRuleContext> statements = new LinkedHashSet<>();
@Override
public void onEnterNode(ParseTree node) {
if (wrapper.isCollectable(node)) {
this.statements.add((ParserRuleContext) node);
}
else if (wrapper.isMethodDeclaration(node)) {
this.methodDeclarations.add((ParserRuleContext) node);
}
}
public Set<ParserRuleContext> getStatements() {
return this.statements;
}
public Set<ParserRuleContext> getMethodDeclarations() {
return this.methodDeclarations;
}
}

View File

@ -0,0 +1,42 @@
package it.unitn.repoman.core.lang.traversals.generic;
import java.util.LinkedHashSet;
import java.util.Set;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class SymbolExtractTraversal extends DFSTraversal {
private Set<ParseTree> symbols = new LinkedHashSet<>();
public SymbolExtractTraversal(ParserRuleContext ctx) {
MethodCallTraversal t = wrapper.getMethodCallTraversal(ctx);
if (!t.isMethodCall()) {
traverse(ctx);
}
else {
this.symbols.addAll(t.getParams());
DotSymbolTraversal dott = new DotSymbolTraversal(t.getCallNameNode());
symbols.addAll(dott.getLeftNodes());
}
}
@Override
public void onEnterNode(ParseTree node) {
if (isWithinContext(node) && wrapper.isToken(node) && wrapper.isToken(node)) {
symbols.add(node);
}
}
@Override
protected boolean isWithinContext(ParseTree node) {
return wrapper.isTerminal(node);
}
public Set<ParseTree> getSymbols() {
return this.symbols;
}
}

View File

@ -0,0 +1,9 @@
package it.unitn.repoman.core.lang.traversals.generic;
import org.antlr.v4.runtime.tree.ParseTree;
public interface Traversal {
void traverse(ParseTree startNode);
void onEnterNode(ParseTree node);
void onExitNode(ParseTree node);
}

View File

@ -0,0 +1,125 @@
package it.unitn.repoman.core.lang.traversals.java;
import java.util.HashSet;
import java.util.Set;
import it.unitn.repoman.core.lang.traversals.generic.DFSTraversal;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import it.unitn.repoman.core.lang.parsers.java.JavaParser;
public class JavaAPISignatureTraversal extends DFSTraversal {
protected final Set<String> signatures = new HashSet<>();
public JavaAPISignatureTraversal(ParseTree node) {
traverse(node);
}
@Override
public void onEnterNode(ParseTree node) {
if (wrapper.isMethodDeclaration(node)) {
ParserRuleContext method = (ParserRuleContext) node;
this.signatures.add(getMethodSignature(method));
}
}
public String getMethodSignature(ParserRuleContext method) {
StringBuilder builder = new StringBuilder();
if (wrapper.isMethodDeclaration(method)) {
ParserRuleContext declRoot = method.getParent().getParent();
for (int i=0; i<declRoot.getChildCount(); i++) {
ParseTree node = declRoot.getChild(i);
if (node.getClass().equals(JavaParser.ModifierContext.class)) {
builder.append(node.getText());
}
}
for (int i=0; i<method.getChildCount(); i++) {
ParseTree node = method.getChild(i);
if (wrapper.isTerminal(node) || node.getClass().equals(JavaParser.TypeTypeContext.class)
|| node.getClass().equals(JavaParser.FormalParametersContext.class)) {
builder.append(node.getText());
}
}
return refineSignature(builder.toString());
}
return "";
}
public boolean methodSignatureExists(String signature) {
signature = refineSignature(signature);
for (String s : signatures) {
if (s.equals(signature)) {
return true;
}
}
return false;
}
public boolean isPublicMethod(String signature) {
signature = refineSignature(signature);
return signature.startsWith("public");
}
public boolean isProtectedMethod(String signature) {
signature = refineSignature(signature);
return signature.startsWith("protected");
}
public boolean isPrivateMethod(String signature) {
signature = refineSignature(signature);
return signature.startsWith("private");
}
protected String refineSignature(String signature) {
int closingBracketPosition = signature.indexOf(")");
if (closingBracketPosition != -1) {
return signature.replace(signature.substring(signature.indexOf(")")), ")").replace("@Override", "");
}
return signature;
}
public int getSignaturesCount() {
return this.signatures.size();
}
public Set<String> getPublicSignatures() {
Set<String> s = new HashSet<>();
for (String signature : this.signatures) {
if (this.isPublicMethod(signature)) {
s.add(signature);
}
}
return s;
}
public Set<String> getProtectedSignatures() {
Set<String> s = new HashSet<>();
for (String signature : this.signatures) {
if (this.isProtectedMethod(signature)) {
s.add(signature);
}
}
return s;
}
public Set<String> getPrivateSignatures() {
Set<String> s = new HashSet<>();
for (String signature : this.signatures) {
if (this.isPrivateMethod(signature)) {
s.add(signature);
}
}
return s;
}
public Set<String> getSignatures() {
return this.signatures;
}
public int getPublicSignaturesCount() {
return this.getPublicSignatures().size();
}
}

View File

@ -0,0 +1,114 @@
package it.unitn.repoman.core.lang.traversals.java;
import java.util.LinkedList;
import java.util.List;
import it.unitn.repoman.core.lang.traversals.generic.DotSymbolTraversal;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import it.unitn.repoman.core.lang.traversals.generic.DFSTraversal;
import it.unitn.repoman.core.lang.parsers.java.JavaParser;
import org.antlr.v4.runtime.tree.ParseTree;
public class JavaMethodCallTraversal extends MethodCallTraversal {
public JavaMethodCallTraversal(ParseTree node) {
super(node);
}
private class ParamsTraversal extends DFSTraversal {
private List<ParseTree> params = new LinkedList<>();
@Override
public void onEnterNode(ParseTree node) {
if (node.getClass().equals(JavaParser.ExpressionContext.class) &&
node.getParent().getClass().equals(JavaParser.ExpressionListContext.class)) {
SingleParamTraversal t = new SingleParamTraversal();
t.traverse(node);
if (t.paramName != null) {
params.add(t.paramName);
}
}
}
}
private class SingleParamTraversal extends DFSTraversal {
private ParseTree paramName = null;
@Override
public void onEnterNode(ParseTree node) {
if (wrapper.isTerminal(node) && wrapper.isToken(node)) {
paramName = node;
terminate();
}
}
}
@Override
public void onEnterNode(ParseTree node) {
skip--;
if (node.getClass().equals(JavaParser.LocalVariableDeclarationContext.class)) {
skip = 10;
}
if (node.getClass().equals(JavaParser.StatementExpressionContext.class)) {
if (node.getChild(0).getChild(1).getText().equals("(")) {
skip = 1;
}
else {
skip = 6;
}
}
else if (node.getClass().equals(JavaParser.ExpressionContext.class)) {
if (node.getChild(1) != null && node.getChild(1).getText().equals("(")) {
skip = 0;
}
else {
skip = 5;
}
}
if (skip == 0) {
try {
this.methodContext = node;
this.callNameNode = node.getChild(0);
ParseTree lbrace = node.getChild(1);
this.paramsNode = node.getChild(2);
ParseTree rbrace = node.getChild(3);
if (lbrace.getText().equals("(")) {
if (paramsNode.getText().equals(")")) {
this.isMethodCall = true;
paramsNode = null;
} else if (rbrace.getText().equals(")")) {
this.isMethodCall = true;
}
}
if (paramsNode != null) {
ParamsTraversal pt = new ParamsTraversal();
pt.traverse(paramsNode);
for (ParseTree param : pt.params) {
if (wrapper.isToken(param)) {
this.params.add(param);
}
}
}
}
catch (NullPointerException e) {
this.isMethodCall = false;
}
finally {
terminate();
}
}
}
@Override
public String getMethodName() {
if (callNameNode != null) {
DotSymbolTraversal t = new DotSymbolTraversal(callNameNode);
return t.getRightmostNodeName();
}
return "";
}
}

View File

@ -0,0 +1,103 @@
package it.unitn.repoman.core.lang.wrappers.c;
import it.unitn.repoman.core.lang.traversals.c.CMethodCallTraversal;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import it.unitn.repoman.core.lang.wrappers.generic.Wrapper;
import it.unitn.repoman.core.lang.parsers.c.CParser;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;
public class CWrapper extends Wrapper {
public CWrapper() {
this.restrictedKeywords = new String[]{ "return", "true", "false"};
}
@Override
public boolean isStatement(ParseTree node) {
return node instanceof CParser.DeclarationContext ||
node instanceof CParser.ExpressionStatementContext;
}
@Override
public boolean isReturnStatement(ParseTree node) {
return (node instanceof CParser.JumpStatementContext && node.getChild(0).getText().equals("return"));
}
@Override
public boolean isConditionalExpression(ParseTree node) {
return (node instanceof CParser.ExpressionContext &&
node.getParent() instanceof CParser.SelectionStatementContext);
}
@Override
public boolean isMethodDeclaration(ParseTree node) {
return node instanceof CParser.FunctionDefinitionContext;
}
@Override
public boolean isFieldDeclaration(ParseTree node) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isToken(ParseTree node) {
Pattern pattern = Pattern.compile(this.validVarNameRegex);
Matcher matcher = pattern.matcher(node.getText());
return (!isRestrictedKeyword(node) && matcher.matches() &&
node instanceof TerminalNodeImpl);
}
@Override
public boolean isFormalParameter(ParseTree node) {
return node instanceof CParser.DeclaratorContext &&
node.getParent() instanceof CParser.ParameterDeclarationContext;
}
@Override
protected String getMethodDeclarationName(ParseTree node) {
return node.getChild(1).getChild(0).getChild(0).getText();
}
@Override
protected ParseTree getMethodDeclarationParams(ParseTree node) {
return node.getChild(1).getChild(0).getChild(2);
}
@Override
public MethodCallTraversal getMethodCallTraversal(ParseTree node) {
return new CMethodCallTraversal(node);
}
@Override
public boolean isTerminal(ParseTree node) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isLocalVariableDeclaration(ParseTree node) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAssignmentExpression(ParseTree node) {
// TODO Auto-generated method stub
return false;
}
// TODO: implement the method
@Override
public boolean isPartOfExpression(ParseTree node) {
return false;
}
}

View File

@ -0,0 +1,137 @@
package it.unitn.repoman.core.lang.wrappers.generic;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import it.unitn.repoman.core.lang.traversals.generic.SymbolExtractTraversal;
import it.unitn.repoman.core.lang.traversals.generic.AssignmentSymbolExtractTraversal;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public abstract class Wrapper {
protected String validVarNameRegex = "[A-Za-z_][A-Za-z_0-9]*$";
protected String[] restrictedKeywords = {""};
public abstract boolean isTerminal(ParseTree node);
public abstract boolean isStatement(ParseTree node);
public abstract boolean isLocalVariableDeclaration(ParseTree node);
public abstract boolean isAssignmentExpression(ParseTree node);
public abstract boolean isPartOfExpression(ParseTree node);
public abstract boolean isReturnStatement(ParseTree node);
public abstract boolean isConditionalExpression(ParseTree node);
public abstract boolean isMethodDeclaration(ParseTree node);
public abstract boolean isFieldDeclaration(ParseTree node);
public abstract boolean isToken(ParseTree node);
public abstract boolean isFormalParameter(ParseTree node);
protected abstract String getMethodDeclarationName(ParseTree node);
protected abstract ParseTree getMethodDeclarationParams(ParseTree node);
public boolean isClassDeclaration(ParseTree node) {
return false;
}
public boolean isTypeDeclaration(ParseTree node) {
return false;
}
public boolean isCollectable(ParseTree node) {
if (!(node instanceof ParserRuleContext)) {
return false;
}
return (this.isStatement(node) ||
this.isConditionalExpression(node) ||
this.isReturnStatement(node) ||
this.isFieldDeclaration(node));
}
public boolean isRuleContext(ParseTree node) {
return node instanceof ParserRuleContext;
}
protected boolean isRestrictedKeyword(ParseTree node) {
for (int i = 0; i < this.restrictedKeywords.length; i++) {
if (this.restrictedKeywords[i].equals(node.getText())) {
return true;
}
}
return false;
}
public ParseTree getDefinedVar(ParserRuleContext stmt) {
ParseTree defVar = null;
if (this.isLocalVariableDeclaration(stmt) || this.isAssignmentExpression(stmt) ||
this.isFieldDeclaration(stmt)) {
AssignmentSymbolExtractTraversal traversal = new AssignmentSymbolExtractTraversal(stmt);
defVar = traversal.getLhs();
}
return defVar;
}
public Set<ParseTree> getReferencedVars(ParserRuleContext stmt) {
Set<ParseTree> refVars = new LinkedHashSet<>();
if (isLocalVariableDeclaration(stmt) || isAssignmentExpression(stmt) || isFieldDeclaration(stmt)) {
AssignmentSymbolExtractTraversal traversal = new AssignmentSymbolExtractTraversal(stmt);
for (ParseTree var : traversal.getRhsList()) {
refVars.add(var);
}
}
else if (isConditionalExpression(stmt) || isMethodCall(stmt) || isReturnStatement(stmt)) {
SymbolExtractTraversal traversal = new SymbolExtractTraversal(stmt);
for (ParseTree var : traversal.getSymbols()) {
refVars.add(var);
}
}
return refVars;
}
public ParserRuleContext getContainer(ParseTree ctx) {
ParseTree c = ctx.getParent();
while (!isTypeDeclaration(c)) {
if (isMethodDeclaration(c)) {
return (ParserRuleContext)c;
}
c = c.getParent();
}
return (ParserRuleContext)c;
}
public boolean precedes(ParserRuleContext stmt1, ParserRuleContext stmt2) {
if (stmt1 == null || stmt2 == null) {
return false;
}
return (stmt1.getStart().getLine() < stmt2.getStart().getLine());
}
public Collection<? extends ParseTree> getExternalSeeds(ParseTree method, ParseTree decl) {
// TODO Auto-generated method stub
final Set<ParseTree> seeds = new HashSet<>();
return seeds;
}
public abstract MethodCallTraversal getMethodCallTraversal(ParseTree node);
public boolean isMethodCall(ParseTree stmt) {
MethodCallTraversal traversal = this.getMethodCallTraversal(stmt);
return traversal.isMethodCall();
}
}

View File

@ -0,0 +1,114 @@
package it.unitn.repoman.core.lang.wrappers.java;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import it.unitn.repoman.core.lang.wrappers.generic.Wrapper;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;
import it.unitn.repoman.core.lang.traversals.java.JavaMethodCallTraversal;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import it.unitn.repoman.core.lang.parsers.java.JavaParser;
public class JavaWrapper extends Wrapper {
public JavaWrapper() {
this.restrictedKeywords = new String[]{"true", "false", "return", "null", "new", "this"};
}
@Override
public boolean isStatement(ParseTree node) {
return node.getClass().equals(JavaParser.StatementExpressionContext.class) ||
node.getClass().equals(JavaParser.LocalVariableDeclarationContext.class) ||
node.getClass().equals(JavaParser.FieldDeclarationContext.class);
}
@Override
public boolean isReturnStatement(ParseTree node) {
return (node.getClass().equals(JavaParser.StatementContext.class) && node.getChild(0).getText().equals("return"));
}
@Override
public boolean isConditionalExpression(ParseTree node) {
return node.getClass().equals(JavaParser.ParExpressionContext.class);
}
@Override
public boolean isMethodDeclaration(ParseTree node) {
return node.getClass().equals(JavaParser.MethodDeclarationContext.class);
}
@Override
public boolean isClassDeclaration(ParseTree node) {
return node.getClass().equals(JavaParser.ClassDeclarationContext.class);
}
@Override
public boolean isTypeDeclaration(ParseTree node) {
return node.getClass().equals(JavaParser.TypeDeclarationContext.class);
}
@Override
public boolean isFieldDeclaration(ParseTree node) {
return node.getClass().equals(JavaParser.FieldDeclarationContext.class);
}
@Override
public boolean isToken(ParseTree node) {
Pattern pattern = Pattern.compile(this.validVarNameRegex);
Matcher matcher = pattern.matcher(node.getText());
return (!isRestrictedKeyword(node) && matcher.matches() &&
!(node.getParent().getClass().equals(JavaParser.ClassOrInterfaceTypeContext.class)) &&
!(node.getParent().getClass().equals(JavaParser.PrimitiveTypeContext.class)));
}
@Override
public boolean isFormalParameter(ParseTree node) {
return node.getClass().equals(JavaParser.FormalParameterContext.class);
}
@Override
protected String getMethodDeclarationName(ParseTree node) {
return node.getChild(1).getText();
}
@Override
protected ParseTree getMethodDeclarationParams(ParseTree node) {
return node.getChild(2).getChild(1);
}
@Override
public MethodCallTraversal getMethodCallTraversal(ParseTree node) {
return new JavaMethodCallTraversal(node.getParent());
}
@Override
public boolean isTerminal(ParseTree node) {
return node.getClass().equals(TerminalNodeImpl.class);
}
@Override
public boolean isLocalVariableDeclaration(ParseTree node) {
return node.getClass().equals(JavaParser.LocalVariableDeclarationContext.class);
}
@Override
public boolean isAssignmentExpression(ParseTree node) {
if (node.getClass().equals(JavaParser.StatementExpressionContext.class)) {
ParseTree child = node.getChild(0);
if (child.getChildCount() > 1) {
child = child.getChild(1);
if (child.getText().equals("=")) {
return true;
}
}
}
return false;
}
@Override
public boolean isPartOfExpression(ParseTree node) {
return node.getClass().equals(JavaParser.ExpressionContext.class);
}
}

View File

@ -0,0 +1,124 @@
package it.unitn.repoman.core.slicers;
import java.util.*;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import it.unitn.repoman.core.lang.traversals.generic.MethodDeclarationTraversal;
import it.unitn.repoman.core.slicers.tainters.BackwardTainter;
import it.unitn.repoman.core.slicers.tainters.ForwardTainter;
import it.unitn.repoman.core.slicers.tainters.TaintedVariableSet;
import org.antlr.v4.runtime.ParserRuleContext;
import it.unitn.repoman.core.lang.traversals.generic.StatementMappingTraversal;
import org.antlr.v4.runtime.tree.ParseTree;
public class LightweightSlice {
protected final ParserRuleContext root;
protected final Set<Integer> selectedLines = new LinkedHashSet<>();
protected final Set<ParserRuleContext> collectables;
protected final Set<ParserRuleContext> methodDeclarations;
public LightweightSlice(ParserRuleContext root, Set<Integer> lines) throws Exception {
this.root = root;
StatementMappingTraversal statementGetter = new StatementMappingTraversal();
statementGetter.traverse(this.root);
collectables = statementGetter.getStatements();
methodDeclarations = statementGetter.getMethodDeclarations();
Set<Integer> toAdd = new LinkedHashSet<>();
toAdd.addAll(makePass(lines));
selectedLines.addAll(toAdd);
}
protected Set<Integer> makePass(Set<Integer> lines) {
Set<Integer> matchedLines = new LinkedHashSet<>();
Set<ParserRuleContext> statements = new LinkedHashSet<>();
for (ParserRuleContext stmt : collectables) {
if (lines.contains(stmt.getStart().getLine())) {
statements.add(stmt);
}
}
ForwardTainter forwardTainter = new ForwardTainter(collectables, statements);
matchedLines.addAll(forwardTainter.getCollectedLines());
BackwardTainter backwardTainter = new BackwardTainter(collectables, statements);
matchedLines.addAll(backwardTainter.getCollectedLines());
/* TODO: Experimental
Set<Integer> inter = propagrateForwardTaint(collectables, methodDeclarations, forwardTainter);
matchedLines.addAll(inter);
*/
return matchedLines;
}
// TODO: Experimental
protected Set<Integer> propagrateForwardTaint(Set<ParserRuleContext> collectables, Set<ParserRuleContext> methodDeclarations, ForwardTainter forwardTainter) {
Set<Integer> collected = new LinkedHashSet<>();
// get intra-procedural tainted variables
TaintedVariableSet taintedVars = forwardTainter.getTaintedVars();
// get intra-procedural tainted method calls
Set<ParserRuleContext> taintedMethodCalls = forwardTainter.getTaintedMethodCalls();
// match a tainted method call to the corresponding method declaration
for (ParserRuleContext tmc : taintedMethodCalls) {
MethodCallTraversal t1 = LanguageFactory.getWrapper().getMethodCallTraversal(tmc);
String methodCallName = t1.getMethodName();
for (ParserRuleContext md : methodDeclarations) {
MethodDeclarationTraversal t2 = new MethodDeclarationTraversal(md);
String methodDeclName = t2.getMethodName();
if (methodCallName.equals(methodDeclName) && t1.getParamsNumber() == t2.getParamsNumber()) {
// ---------------- inter-procedural "expansion" goes here ----------------------------------------
// get tainted variables for the method call statement
List<ParseTree> vars = forwardTainter.getTaintedVars().getStatementVariables((ParserRuleContext) t1.getMethodContextNode());
// keep only tainted parameters
List<String> taintedParams = new LinkedList<>();
List<String> params = t1.getParamNames();
for (int i=0; i<t1.getParamsNumber(); i++) {
String param = t1.getParamName(i);
boolean match = false;
for (ParseTree var : vars) {
if (param.equals(var.getText())) {
match = true;
break;
}
}
if (match) {
taintedParams.add(param);
}
else {
taintedParams.add("NOT_TAINTED");
}
}
// match tainted parameters to aliases in the method declaration
List<ParseTree> matchedTaintedParams = new LinkedList<>();
for (int i=0; i<taintedParams.size(); i++) {
String callParam = taintedParams.get(i);
String declParam = t2.getParamNames().get(i);
if (!callParam.equals("NOT_TAINTED")) {
matchedTaintedParams.add(t2.getParamNode(i));
}
}
// taint relevant stuff within the method declaration...
ForwardTainter expandedFt = new ForwardTainter(collectables, matchedTaintedParams);
collected.addAll(expandedFt.getCollectedLines());
break;
}
}
}
return collected;
}
public Set<Integer> getSelectedLines() {
return this.selectedLines;
}
}

View File

@ -0,0 +1,35 @@
package it.unitn.repoman.core.slicers;
import it.unitn.repoman.core.slicers.tainters.BackwardTainterPessimist;
import it.unitn.repoman.core.slicers.tainters.ForwardTainterPessimist;
import org.antlr.v4.runtime.ParserRuleContext;
import java.util.LinkedHashSet;
import java.util.Set;
public class LightweightSlicePessimist extends LightweightSlice {
public LightweightSlicePessimist(ParserRuleContext root, Set<Integer> lines) throws Exception {
super(root, lines);
}
@Override
protected Set<Integer> makePass(Set<Integer> lines) {
Set<Integer> matchedLines = new LinkedHashSet<>();
Set<ParserRuleContext> statements = new LinkedHashSet<>();
for (ParserRuleContext stmt : collectables) {
if (lines.contains(stmt.getStart().getLine())) {
statements.add(stmt);
}
}
ForwardTainterPessimist forwardTainter = new ForwardTainterPessimist(collectables, statements);
matchedLines.addAll(forwardTainter.getCollectedLines());
BackwardTainterPessimist backwardTainter = new BackwardTainterPessimist(collectables, statements);
matchedLines.addAll(backwardTainter.getCollectedLines());
return matchedLines;
}
}

View File

@ -0,0 +1,73 @@
package it.unitn.repoman.core.slicers.tainters;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.lang.wrappers.generic.Wrapper;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import java.util.*;
public abstract class AbstractTainter {
protected final Wrapper wrapper = LanguageFactory.getWrapper();
protected final Set<ParserRuleContext> collectables;
protected final TaintedVariableSet taints = new TaintedVariableSet();
protected final Set<ParserRuleContext> taintedStatements = new LinkedHashSet<>();
public AbstractTainter(Set<ParserRuleContext> collectables, List<ParseTree> taintedVars) {
this.collectables = collectables;
Set<ParserRuleContext> seeds = new LinkedHashSet<>();
for (ParseTree taintedVar : taintedVars) {
ParserRuleContext taintedVarScope = wrapper.getContainer(taintedVar);
taints.addTaintedVariable(taintedVarScope, taintedVar);
for (ParserRuleContext collectable : collectables) {
ParserRuleContext collectableScope = wrapper.getContainer(collectable);
if (taintedVarScope.equals(collectableScope)) {
Set<ParseTree> referencedVars = wrapper.getReferencedVars(collectable);
for (ParseTree refVar : referencedVars) {
if (refVar.getText().equals(taintedVar.getText())) {
seeds.add(collectable);
taints.addTaintedVariable(collectableScope, refVar);
}
}
}
}
}
initSeeds(seeds);
expand();
}
public AbstractTainter(Set<ParserRuleContext> collectables, Set<ParserRuleContext> seeds) {
this.collectables = collectables;
initSeeds(seeds);
expand();
}
protected void expand() {
Queue<ParserRuleContext> q = new LinkedList<>();
q.addAll(taintedStatements);
while (!q.isEmpty()) {
ParserRuleContext stmt = q.poll();
Set<ParserRuleContext> growths = iterate(stmt);
taintedStatements.add(stmt);
q.addAll(growths);
}
}
public Set<Integer> getCollectedLines() {
Set<Integer> lineNumbers = new LinkedHashSet<>();
for (ParserRuleContext stmt : this.taintedStatements) {
lineNumbers.add(stmt.getStart().getLine());
}
return lineNumbers;
}
public TaintedVariableSet getTaintedVars() {
return this.taints;
}
protected abstract void initSeeds(Set<ParserRuleContext> seeds);
public abstract Set<ParserRuleContext> iterate(ParserRuleContext taintedStmt);
}

View File

@ -0,0 +1,75 @@
package it.unitn.repoman.core.slicers.tainters;
import java.util.*;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import it.unitn.repoman.core.lang.traversals.generic.ConditionTraversal;
public class BackwardTainter extends ForwardTainter {
public BackwardTainter(Set<ParserRuleContext> collectables, Set<ParserRuleContext> seeds) {
super(collectables, seeds);
}
@Override
protected void initSeed(ParserRuleContext stmt) {
this.taintedStatements.add(stmt);
ParserRuleContext scope = wrapper.getContainer(stmt);
Set<ParseTree> refVars = wrapper.getReferencedVars(stmt);
for (ParseTree refVar : refVars) {
this.taints.addTaintedVariable(scope, refVar);
}
ParseTree defVar = wrapper.getDefinedVar(stmt);
if (defVar != null) {
this.taints.addTaintedVariable(scope, defVar);
}
}
@Override
public Set<ParserRuleContext> iterate(ParserRuleContext taintedStmt) {
Set<ParserRuleContext> elementsToAdd = new LinkedHashSet<>();
ParserRuleContext taintedScope = wrapper.getContainer(taintedStmt);
LinkedList<ParserRuleContext> list = new LinkedList<>(this.collectables);
Iterator<ParserRuleContext> backwardIter = list.descendingIterator();
while (backwardIter.hasNext()) {
ParserRuleContext collectable = backwardIter.next();
if (taintedStatements.contains(collectable)) {
continue;
}
ParserRuleContext collectableScope = wrapper.getContainer(collectable);
if (collectableScope.equals(taintedScope) && wrapper.precedes(collectable, taintedStmt)) {
Set<String> taintedVars = this.taints.getVariableNames(collectableScope);
// if the seed is an inner statement of a conditional statement, take the conditional statement-----
if (wrapper.isConditionalExpression(collectable)) {
ConditionTraversal t = new ConditionTraversal(collectable);
for (ParserRuleContext innerStmt : t.getInnerStatements()) {
if (this.taintedStatements.contains(innerStmt) || elementsToAdd.contains(innerStmt)) {
elementsToAdd.add(collectable);
Set<ParseTree> referencedVars = wrapper.getReferencedVars(collectable);
for (ParseTree referencedVar : referencedVars) {
taints.addTaintedVariable(collectableScope, referencedVar);
}
break;
}
}
}
else {
ParseTree definedVar = wrapper.getDefinedVar(collectable);
if (definedVar != null) {
if (taintedVars.contains(definedVar.getText())) {
elementsToAdd.add(collectable);
Set<ParseTree> referencedVars = wrapper.getReferencedVars(collectable);
for (ParseTree referencedVar : referencedVars) {
taints.addTaintedVariable(collectableScope, referencedVar);
}
}
}
}
}
}
return elementsToAdd;
}
}

View File

@ -0,0 +1,104 @@
package it.unitn.repoman.core.slicers.tainters;
import it.unitn.repoman.core.lang.traversals.generic.ConditionTraversal;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import java.util.*;
public class BackwardTainterPessimist extends BackwardTainter {
public BackwardTainterPessimist(Set<ParserRuleContext> collectables, Set<ParserRuleContext> seeds) {
super(collectables, seeds);
}
@Override
protected void initSeed(ParserRuleContext stmt) {
this.taintedStatements.add(stmt);
ParserRuleContext scope = wrapper.getContainer(stmt);
Set<ParseTree> refVars = wrapper.getReferencedVars(stmt);
for (ParseTree refVar : refVars) {
this.taints.addTaintedVariable(scope, refVar);
}
ParseTree defVar = wrapper.getDefinedVar(stmt);
if (defVar != null) {
this.taints.addTaintedVariable(scope, defVar);
}
/*
* THIS SHOULD NOT HAPPEN IN AN "EFFECT-FREE" SLICE!
* taint ref. variables in a method call as well */
if (wrapper.isMethodCall(stmt)) {
for (ParseTree var : wrapper.getReferencedVars(stmt)) {
this.taints.addTaintedVariable(scope, var);
}
}
}
@Override
public Set<ParserRuleContext> iterate(ParserRuleContext taintedStmt) {
Set<ParserRuleContext> elementsToAdd = new LinkedHashSet<>();
ParserRuleContext taintedScope = wrapper.getContainer(taintedStmt);
LinkedList<ParserRuleContext> list = new LinkedList<>(this.collectables);
Iterator<ParserRuleContext> backwardIter = list.descendingIterator();
while (backwardIter.hasNext()) {
ParserRuleContext collectable = backwardIter.next();
if (taintedStatements.contains(collectable)) {
continue;
}
ParserRuleContext collectableScope = wrapper.getContainer(collectable);
if (collectableScope.equals(taintedScope) && wrapper.precedes(collectable, taintedStmt)) {
Set<String> taintedVars = this.taints.getVariableNames(collectableScope);
// if the seed is an inner statement of a conditional statement, take the conditional statement-----
if (wrapper.isConditionalExpression(collectable)) {
ConditionTraversal t = new ConditionTraversal(collectable);
for (ParserRuleContext innerStmt : t.getInnerStatements()) {
if (this.taintedStatements.contains(innerStmt) || elementsToAdd.contains(innerStmt)) {
elementsToAdd.add(collectable);
Set<ParseTree> referencedVars = wrapper.getReferencedVars(collectable);
for (ParseTree referencedVar : referencedVars) {
taints.addTaintedVariable(collectableScope, referencedVar);
}
break;
}
}
}
else {
ParseTree definedVar = wrapper.getDefinedVar(collectable);
if (definedVar != null) {
if (taintedVars.contains(definedVar.getText())) {
elementsToAdd.add(collectable);
Set<ParseTree> referencedVars = wrapper.getReferencedVars(collectable);
for (ParseTree referencedVar : referencedVars) {
taints.addTaintedVariable(collectableScope, referencedVar);
}
}
}
if (wrapper.isMethodCall(collectable)) {
MethodCallTraversal t = wrapper.getMethodCallTraversal(collectable);
List<ParseTree> vars = t.getParams();
boolean tainted = false;
for (ParseTree var : vars) {
if (taintedVars.contains(var.getText())) {
tainted = true;
break;
}
}
if (tainted) {
for (ParseTree var : vars) {
taints.addTaintedVariable(collectableScope, var);
}
taintedStatements.add(collectable);
}
}
}
}
}
return elementsToAdd;
}
}

View File

@ -0,0 +1,140 @@
package it.unitn.repoman.core.slicers.tainters;
import java.util.*;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import it.unitn.repoman.core.lang.traversals.generic.ConditionTraversal;
public class ForwardTainter extends AbstractTainter {
protected final Set<ParserRuleContext> taintedMethodCalls = new LinkedHashSet<>();
public ForwardTainter(Set<ParserRuleContext> collectables, Set<ParserRuleContext> seeds) {
super(collectables, seeds);
}
public ForwardTainter(Set<ParserRuleContext> collectables, List<ParseTree> taintedVars) {
super(collectables, taintedVars);
}
@Override
protected void initSeeds(Set<ParserRuleContext> seeds) {
for (ParserRuleContext seed : seeds) {
this.initSeed(seed);
}
}
@Override
public Set<ParserRuleContext> iterate(ParserRuleContext taintedStmt) {
Set<ParserRuleContext> elementsToAdd = new LinkedHashSet<>();
ParserRuleContext taintedScope = wrapper.getContainer(taintedStmt);
for (ParserRuleContext collectable: this.collectables) {
// do nothing if a statement is already collected
if (taintedStatements.contains(collectable)) {
continue;
}
ParserRuleContext collectableScope = wrapper.getContainer(collectable);
if (collectableScope.equals(taintedScope) && wrapper.precedes(taintedStmt, collectable)) {
Set<String> taintedVars = this.taints.getVariableNames(collectableScope);
Set<ParseTree> referencedVars = wrapper.getReferencedVars(collectable);
MethodCallTraversal t = wrapper.getMethodCallTraversal(collectable);
if (t.isMethodCall()) {
List<ParseTree> vars = t.getParams();
for (ParseTree var : vars) {
if (taintedVars.contains(var.getText())) {
taints.addTaintedVariable(collectableScope, var);
}
}
}
for (ParseTree referencedVar : referencedVars) {
if (taintedVars.contains(referencedVar.getText())) {
elementsToAdd.add(collectable);
ParseTree definedVar = wrapper.getDefinedVar(collectable);
if (definedVar != null) {
taints.addTaintedVariable(collectableScope, definedVar);
}
}
}
}
}
Set<ParserRuleContext> taintedInnerStatements = new HashSet<>();
for (ParserRuleContext ctx : elementsToAdd) {
if (wrapper.isConditionalExpression(ctx)) {
taintedInnerStatements.addAll(taintInnerStatements(ctx));
}
}
elementsToAdd.addAll(taintedInnerStatements);
return elementsToAdd;
}
protected void initSeed(ParserRuleContext stmt) {
this.taintedStatements.add(stmt);
ParserRuleContext scope = wrapper.getContainer(stmt);
ParseTree defVar = wrapper.getDefinedVar(stmt);
if (defVar != null) {
this.taints.addTaintedVariable(scope, defVar);
}
/*
* THIS SHOULD NOT HAPPEN IN AN "EFFECT-FREE" SLICE!
* taint ref. variables in a method call as well
if (wrapper.isMethodCall(stmt)) {
for (ParseTree var : wrapper.getReferencedVars(stmt)) {
this.taints.addTaintedVariable(scope, var);
}
}
*/
// if the seed is a conditional statement or a return statement, take all inner statements
else if (wrapper.isConditionalExpression(stmt)) {
this.taintedStatements.addAll(taintConditionalExpression(stmt));
// and taint all variables within the condition
Set<ParseTree> vars = wrapper.getReferencedVars(stmt);
for (ParseTree var : vars) {
taints.addTaintedVariable(scope, var);
}
}
}
protected Set<ParserRuleContext> taintInnerStatements(ParserRuleContext cnd) {
Set<ParserRuleContext> addedStmts = new HashSet<>();
ConditionTraversal t = new ConditionTraversal(cnd);
for (ParserRuleContext innerStmt : t.getInnerStatements()) {
ParseTree defVar = wrapper.getDefinedVar(innerStmt);
if (defVar != null) {
taints.addTaintedVariable(wrapper.getContainer(innerStmt), defVar);
}
addedStmts.add(innerStmt);
}
return addedStmts;
}
protected Set<ParserRuleContext> taintConditionalExpression(ParserRuleContext cnd) {
ConditionTraversal t = new ConditionTraversal(cnd);
Set<ParserRuleContext> addedStmts = new LinkedHashSet<>();
addedStmts.add(cnd);
for (ParserRuleContext innerStmt : t.getInnerStatements()) {
ParseTree innerStmtDefVar = wrapper.getDefinedVar(innerStmt);
if (innerStmtDefVar != null) {
taints.addTaintedVariable(wrapper.getContainer(innerStmt), innerStmtDefVar);
}
addedStmts.add(innerStmt);
}
return addedStmts;
}
public Set<ParserRuleContext> getTaintedMethodCalls() {
if (taintedMethodCalls.size() == 0) {
for (ParserRuleContext ctx : this.collectables) {
if (getCollectedLines().contains(ctx.getStart().getLine())) {
MethodCallTraversal t = wrapper.getMethodCallTraversal(ctx);
if (t.isMethodCall()) {
taintedMethodCalls.add(ctx);
}
}
}
}
return taintedMethodCalls;
}
}

View File

@ -0,0 +1,119 @@
package it.unitn.repoman.core.slicers.tainters;
import it.unitn.repoman.core.lang.traversals.generic.ConditionTraversal;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class ForwardTainterPessimist extends ForwardTainter {
public ForwardTainterPessimist(Set<ParserRuleContext> collectables, Set<ParserRuleContext> seeds) {
super(collectables, seeds);
}
@Override
protected void initSeed(ParserRuleContext stmt) {
this.taintedStatements.add(stmt);
ParserRuleContext scope = wrapper.getContainer(stmt);
ParseTree defVar = wrapper.getDefinedVar(stmt);
if (defVar != null) {
this.taints.addTaintedVariable(scope, defVar);
}
/*
* THIS SHOULD NOT HAPPEN IN AN "EFFECT-FREE" SLICE!
* taint ref. variables in a method call as well */
if (wrapper.isMethodCall(stmt)) {
for (ParseTree var : wrapper.getReferencedVars(stmt)) {
this.taints.addTaintedVariable(scope, var);
}
}
// if the seed is a conditional statement or a return statement, take all inner statements
else if (wrapper.isConditionalExpression(stmt)) {
this.taintedStatements.addAll(taintConditionalExpression(stmt));
// and taint all variables within the condition
Set<ParseTree> vars = wrapper.getReferencedVars(stmt);
for (ParseTree var : vars) {
taints.addTaintedVariable(scope, var);
}
}
}
@Override
public Set<ParserRuleContext> iterate(ParserRuleContext taintedStmt) {
Set<ParserRuleContext> elementsToAdd = new LinkedHashSet<>();
ParserRuleContext taintedScope = wrapper.getContainer(taintedStmt);
for (ParserRuleContext collectable: this.collectables) {
ParserRuleContext collectableScope = wrapper.getContainer(collectable);
// do nothing if a statement is already collected
if (taintedStatements.contains(collectable)) {
if (wrapper.isMethodCall(collectable)) {
for (ParseTree var : wrapper.getReferencedVars(collectable)) {
this.taints.addTaintedVariable(collectableScope, var);
}
}
continue;
}
if (collectableScope.equals(taintedScope) && wrapper.precedes(taintedStmt, collectable)) {
Set<String> taintedVars = this.taints.getVariableNames(collectableScope);
Set<ParseTree> referencedVars = wrapper.getReferencedVars(collectable);
MethodCallTraversal t = wrapper.getMethodCallTraversal(collectable);
if (t.isMethodCall()) {
List<ParseTree> vars = t.getParams();
boolean tainted = false;
for (ParseTree var : vars) {
if (taintedVars.contains(var.getText())) {
tainted = true;
break;
}
}
if (tainted) {
for (ParseTree var : vars) {
taints.addTaintedVariable(collectableScope, var);
}
}
}
for (ParseTree referencedVar : referencedVars) {
if (taintedVars.contains(referencedVar.getText())) {
elementsToAdd.add(collectable);
ParseTree definedVar = wrapper.getDefinedVar(collectable);
if (definedVar != null) {
taints.addTaintedVariable(collectableScope, definedVar);
}
}
}
}
}
Set<ParserRuleContext> taintedInnerStatements = new HashSet<>();
for (ParserRuleContext ctx : elementsToAdd) {
if (wrapper.isConditionalExpression(ctx)) {
taintedInnerStatements.addAll(taintInnerStatements(ctx));
}
}
elementsToAdd.addAll(taintedInnerStatements);
return elementsToAdd;
}
@Override
protected Set<ParserRuleContext> taintInnerStatements(ParserRuleContext cnd) {
Set<ParserRuleContext> addedStmts = new HashSet<>();
ConditionTraversal t = new ConditionTraversal(cnd);
for (ParserRuleContext innerStmt : t.getInnerStatements()) {
ParseTree defVar = wrapper.getDefinedVar(innerStmt);
if (defVar != null) {
taints.addTaintedVariable(wrapper.getContainer(innerStmt), defVar);
}
addedStmts.add(innerStmt);
}
return addedStmts;
}
}

View File

@ -0,0 +1,38 @@
package it.unitn.repoman.core.slicers.tainters;
import it.unitn.repoman.core.lang.traversals.generic.MethodCallTraversal;
import org.antlr.v4.runtime.ParserRuleContext;
import java.util.*;
public class MethodCallTainter extends AbstractTainter {
public MethodCallTainter(Set<ParserRuleContext> collectables, Set<ParserRuleContext> seeds) {
super(collectables, seeds);
}
@Override
protected void initSeeds(Set<ParserRuleContext> seeds) {
this.taintedStatements.addAll(seeds);
}
@Override
public Set<ParserRuleContext> iterate(ParserRuleContext taintedStmt) {
Set<ParserRuleContext> elementsToAdd = new LinkedHashSet<>();
ParserRuleContext taintedScope = wrapper.getContainer(taintedStmt);
for (ParserRuleContext collectable : collectables) {
if (!taintedStatements.contains(collectable)) {
if (wrapper.getContainer(collectable).equals(taintedScope)) {
MethodCallTraversal t = wrapper.getMethodCallTraversal(collectable);
MethodCallTraversal tt = wrapper.getMethodCallTraversal(taintedStmt);
if (t.getMethodName().equals(tt.getMethodName()) && t.getParamsNumber() == tt.getParamsNumber()) {
elementsToAdd.add(collectable);
}
}
}
}
return elementsToAdd;
}
}

View File

@ -0,0 +1,29 @@
package it.unitn.repoman.core.slicers.tainters;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class TaintedVariable {
private final ParseTree variable;
private final ParserRuleContext scope;
public TaintedVariable(ParserRuleContext scope, ParseTree variable) {
this.scope = scope;
this.variable = variable;
}
public ParserRuleContext getScope() {
return this.scope;
}
public ParseTree getVariable() {
return this.variable;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("[" + this.scope.getStart().getLine() + "] -> " + this.variable.getText() + "\n");
return builder.toString();
}
}

View File

@ -0,0 +1,95 @@
package it.unitn.repoman.core.slicers.tainters;
import java.util.*;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.lang.traversals.generic.NodeContainmentTraversal;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
public class TaintedVariableSet {
private final Set<TaintedVariable> taintedVars = new LinkedHashSet<>();
public void addTaintedVariable(TaintedVariable newVariable) {
// for (TaintedVariable var : this.taintedVars) {
// if (var.getScope().equals(newVariable.getScope())
// && var.getVariable().getText().equals(newVariable.getVariable().getText())) {
// return;
// }
// }
for (TaintedVariable var : this.taintedVars) {
if (var.getVariable().equals(newVariable.getVariable())) {
return;
}
}
taintedVars.add(newVariable);
}
public void addTaintedVariable(ParserRuleContext scope, ParseTree variable) {
this.addTaintedVariable((new TaintedVariable(scope, variable)));
}
public Set<String> getVariableNames(ParserRuleContext scope) {
Set<String> vars = new LinkedHashSet<>();
for (TaintedVariable var : this.taintedVars) {
if (var.getScope().equals(scope)) {
vars.add(var.getVariable().getText());
}
}
return vars;
}
public Set<ParseTree> getVariables(ParserRuleContext scope) {
Set<ParseTree> vars = new LinkedHashSet<>();
for (TaintedVariable var : this.taintedVars) {
if (var.getScope().equals(scope)) {
vars.add(var.getVariable());
}
}
return vars;
}
public List<ParseTree> getStatementVariables(ParserRuleContext statement) {
List<ParseTree> vars = new LinkedList<>();
ParserRuleContext scope = LanguageFactory.getWrapper().getContainer(statement);
for (TaintedVariable var : this.taintedVars) {
if (var.getScope().equals(scope)) {
NodeContainmentTraversal t = new NodeContainmentTraversal(statement, var.getVariable());
if (t.isFound()) {
vars.add(var.getVariable());
}
}
}
return vars;
}
// public void removeVariable(ParserRuleContext scope, ParseTree variable) {
// Iterator<TaintedVariable> it = this.taintedVars.iterator();
// while (it.hasNext()) {
// TaintedVariable var = it.next();
// if (var.getScope().equals(scope) &&
// var.getVariable().getText().equals(variable.getText())) {
// it.remove();
// }
// }
// }
public boolean isVariableTainted(ParserRuleContext scope, ParseTree variable) {
for (TaintedVariable var : this.taintedVars) {
if (var.getScope().equals(scope) && var.getVariable().getText().equals(variable.getText())) {
return true;
}
}
return false;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (TaintedVariable var : this.taintedVars) {
builder.append(var.toString());
}
return builder.toString();
}
}

View File

@ -0,0 +1,102 @@
package it.unitn.repoman.core.utils.printers;
import java.util.Set;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.slicers.LightweightSlice;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.Utils;
import org.antlr.v4.runtime.tree.*;
public class ConsolePrinterListener implements ParseTreeListener {
private final Set<Integer> selectedLines;
private final Parser parser;
private final StringBuilder builder = new StringBuilder();
private int indent = 0;
private boolean marked = false;
private String MARK_START = "\u001B[31m";
private String MARK_END = "\u001B[0m";
public ConsolePrinterListener(Parser parser, LightweightSlice slice) {
this.parser = parser;
this.selectedLines = slice.getSelectedLines();
builder.append("Selected lines: " + slice.getSelectedLines() + "\n");
builder.append("#Selected lines: " + slice.getSelectedLines().size() + "\n");
builder.append("\n\n");
ParseTreeWalker.DEFAULT.walk(this, LanguageFactory.getRoot());
}
@Override
public void visitTerminal(TerminalNode node) {
if (marked) {
mark(builder);
}
if (builder.length() > 0)
builder.append(' ');
String text = Trees.getNodeText(node, this.parser);
if (text.equals("{")) {
indent++;
builder.append(Utils.escapeWhitespace(text, false));
unmark(builder);
appendNewline();
}
else if (text.equals(";")) {
builder.append(Utils.escapeWhitespace(text, false));
unmark(builder);
appendNewline();
}
else if (text.equals("}")) {
indent--;
appendNewline();
builder.append(" " + Utils.escapeWhitespace(text, false));
unmark(builder);
appendNewline();
}
else {
if (!text.contains("<EOF>")) {
builder.append(Utils.escapeWhitespace(text, false));
}
}
}
@Override
public void visitErrorNode(ErrorNode node) {
builder.append(Utils.escapeWhitespace(Trees.getNodeText(node, this.parser), false));
}
@Override
public void enterEveryRule(ParserRuleContext ctx) {
marked = this.selectedLines.contains(ctx.getStart().getLine());
}
@Override
public void exitEveryRule(ParserRuleContext ctx) {
}
private void appendNewline() {
builder.append("\n");
for (int i=0; i<indent; i++) {
builder.append(" ");
}
}
private void unmark(StringBuilder builder) {
builder.append(MARK_END);
marked = false;
}
private void mark(StringBuilder builder) {
builder.append(MARK_START);
marked = true;
}
@Override
public String toString() {
return builder.toString();
}
}

View File

@ -0,0 +1,18 @@
package it.unitn.repoman.core.utils.printers;
import java.util.Set;
public class HTMLPrinter {
protected final StringBuilder builder = new StringBuilder();
public HTMLPrinter(String fileContents, Set<Integer> selectedLines) {
}
@Override
public String toString() {
return builder.toString();
}
}

View File

@ -0,0 +1,73 @@
package it.unitn.repoman.core.utils.printers;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.slicers.LightweightSlice;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.Utils;
import org.antlr.v4.runtime.tree.*;
import java.util.Set;
public class TextPrinterListener implements ParseTreeListener {
private final Set<Integer> selectedLines;
private final Parser parser;
private final StringBuilder builder = new StringBuilder();
private boolean marked = false;
private int currentLineNumber = -1;
public TextPrinterListener(Parser parser, LightweightSlice slice) {
this.parser = parser;
this.selectedLines = slice.getSelectedLines();
builder.append("Selected lines: " + slice.getSelectedLines() + "\n");
builder.append("#Selected lines: " + slice.getSelectedLines().size() + "\n");
ParseTreeWalker.DEFAULT.walk(this, LanguageFactory.getRoot());
}
@Override
public void enterEveryRule(ParserRuleContext ctx) {
int lineNumber = ctx.getStart().getLine();
marked = (selectedLines.contains(lineNumber));
if (lineNumber != currentLineNumber && marked) {
builder.append("\n");
currentLineNumber = lineNumber;
builder.append(lineNumber);
builder.append(": ");
}
}
@Override
public void visitTerminal(TerminalNode node) {
if (marked) {
if (builder.length() > 0) {
builder.append(' ');
}
String text = Trees.getNodeText(node, this.parser);
if (text.equals("{")) {
builder.append(Utils.escapeWhitespace(text, false));
} else if (text.equals(";")) {
builder.append(Utils.escapeWhitespace(text, false));
} else if (text.equals("}")) {
builder.append(" " + Utils.escapeWhitespace(text, false));
} else {
if (!text.contains("<EOF>")) {
builder.append(Utils.escapeWhitespace(text, false));
}
}
}
}
@Override
public void visitErrorNode(ErrorNode node) {
builder.append(Utils.escapeWhitespace(Trees.getNodeText(node, this.parser), false));
}
@Override
public void exitEveryRule(ParserRuleContext ctx) {
}
@Override
public String toString() {
return builder.toString();
}
}