diff --git a/.gitignore b/.gitignore
index e16b0553f..3edac033f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@
**/target
dependency-reduced-pom.xml
bazel-*
+# Generated by ant
+jflex/build
# IntelliJ
*.iml
diff --git a/.lgtm.yml b/.lgtm.yml
new file mode 100644
index 000000000..e33dbae1a
--- /dev/null
+++ b/.lgtm.yml
@@ -0,0 +1,17 @@
+# Configutation for LGTM
+# https://lgtm.com/projects/g/jflex-de/jflex/
+# Format at https://help.semmle.com/lgtm-enterprise/user/help/lgtm.yml-configuration-file.html
+
+# Note that results for all files classified with a tag are hidden.
+# Path syntax is ant matcher https://confluence.atlassian.com/fisheye/pattern-matching-guide-298976797.html
+path_classifiers:
+ test:
+ - "src/test"
+ docs:
+ - "LICENSE*"
+ - "*.md"
+ third_party:
+ - "/cup"
+ - "/third_party"
+ generated:
+ - "/jflex/src/main/java/jflex/unicode/data/Unicode_*.java"
diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100755
index 000000000..fa4f7b499
--- /dev/null
+++ b/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,110 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
index f775b1c04..01e679973 100755
Binary files a/.mvn/wrapper/maven-wrapper.jar and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
index a447c9fa8..00d32aab1 100755
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -1 +1 @@
-distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
\ No newline at end of file
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
\ No newline at end of file
diff --git a/.travis.bazelrc b/.travis.bazelrc
new file mode 100644
index 000000000..a34c9f070
--- /dev/null
+++ b/.travis.bazelrc
@@ -0,0 +1,9 @@
+# This is from Bazel's former travis setup, to avoid blowing up the RAM usage.
+startup --host_jvm_args=-Xms2000m
+startup --host_jvm_args=-Xmx3000m
+test --ram_utilization_factor=10
+
+# This is so we understand failures better
+build --verbose_failures
+test --test_output=errors
+
diff --git a/.travis.yml b/.travis.yml
index 29fb24da4..b18cbb064 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,41 +5,109 @@ branches:
- aggregated-java-sources
- travis
+# We don't use the git log, a very small depth is sufficient
+git:
+ depth: 3
+
language: java
-# TODO(regisd) Remove the build matrix ; it really makes the deploy phase more complex
jdk:
-- openjdk7
-- oraclejdk8
+- openjdk9
-env:
- matrix:
- - TEST_SUITE=ant
- - TEST_SUITE=unit
- - TEST_SUITE=regression
+matrix:
+ include:
+ - name: "🛂 Check Java format"
+ script: scripts/test-java-format.sh
+ language: generic
+ - name: "🔨 Maven (compile, unit test, uberjar, ubersrcs, site)"
+ script:
+ - scripts/test-unit.sh
+ - scripts/mvn-site.sh
+ - scripts/mvn-aggregate-srcs.sh
+ after_success: scripts/send-code-coverage.sh
+ env:
+ - PUBLISH_SOURCES=true
+ language: generic
+ - name: "📝 Regression tests"
+ script:
+ - scripts/mvn-install-fastbuild.sh jflex-maven-plugin,testsuite/jflex-testsuite-maven-plugin
+ - scripts/test-regression.sh
+ - name: "😎 Examples (mvn, ant, make)"
+ script: scripts/test-examples.sh
+ - name: "👴 Examples (mvn, ant, make) — JDK7"
+ script: scripts/test-examples.sh
+ jdk: openjdk7
+ - name: "💚 Bazel (Examples and documentation)"
+ language: generic
+ script:
+ - scripts/mvn-install-fastbuild.sh
+ - scripts/bazel.sh
+ # Prerequisites for Bazel
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - curl
+ - pkg-config
+ - zip
+ - g++
+ - zlib1g-dev
+ - unzip
+ - python
+ before_install:
+ - mkdir -p tools
+ - curl -L https://github.com/bazelbuild/bazel/releases/download/0.17.2/bazel_0.17.2-linux-x86_64.deb -o tools/bazel-0.17.2.deb
+ install:
+ - sudo apt-get install ./tools/bazel-0.17.2.deb
+ sudo: true
+ - name: "📄 Documentation"
+ language: generic
+ install: true
+ addons:
+ apt:
+ packages:
+ # pandoc used for building the doc
+ - pandoc
+ - pandoc-citeproc
+ # texlive used for PDF output
+ - texlive
+ # texlive-latex-extra provides extra styles such as a4wide and upquote.sty
+ - texlive-latex-extra
+ # lmodern.sty
+ - lmodern
+ script:
+ - cd docs; make; cd ..
# Empty the previously built artifacts
# They cannot be deleted in the before_cache phase,
# otherwise `mvn site` fails in the before_deploy phase.
-before_install: ./scripts/clean.sh
-
-install: ./mvnw -version
+before_install:
+- ./scripts/clean.sh
-script: ./scripts/run-tests.sh
+install:
+- java -version
+- javac -version
+- ./mvnw -version
-after_success:
-- ./scripts/mvn-site.sh
-- ./scripts/mvn-aggregate-srcs.sh
+script: scripts/run-tests.sh
# Travis sometimes fails to download deps from repo1.maven.org
# A cache avoids downloading too much, and will also speed up the build.
# NB: There is one cache per branch and language version/ compiler version/ JDK version
cache:
+ apt: true
# The timeout (in seconds) empties the cache to avoid being stuck with a corrupted artefact
timeout: 86400 # 24 hours
directories:
- $HOME/.m2
+ # All our Bazel build artifacts
+ - $HOME/__bazel_output_base__/
+ # Items fetched from repositories
+ - $HOME/__bazel_travis_root__/cache
+ # DO NOT cache __bazel_output_travis__/install
- jflex/lib
+ - tools
deploy:
# Deploy the maven site on Github pages
@@ -49,7 +117,7 @@ deploy:
branch: release
condition:
- $TEST_SUITE = unit
- - $TRAVIS_JDK_VERSION = oraclejdk8
+ - $TRAVIS_JDK_VERSION = openjdk9
local_dir: target/maven-staging-site/maven-site
# GITHUB_TOKEN set in travis-ci.org dashboard
github_token: $GITHUB_TOKEN
@@ -64,6 +132,5 @@ deploy:
- master
- travis
condition:
- - $TEST_SUITE = unit
- - $TRAVIS_JDK_VERSION = oraclejdk8
+ - $PUBLISH_SOURCES
script: ./scripts/deploy-source-code.sh
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 000000000..53f8b359e
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,13 @@
+# Default owner for everything, unless a later match takes precedence
+# This project was created by Gerwin
+* @lsf37
+
+# In general, we don't wan't to change code in cup.
+# Be sure we have a big red warning by giving ownership to nobody.
+/cup/ @issues
+
+# The Maven plugin was initally authored by Régis
+/jflex-maven-plugin/ @regisd
+# Régis alsi knows more Bazel confg
+WORKSPACE @regis
+BUILD @regisd
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index afb9d3435..000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# Contribution
-## Contributions are welcome
-
-JFlex is free software and contributions are welcome.
-
-The preferred way to contribute code changes or fixes is via github pull
-requests. Before you send a pull request, please make sure that unit tests and
-regression test suite pass.
-
-## Code style
-
-JFlex follows the [Google-style][google-style] for Java.
-
-This is enforced by the [fmt-maven-plugin][fmt-maven-plugin].
-
-You can also use a configuration style
-
-* [Google style for Eclipse][google-style-eclipse]
-* [Google style for IntelliJ][google-style-intellij]
-
-## Setting up your environment
-
-We provide help on how to set up your
-[development environment](https://github.com/jflex-de/jflex/wiki/Development-environment).
-
-## Running the test suites
-
-### Short version
-
- ./run-tests
-
-This runs the entire test suites, including unit and regression tests, as
-well as examples.
-
-### Longer version
-
-Unit tests are run automatically if you locally install the jflex package for
-instance via
-
- mvn -N install
- mvn install
-
-The regression test suite must be run from the directory
-`testsuite/testcases`, for instance with
-
- mvn test
-
-The jflex/examples can be run individually either by calling `make` or `mvn
-test`.
-
-
-## Get in touch
-
-If you have larger code changes or new features to contribute it is usually a
-good idea to get in touch with the developers first and discuss if your idea
-fits with the rest of the JFlex design. You can get in contact either on the
-github issue tracking system or the [JFlex users mailing list][ml].
-
-[ml]: http://jflex.de/mailing.html
-[fmt-maven-plugin]: https://github.com/coveo/fmt-maven-plugin
-[google-style]: https://github.com/google/styleguide/
-[google-style-eclipse]: https://github.com/google/styleguide/blob/gh-pages/eclipse-java-google-style.xml
-[google-style-intellij]: https://github.com/google/styleguide/blob/gh-pages/intellij-java-google-style.xml
-
diff --git a/README.md b/README.md
index 8464a9e8a..fef8dc2cf 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,9 @@
-[![Build Status](https://travis-ci.org/jflex-de/jflex.svg?branch=master)](https://travis-ci.org/jflex-de/jflex)
+
+
+
+
+
+
# JFlex
@@ -13,6 +18,7 @@ operators, etc, and generating an input token stream for parsers.
JFlex lexers are based on deterministic finite automata (DFAs).
They are fast, without expensive backtracking.
+
## Modules
The top level directory of the JFLex git repository contains:
@@ -24,6 +30,8 @@ The top level directory of the JFLex git repository contains:
* **jflex-maven-plugin** the JFlex maven plugin, that helps to integrate JFlex in your project
* **jflex-unicode-plugin** the JFlex unicode maven plugin, used for compiling JFlex
* **testsuite** the regression test suite for JFlex,
+ * **third_party** third-party librairies used by examples of the [Bazel build system][bazel]
+
## Usage
@@ -57,8 +65,6 @@ and the [wiki][wiki].
3. Voilà: Java code is produced in `target/generated-sources/` during the `generate-sources` phase
(which happens before the `compile` phase) and included in the compilation scope.
-Sample project: [simple-maven][example-simple-maven]
-
### Usage with ant
1. Define ant task
@@ -72,6 +78,19 @@ Sample project: [simple-maven][example-simple-maven]
```
+### Usage with Bazel
+
+We provide a [jflex rule](https://jflex-de.github.io/bazel_rules/)
+
+```
+load("@jflex_rules//jflex:jflex.bzl", "jflex")
+jflex(
+ name = "", # Choose a rule name
+ srcs = [], # Add input lex specifications
+ outputs = [], # List expected generated files
+)
+```
+
### Usage in CLI
You can also use JFlex directly from the command line:
@@ -84,20 +103,34 @@ Or:
java -jar jflex-full-1.7.0.jar -d output src/grammar/parser.flex
```
+### Other build tools
+
+See [Build tool plugins](https://github.com/jflex-de/jflex/wiki/Build-tool-integration).
+
+
+## Examples
+
+Have a look at the sample project: [simple][example-simple] and other [examples].
+
+
## Build from source
```
./mvnw install
```
+
## Contributing
JFlex is free software, contributions are welcome.
-See the file [CONTRIBUTING.md](CONTRIBUTING.md) for instructions.
+See the [Contributing][contrib] page for instructions.
[jflex]: http://jflex.de/
[jflex-doc]: http://jflex.de/manual.html
[wiki]: https://github.com/jflex-de/jflex/wiki
[pom-build]: https://maven.apache.org/pom.html#Build_Settings
-[example-simple-maven]: https://github.com/jflex-de/jflex/tree/master/jflex/examples/simple-maven
+[example-simple]: https://github.com/jflex-de/jflex/tree/master/jflex/examples/simple
+[examples]: https://github.com/jflex-de/jflex/tree/master/jflex/examples/
+[contrib]: https://github.com/jflex-de/jflex/wiki/Contributing
+[bazel]: http://bazel.build/
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 000000000..346fc68fe
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,52 @@
+# Workspace file for the Bazel build system
+# https://bazel.build/
+
+# JFlex itself is not built with Bazel, but some examples and the documentation are.
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+
+git_repository(
+ name = "jflex_rules",
+ branch = "stable",
+ remote = "https://github.com/jflex-de/bazel_rules.git",
+)
+
+load("@jflex_rules//jflex:deps.bzl", "jflex_deps")
+
+jflex_deps()
+
+# pandoc used to build the documentatoin
+
+# TODO(regisd) Take upstream when they have accepted my PR to allow specifying output
+# https://github.com/ProdriveTechnologies/bazel-pandoc/pull/1
+#http_archive(
+# name = "bazel_pandoc",
+# strip_prefix = "bazel-pandoc-0.1",
+# url = "https://github.com/ProdriveTechnologies/bazel-pandoc/archive/v0.1.tar.gz",
+#)
+http_archive(
+ name = "bazel_pandoc",
+ sha256 = "0dd9d0d44658d46a96c36caba25f7ce9f119a6883c3219f61b76c11cfdc83c8f",
+ strip_prefix = "bazel_pandoc-0.1.1",
+ url = "https://github.com/regisd/bazel_pandoc/archive/v0.1.1.tar.gz",
+)
+
+load("@bazel_pandoc//:repositories.bzl", "pandoc_repositories")
+
+pandoc_repositories()
+
+# latex rule to build PDF from tex files
+
+http_archive(
+ name = "bazel_latex",
+ strip_prefix = "bazel-latex-0.9",
+ url = "https://github.com/ProdriveTechnologies/bazel-latex/archive/v0.9.tar.gz",
+)
+
+load("@bazel_latex//:repositories.bzl", "latex_repositories")
+
+latex_repositories()
+
+# Third-party depenencies
+load("//third_party:deps.bzl", "third_party_deps")
+
+third_party_deps()
diff --git a/cup-maven-plugin/README.md b/cup-maven-plugin/README.md
new file mode 100644
index 000000000..f1eaa22a9
--- /dev/null
+++ b/cup-maven-plugin/README.md
@@ -0,0 +1,34 @@
+# CUP Maven plugin
+
+This is a plugin to invoke cup from Maven.
+
+Version 1.0 of the plugin uses CUP 11b.
+
+## Usage
+
+By default, this plugin runs
+
+```
+cup -destdir target/generated-sources/cup -parser parser -symbols sym src/main/cup/*.cup
+```
+
+```xml
+
+ de.jflex
+ cup-maven-plugin
+ 1.0
+
+
+
+ generate
+
+
+
+
+
+
+```
+
+## Example
+
+Please see [cup/sample-project](/jflex-de/jflex/cup/sample-project/)
diff --git a/cup-maven-plugin/pom.xml b/cup-maven-plugin/pom.xml
index 04f706fc6..397d581cd 100644
--- a/cup-maven-plugin/pom.xml
+++ b/cup-maven-plugin/pom.xml
@@ -76,4 +76,17 @@
test
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.7
+ 1.7
+
+
+
+
diff --git a/cup-maven-plugin/src/main/java/de/jflex/plugin/cup/GenerateMojo.java b/cup-maven-plugin/src/main/java/de/jflex/plugin/cup/GenerateMojo.java
index 98e790015..d885223a8 100644
--- a/cup-maven-plugin/src/main/java/de/jflex/plugin/cup/GenerateMojo.java
+++ b/cup-maven-plugin/src/main/java/de/jflex/plugin/cup/GenerateMojo.java
@@ -149,12 +149,13 @@ private boolean isGeneratedCodeOutdated(File cupFile, String javaPackage) {
}
private String findJavaPackage(File cupFile) throws IOException {
- BufferedReader br = new BufferedReader(new FileReader(cupFile));
- while (br.ready()) {
- String line = br.readLine();
- Optional optJavaPackage = optionalJavaPackage(line);
- if (optJavaPackage.isPresent()) {
- return optJavaPackage.get();
+ try (BufferedReader br = new BufferedReader(new FileReader(cupFile))) {
+ while (br.ready()) {
+ String line = br.readLine();
+ Optional optJavaPackage = optionalJavaPackage(line);
+ if (optJavaPackage.isPresent()) {
+ return optJavaPackage.get();
+ }
}
}
return DEFAULT_JAVA_PACKAGE;
diff --git a/cup/BUILD b/cup/BUILD
new file mode 100644
index 000000000..ff7e3c245
--- /dev/null
+++ b/cup/BUILD
@@ -0,0 +1,22 @@
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"]) # GPL-compatible
+
+java_binary(
+ name = "cup_bin",
+ main_class = "java_cup.Main",
+ runtime_deps = [
+ ":cup",
+ ],
+)
+
+# This is the full Java CUP (with runtime)
+java_import(
+ name = "cup",
+ jars = ["cup/java-cup-11b.jar"],
+)
+
+alias(
+ name = "cup_runtime",
+ actual = "//cup/cup_runtime",
+)
diff --git a/cup/LICENSE b/cup/LICENSE
deleted file mode 100644
index 2b071cd64..000000000
--- a/cup/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-CUP Parser Generator Copyright Notice, License, and Disclaimer
-
-Copyright 1996-2015 by Scott Hudson, Frank Flannery, C. Scott Ananian, Michael Petter
-Permission to use, copy, modify, and distribute this software and its documentation for any purpose
-and without fee is hereby granted, provided that the above copyright notice appear in all copies and
-that both the copyright notice and this permission notice and warranty disclaimer appear in
-supporting documentation, and that the names of the authors or their employers not be used in
-advertising or publicity pertaining to distribution of the software without specific, written prior
-permission.
-
-The authors and their employers disclaim all warranties with regard to this software, including all
-implied warranties of merchantability and fitness. In no event shall the authors or their employers
-be liable for any special, indirect or consequential damages or any damages whatsoever resulting
-from loss of use, data or profits, whether in an action of contract, negligence or other tortious
-action, arising out of or in connection with the use or performance of this software.
diff --git a/cup/LICENSE b/cup/LICENSE
new file mode 120000
index 000000000..b461f6488
--- /dev/null
+++ b/cup/LICENSE
@@ -0,0 +1 @@
+cup_runtime/src/main/resources/LICENSE_CUP
\ No newline at end of file
diff --git a/cup/README.md b/cup/README.md
index 91fcb04d0..384a03a5a 100644
--- a/cup/README.md
+++ b/cup/README.md
@@ -11,4 +11,15 @@ Home directory and parent POM of 2 artefacts:
Note that this code is excluded from many rules of our codebase,
for instance google-java-format is not applied.
+
+## Bazel rule
+
+ load("//cup:cup.bzl", "cup")
+
+ cup(
+ name = "rule_name",
+ src = "spec.cup",
+ )
+
+
[cup]: http://www2.cs.tum.edu/projects/cup/
diff --git a/cup/cup.bzl b/cup/cup.bzl
new file mode 100644
index 000000000..804f9c915
--- /dev/null
+++ b/cup/cup.bzl
@@ -0,0 +1,24 @@
+"""Bazel rules for cup. """
+
+# CUP can only read from stdin, which Skylark rules don't support. Use a genrule for now.
+def cup(name, src, parser = "Parser", symbols = "Symbols", interface = False):
+ """Generate a parser with CUP.
+
+ Args:
+ name: name of the rule
+ srcs: list of cup specifications
+ parser: name of the generated parser class
+ symbols: name of the generated symbols class
+ interface: whether to generate an interface
+ """
+ opts = "-parser {parser} -symbols {symbols}".format(parser = parser, symbols = symbols)
+ if interface:
+ opts = opts + " -interface"
+ cmd = ("$(location //cup:cup_bin) -destdir $(@D) " + opts + " < $<")
+ native.genrule(
+ name = name,
+ srcs = [src],
+ tools = ["//cup:cup_bin"],
+ outs = [parser + ".java", symbols + ".java"],
+ cmd = cmd,
+ )
diff --git a/cup/cup/pom.xml b/cup/cup/pom.xml
index ed6d19986..ca07601bf 100644
--- a/cup/cup/pom.xml
+++ b/cup/cup/pom.xml
@@ -15,6 +15,13 @@
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+ org.apache.maven.pluginsmaven-install-plugin
diff --git a/cup/cup_runtime/BUILD b/cup/cup_runtime/BUILD
new file mode 100644
index 000000000..c9eea2124
--- /dev/null
+++ b/cup/cup_runtime/BUILD
@@ -0,0 +1,6 @@
+licenses(["notice"]) # BSD-like
+java_library(
+ name = "cup_runtime",
+ srcs = glob(["src/main/java/**/*.java"]),
+ visibility=["//visibility:public"]
+)
\ No newline at end of file
diff --git a/cup/cup_runtime/src/main/resources/LICENSE_CUP b/cup/cup_runtime/src/main/resources/LICENSE_CUP
new file mode 100644
index 000000000..2b071cd64
--- /dev/null
+++ b/cup/cup_runtime/src/main/resources/LICENSE_CUP
@@ -0,0 +1,15 @@
+CUP Parser Generator Copyright Notice, License, and Disclaimer
+
+Copyright 1996-2015 by Scott Hudson, Frank Flannery, C. Scott Ananian, Michael Petter
+Permission to use, copy, modify, and distribute this software and its documentation for any purpose
+and without fee is hereby granted, provided that the above copyright notice appear in all copies and
+that both the copyright notice and this permission notice and warranty disclaimer appear in
+supporting documentation, and that the names of the authors or their employers not be used in
+advertising or publicity pertaining to distribution of the software without specific, written prior
+permission.
+
+The authors and their employers disclaim all warranties with regard to this software, including all
+implied warranties of merchantability and fitness. In no event shall the authors or their employers
+be liable for any special, indirect or consequential damages or any damages whatsoever resulting
+from loss of use, data or profits, whether in an action of contract, negligence or other tortious
+action, arising out of or in connection with the use or performance of this software.
diff --git a/cup/pom.xml b/cup/pom.xml
index 315033395..d2f66a6e1 100644
--- a/cup/pom.xml
+++ b/cup/pom.xml
@@ -50,13 +50,18 @@
+
- org.apache.maven.plugins
- maven-deploy-plugin
+ maven-compiler-plugin
- true
+ 1.6
+ 1.6
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ org.apache.maven.pluginsmaven-site-plugin
@@ -67,6 +72,10 @@
+
+ maven-compiler-plugin
+ 3.7.0
+ maven-deploy-plugin2.8.2
@@ -87,6 +96,14 @@
maven-site-plugin3.6
+
+ maven-javadoc-plugin
+ 2.10.1
+
+
+ maven-source-plugin
+ 3.0.1
+
@@ -96,6 +113,51 @@
+
+ release
+
+
+
+ maven-javadoc-plugin
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ maven-source-plugin
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ maven-gpg-plugin
+ 1.6
+
+ 84A70085
+
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+ no-doclint
@@ -108,6 +170,14 @@
+
+ ossrh
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ ossrh
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+ github.pagesGithub pages
diff --git a/cup/sample-project/BUILD b/cup/sample-project/BUILD
new file mode 100644
index 000000000..adac8145b
--- /dev/null
+++ b/cup/sample-project/BUILD
@@ -0,0 +1,6 @@
+load("//cup:cup.bzl", "cup")
+
+cup(
+ name = "gen_parser",
+ src = "src/main/cup/calculator.cup",
+)
diff --git a/cup/sample-project/REAME.md b/cup/sample-project/README.md
similarity index 100%
rename from cup/sample-project/REAME.md
rename to cup/sample-project/README.md
diff --git a/docs/BUILD b/docs/BUILD
new file mode 100644
index 000000000..fd8a1ae95
--- /dev/null
+++ b/docs/BUILD
@@ -0,0 +1,91 @@
+# Build the user manual
+
+load("@bazel_pandoc//:pandoc.bzl", "pandoc")
+load("@bazel_latex//:latex.bzl", "latex_document")
+
+VERSION = "1.7.1-SNAPSHOT"
+
+RELEASE_DATE = "21 September 2018"
+
+UNICODE_VER = "9.0"
+
+GENRULE_CONCATENATE = "cat $(SRCS) > $@"
+
+pandoc(
+ name = "html",
+ src = ":manual_mdx",
+ from_format = "markdown",
+ # TODO: Add "--css manual.css" when the rule accepts data files
+ #
+ # TODO: Add "+smart" when the toolchain supports it
+ #
+ # TODO: Add ["--filter", "pandoc-citeproc"] when #2 is fixed
+ # https://github.com/ProdriveTechnologies/bazel-pandoc/issues/2
+ options = [],
+ output = "manual.html",
+ to_format = "html",
+)
+
+pandoc(
+ name = "latex_content",
+ src = ":manual_mdx",
+ from_format = "markdown",
+ output = "content.tex", # If changed, then change \include{} in manual.tex
+ to_format = "latex",
+)
+
+genrule(
+ name = "manual_full_tex",
+ srcs = [
+ "manual_start.tex",
+ ":latex_content",
+ "manual_end.tex",
+ ],
+ outs = ["manual_full.tex"],
+ cmd = GENRULE_CONCATENATE,
+)
+
+latex_document(
+ name = "manual",
+ srcs = [
+ #"manual.tex",
+ # "minimal.tex",
+ # "manual_full.tex",
+ "@bazel_latex//packages:graphicx",
+ "@bazel_latex//packages:hyperref",
+ "@bazel_latex//packages:microtype",
+ ],
+ main = "manual_full.tex",
+)
+
+# Replaces placeholders by their respective value.
+genrule(
+ name = "manual_mdx",
+ srcs = [":concatenated_manual"],
+ outs = ["manual.mdx"],
+ cmd = "sed -e 's/\$$VERSION/" + VERSION + "/g'" +
+ " -e 's/\$${project.version}/" + VERSION + "/g'" +
+ " -e 's/\$$RELEASE_DATE/" + RELEASE_DATE + "/g'" +
+ " -e 's/\$$UNICODE_VER/" + UNICODE_VER + "/g'" +
+ " $< > $@",
+)
+
+# Concatenates all pages in a single document.
+genrule(
+ name = "concatenated_manual",
+ srcs = [
+ "md/head.md",
+ "md/intro.md",
+ "md/installing.md",
+ "md/maven-plugin.md",
+ "md/ant-task.md",
+ "md/example.md",
+ "md/lex-specs.md",
+ "md/encodings.md",
+ "md/performance.md",
+ "md/porting-and-parsers.md",
+ "md/end.md",
+ ],
+ outs = ["concatenated_manual.md"],
+ cmd = GENRULE_CONCATENATE,
+)
diff --git a/docs/Makefile b/docs/Makefile
index 1d776181d..3c4a8d5df 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -36,9 +36,10 @@ manual.pdf: xmanual.pdf
# variable substitutions:
%.mdx: md/%.md Makefile
- perl -p -e 's/\$$VERSION/$(VERSION)/g' < $< | \
- perl -p -e 's/\$$RELEASE_DATE/$(RELEASE_DATE)/g' | \
- perl -p -e 's/\$$UNICODE_VER/$(UNICODE_VER)/g' > $@
+ sed -e 's/\$$VERSION/$(VERSION)/g' \
+ -e 's/\$${project.version}/$(VERSION)/g' \
+ -e 's/\$$RELEASE_DATE/$(RELEASE_DATE)/g' \
+ -e 's/\$$UNICODE_VER/$(UNICODE_VER)/g' $< > $@
%.tex: %.mdx
pandoc -f markdown -t latex --biblatex $< -o $@
diff --git a/docs/manual.tex b/docs/manual.tex
new file mode 100644
index 000000000..f22380b3e
--- /dev/null
+++ b/docs/manual.tex
@@ -0,0 +1,83 @@
+% The Latex template for the manual, when doc built with bazel
+
+\documentclass[11pt]
+%{scrartcl}
+%\usepackage{a4wide}
+%\usepackage{verbatim}
+%\usepackage{graphicx} % "@bazel_latex//packages:graphicx"
+%\usepackage{upquote}
+%\usepackage{microtype} % "@bazel_latex//packages:microtype"
+
+%\usepackage{color}
+\definecolor{lcol}{rgb}{0,0,0.5}
+%\usepackage[unicode=true,bookmarks,
+% colorlinks=true,linkcolor=lcol,citecolor=lcol,
+% filecolor=lcol,urlcolor=lcol,
+% pdfauthor={Gerwin Klein, Steve Rowe, Regis Decamps},
+% pdftitle={JFlex User's Manual},
+% pdfkeywords={Java, scanner, lexer, scanner generator},
+% plainpages=false]{hyperref}
+
+
+% pandoc packages
+\usepackage{lmodern}
+\usepackage{fixltx2e} % provides \textsubscript
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+
+\newcommand{\textcite}[1]{\cite{#1}}
+\newcommand{\autocite}[1]{\cite{#1}}
+
+\renewcommand{\textquotesingle}{'}
+
+\let\orighyperref\hyperref
+\renewcommand{\hyperref}[2][]{\orighyperref[#1]{#2} (\autoref{#1})}
+
+\let\ttf\ttfamily
+\renewcommand{\ttfamily}{\small\ttf}
+
+\renewcommand{\sectionautorefname}{Section}
+\renewcommand{\subsectionautorefname}{Section}
+\renewcommand{\subsubsectionautorefname}{Section}
+\renewcommand{\Hfootnoteautorefname}{Footnote}
+
+\setlength{\parindent}{0pt}
+\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
+
+% pandoc now uses \tightlist
+\providecommand{\tightlist}{%
+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
+
+\begin{document}
+
+% TODO Find real bath of image
+% can't find file fix.jflex-black.png
+%\centerline{\includegraphics[width=0.6\textwidth]{fig/jflex-black.png}}
+
+\begin{center}
+\sffamily
+{\Large The Fast Lexical Analyser Generator}\\
+\smallskip\smallskip
+Copyright \copyright\ 1998--2018
+by \href{http://www.doclsf.de}{Gerwin Klein},
+Steve Rowe,
+and \href{http://regis.decamps.info/}{R\'egis D\'ecamps}.
+
+\vspace*{15ex}
+{\Huge \sffamily \bfseries JFlex User's Manual}\\
+\bigskip
+Version 1.7.1-SNAPSHOT, {\today}
+\end{center}
+
+\newpage
+\tableofcontents
+\newpage
+
+\include{content}
+
+\newpage
+
+\bibliographystyle{plain}
+\bibliography{manual}
+
+\end{document}
diff --git a/docs/manual_end.tex b/docs/manual_end.tex
new file mode 100644
index 000000000..1aad1859f
--- /dev/null
+++ b/docs/manual_end.tex
@@ -0,0 +1,2 @@
+
+\end{document}
\ No newline at end of file
diff --git a/docs/manual_start.tex b/docs/manual_start.tex
new file mode 100644
index 000000000..455843755
--- /dev/null
+++ b/docs/manual_start.tex
@@ -0,0 +1,10 @@
+\documentclass{article}
+\usepackage{hyperref}
+
+% pandoc now uses \tightlist
+\providecommand{\tightlist}{%
+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
+
+\newcommand{\textquotesingle}{'}
+
+\begin{document}
diff --git a/docs/md/head.md b/docs/md/head.md
index 1fbc4cb34..87094a07d 100644
--- a/docs/md/head.md
+++ b/docs/md/head.md
@@ -3,8 +3,9 @@ title: JFlex User's Manual
bibliography: manual.bib
---
+TODO: Restore image
+
-![](fig/jflex-black.png)
The Fast Lexical Analyser Generator
diff --git a/docs/md/installing.md b/docs/md/installing.md
index b2d512da7..c7b81696d 100644
--- a/docs/md/installing.md
+++ b/docs/md/installing.md
@@ -21,7 +21,7 @@ To install JFlex on Windows, follow these three steps:
+--cup-maven\ (calculator example for cup and maven)
+--interpreter\ (interpreter example for cup)
+--java\ (Java lexer specification)
- +--simple-maven\ (example scanner built with maven)
+ +--simple\ (example scanner with no parser)
+--standalone-maven\ (a simple standalone scanner,
built with maven)
+--zero-reader\ (Readers that return 0 characters)
diff --git a/docs/md/maven-plugin.md b/docs/md/maven-plugin.md
index 9f332217c..3593f442b 100644
--- a/docs/md/maven-plugin.md
+++ b/docs/md/maven-plugin.md
@@ -7,6 +7,9 @@ generates a corresponding Java parser
### Usage
+See [jflex-maven-plugin site](http://jflex-de.github.io/jflex-web/jflex-maven-plugin/plugin-info.html)
+for more information.
+
#### Minimal configuration
This configuration generates java code of a parser
@@ -20,6 +23,7 @@ in sub-directories following the Java convention on package names.
Update the `pom.xml` to add the plugin:
+
```
@@ -28,7 +32,7 @@ Update the `pom.xml` to add the plugin:
de.jflexjflex-maven-plugin
- 1.7.0
+ ${project.version}
@@ -56,7 +60,7 @@ The generated Java code is placed into `src/main/java` instead of
de.jflexjflex-maven-plugin
- 1.6.0
+ ${project.version}
@@ -89,7 +93,7 @@ This generates the source for
de.jflexjflex-maven-plugin
- 1.6.0
+ ${project.version}strict jlex
@@ -132,7 +136,7 @@ More information in the [POM reference guide on plugins](http://maven.apache.org
Which version of the plugin is best for you?
- * jflex-maven-plugin-$VERSION depends on $VERSION
+ * jflex-maven-plugin-${project.version} depends on ${project.version}
and requires Java 7 when you `mvn jflex:generate`
* jflex-maven-plugin-1.7.0 depends on 1.7.0
diff --git a/jflex-maven-plugin/pom.xml b/jflex-maven-plugin/pom.xml
index db1c66d60..3d1badcb5 100644
--- a/jflex-maven-plugin/pom.xml
+++ b/jflex-maven-plugin/pom.xml
@@ -77,6 +77,11 @@
+
+ com.google.code.findbugs
+ jsr305
+ 3.0.2
+ com.google.guavaguava
@@ -97,7 +102,7 @@
org.apache.maven.plugin-toolsmaven-plugin-annotations
- 3.5
+ 3.5.2provided
@@ -112,5 +117,34 @@
3.3.0test
+
+ com.google.truth
+ truth
+ 0.42
+ test
+
+
+ junit
+ junit
+ test
+
+
+ junit
+ junit
+ test
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
+ maven-plugin-plugin
+
+
+
diff --git a/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/ClassInfo.java b/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/ClassInfo.java
index 67620211c..9aa1668ee 100644
--- a/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/ClassInfo.java
+++ b/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/ClassInfo.java
@@ -8,11 +8,37 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package de.jflex.plugin.maven;
+import com.google.common.base.Strings;
import java.io.File;
+import java.util.Objects;
+import javax.annotation.Nullable;
class ClassInfo {
- String className = null;
- String packageName = null;
+
+ final String className;
+
+ /** dot-separated package name. Empty string for the default package. */
+ final String packageName;
+
+ ClassInfo(String className, @Nullable String packageName) {
+ this.className = className;
+ this.packageName = Strings.nullToEmpty(packageName);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ClassInfo)) {
+ return false;
+ }
+ ClassInfo other = (ClassInfo) obj;
+ return Objects.equals(className, other.className)
+ && Objects.equals(packageName, other.packageName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(className, packageName);
+ }
/**
* Returns the (relative) path name of the java source code file that corresponds to the class.
@@ -22,10 +48,7 @@ class ClassInfo {
* @return Name of the java file.
*/
String getOutputFilename() {
- String packageDir = "";
- if (packageName != null) {
- packageDir += packageName.replace('.', File.separatorChar);
- }
+ String packageDir = packageName.replace('.', File.separatorChar);
if (packageDir.length() > 0) {
packageDir += File.separatorChar;
}
diff --git a/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/JFlexMojo.java b/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/JFlexMojo.java
index 8f80a187b..c81418b61 100644
--- a/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/JFlexMojo.java
+++ b/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/JFlexMojo.java
@@ -8,6 +8,8 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package de.jflex.plugin.maven;
+import static com.google.common.base.Strings.isNullOrEmpty;
+
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
@@ -18,7 +20,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import jflex.Main;
+import java.util.Objects;
+import jflex.LexGenerator;
import jflex.Options;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
@@ -47,7 +50,7 @@ public class JFlexMojo extends AbstractMojo {
* List of grammar definitions to run the JFlex parser generator on. Each path may either specify
* a single grammar file or a directory. Directories will be recursively scanned for files with
* one of the following extensions: ".jflex", ".flex", ".jlex" or ".lex". By default, all files in
- * src/main/jflex will be processed.
+ * {@code src/main/jflex} will be processed.
*
* @see #SRC_MAIN_JFLEX
*/
@@ -90,7 +93,7 @@ public class JFlexMojo extends AbstractMojo {
@Parameter(defaultValue = "false")
private boolean jlex;
- /** The generation method to use for the scanner. The only valid value is pack. */
+ /** The generation method to use for the scanner. The only valid value is {@code pack}. */
@Parameter(defaultValue = "pack")
private String generationMethod = "pack"; // NOPMD
@@ -189,16 +192,7 @@ private void parseLexFile(File lexFile) throws MojoFailureException, MojoExecuti
assert lexFile.isAbsolute() : lexFile;
getLog().debug("Generating Java code from " + lexFile.getName());
- ClassInfo classInfo;
- try {
- classInfo = LexSimpleAnalyzer.guessPackageAndClass(lexFile);
- } catch (FileNotFoundException e) {
- throw new MojoFailureException(e.getMessage(), e);
- } catch (IOException e) {
- classInfo = new ClassInfo();
- classInfo.className = LexSimpleAnalyzer.DEFAULT_NAME;
- classInfo.packageName = null; // NOPMD
- }
+ ClassInfo classInfo = findClassInfo(lexFile);
checkParameters(lexFile);
@@ -215,6 +209,7 @@ private void parseLexFile(File lexFile) throws MojoFailureException, MojoExecuti
// set options. Very strange that JFlex expects this in a static way.
Options.setDefaults();
Options.setDir(generatedFile.getParentFile());
+ Options.setRootDirectory(project.getBasedir());
Options.dump = dump;
Options.verbose = verbose;
Options.unused_warning = unusedWarning;
@@ -227,11 +222,11 @@ private void parseLexFile(File lexFile) throws MojoFailureException, MojoExecuti
Options.no_minimize = !minimize; // NOPMD
Options.no_backup = !backup; // NOPMD
- if (!"pack".equals(generationMethod)) {
+ if (!Objects.equals("pack", generationMethod)) {
throw new MojoExecutionException("Illegal generation method: " + generationMethod);
}
- if (!"".equals(encodingName)) {
+ if (!isNullOrEmpty(encodingName)) {
try {
Options.setEncoding(encodingName);
} catch (Exception e) {
@@ -240,13 +235,23 @@ private void parseLexFile(File lexFile) throws MojoFailureException, MojoExecuti
}
try {
- Main.generate(lexFile);
+ LexGenerator.generate(lexFile);
getLog().info(" generated " + generatedFile);
} catch (Exception e) {
throw new MojoExecutionException(e.getMessage(), e);
}
}
+ private ClassInfo findClassInfo(File lexFile) throws MojoFailureException {
+ try {
+ return LexSimpleAnalyzer.guessPackageAndClass(lexFile);
+ } catch (FileNotFoundException e) {
+ throw new MojoFailureException(e.getMessage(), e);
+ } catch (IOException e) {
+ return new ClassInfo(LexSimpleAnalyzer.DEFAULT_NAME, /*packageName=*/ "");
+ }
+ }
+
/**
* Check parameter lexFile.
*
diff --git a/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/LexSimpleAnalyzer.java b/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/LexSimpleAnalyzer.java
index 1840ecd11..9e44bf2d4 100644
--- a/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/LexSimpleAnalyzer.java
+++ b/jflex-maven-plugin/src/main/java/de/jflex/plugin/maven/LexSimpleAnalyzer.java
@@ -9,17 +9,22 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package de.jflex.plugin.maven;
+import com.google.common.io.Files;
import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import javax.annotation.Nullable;
/**
* @author Rafal Mantiuk (Rafal.Mantiuk@bellstream.pl)
* @author Gerwin Klein (lsf@jflex.de)
+ * @author Régis Décamps
*/
class LexSimpleAnalyzer {
+
static final String DEFAULT_NAME = "Yylex";
/**
@@ -31,51 +36,56 @@ class LexSimpleAnalyzer {
* @throws IOException when an IO exception occurred while reading a file.
*/
static ClassInfo guessPackageAndClass(File lexFile) throws IOException {
- assert lexFile.isAbsolute() : lexFile;
+ Reader lexFileReader = Files.newReader(lexFile, StandardCharsets.UTF_8);
+ return guessPackageAndClass(lexFileReader);
+ }
- try (LineNumberReader reader = new LineNumberReader(new FileReader(lexFile))) {
- ClassInfo classInfo = new ClassInfo();
- while (classInfo.className == null || classInfo.packageName == null) {
+ static ClassInfo guessPackageAndClass(Reader lexFileReader) throws IOException {
+ try (LineNumberReader reader = new LineNumberReader(lexFileReader)) {
+ String className = null;
+ String packageName = null;
+ while (className == null || packageName == null) {
String line = reader.readLine();
if (line == null) {
break;
}
-
- guessPackage(classInfo, line);
- guessClass(classInfo, line);
+ if (packageName == null) {
+ packageName = guessPackage(line);
+ }
+ if (className == null) {
+ className = guessClass(line);
+ }
}
- if (classInfo.className == null) {
- classInfo.className = DEFAULT_NAME;
+ if (className == null) {
+ className = DEFAULT_NAME;
}
- return classInfo;
+ return new ClassInfo(className, packageName);
}
}
- private static void guessClass(ClassInfo classInfo, String line) {
- if (classInfo.className == null) {
- int index = line.indexOf("%class");
- if (index >= 0) {
- index += 6;
-
- classInfo.className = line.substring(index);
- classInfo.className = classInfo.className.trim();
- }
+ @Nullable
+ private static String guessClass(String line) {
+ int index = line.indexOf("%class");
+ if (index > -1) {
+ index += "%class".length();
+ return line.substring(index).trim();
}
+ return null;
}
- private static void guessPackage(ClassInfo classInfo, String line) {
- if (classInfo.packageName == null) {
- int index = line.indexOf("package");
- if (index >= 0) {
- index += 7;
+ @Nullable
+ private static String guessPackage(String line) {
+ int index = line.trim().indexOf("package");
+ if (index == 0) {
+ index += "package".length();
- int end = line.indexOf(';', index);
- if (end >= index) {
- classInfo.packageName = line.substring(index, end);
- classInfo.packageName = classInfo.packageName.trim();
- }
+ int end = line.indexOf(';', index);
+ if (end >= index) {
+ return line.substring(index, end).trim();
}
}
+
+ return null;
}
}
diff --git a/jflex-maven-plugin/src/site/apt/changelog.apt b/jflex-maven-plugin/src/site/apt/changelog.apt
deleted file mode 100644
index a461cf82d..000000000
--- a/jflex-maven-plugin/src/site/apt/changelog.apt
+++ /dev/null
@@ -1,107 +0,0 @@
- ---------
- Changelog
- ---------
-
-Latest version
-
-* Version 1.7.0
-
- * Relies on JFlex 1.7.0
-
- * Requires Java 7
-
- * Requires Maven 3
-
- * New option 'enconding' to set lexer spec encoding
-
-* Version 1.6.1
-
- * Relies on JFlex 1.6.1
-
- * New option `unusedWarning` that controls whether to warn about unused
- macros or not.
-
- * New option `dump` that is more verbose than `verbose`
-
- * Option `verbose` set to same verbosity level as command line
-
- * Added m2e plugin configuration for Eclipse
-
- * Development moved to github
-
-
-Recent versions
-
-* Version 1.6.0
-
- * Relies on JFlex 1.6.0
-
- * changed inputStreamCtor default to false
-
-
-* Version 1.5.0
-
- * Changed name from maven-jflex-plugin to jflex-maven-plugin
-
- * Switched license from GPL to BSD
-
- * Relies on JFlex 1.5.0
-
- * Requires Java 5
-
- * Changed package from org.codehaus.mojo.jlex to de.jflex.plugin.maven.
-
-
-* Version 1.4.3-r1
-
- * Java 1.3 bytecode
-
- * Relies on JFlex 1.4.3
-
-* Version 1.4.2-r1
-
- * Java 1.3 bytecode
-
- * Relies on JFlex 1.4.2
-
-
-* Version 0.3
-
- * Java 1.4 bytecode
-
- * relies on JFlex 1.4.1
-
- * new option staleMillis
-
- * more reports on site
-
- * code improvements
-
-
-Alpha versions
-
-* Version 0.2
-
- * Java 5 bytecode
-
- * new options added: generationMethod, minimize, backup
-
- * enhanced documentation
-
- * many code improvements
-
- ** use file comparison, prefer available functionality from File
- class to avoid manual string twiddling
-
- ** fix testInit(): the generated file size depends on the platform
- (because of how new lines are encoded)
-
- ** improve unit test with AbstractMojoTestCase
-
- * changed package from de.jflex.maven.plugin to org.codehaus.maven.plugin
-
-* Version 0.1
-
- * Java 5 bytecode
-
- * Generates Java code from lex files, using JFlex 1.4.1
\ No newline at end of file
diff --git a/jflex-maven-plugin/src/site/markdown/usage.md b/jflex-maven-plugin/src/site/markdown/usage.md
new file mode 120000
index 000000000..e11538f65
--- /dev/null
+++ b/jflex-maven-plugin/src/site/markdown/usage.md
@@ -0,0 +1 @@
+../../../../docs/md/maven-plugin.md
\ No newline at end of file
diff --git a/jflex-maven-plugin/src/site/site.xml b/jflex-maven-plugin/src/site/site.xml
new file mode 100644
index 000000000..316ffed4f
--- /dev/null
+++ b/jflex-maven-plugin/src/site/site.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/ClassInfoTest.java b/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/ClassInfoTest.java
index d25704ace..770e6f465 100644
--- a/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/ClassInfoTest.java
+++ b/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/ClassInfoTest.java
@@ -8,7 +8,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package de.jflex.plugin.maven;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
import java.io.File;
import org.junit.Test;
@@ -16,9 +16,13 @@
public class ClassInfoTest {
@Test
public void testGetOutputFilename() {
- ClassInfo clazz = new ClassInfo();
- clazz.className = "Bar";
- clazz.packageName = "org.foo";
- assertEquals(new File("org/foo/Bar.java"), new File(clazz.getOutputFilename()));
+ ClassInfo clazz = new ClassInfo("Bar", "org.foo");
+ assertThat(new File(clazz.getOutputFilename())).isEqualTo(new File("org/foo/Bar.java"));
+ }
+
+ @Test
+ public void testGetOutputFilename_defaultPackage() {
+ ClassInfo clazz = new ClassInfo("Bar", null);
+ assertThat(new File(clazz.getOutputFilename())).isEqualTo(new File("Bar.java"));
}
}
diff --git a/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/JFlexMojoTest.java b/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/JFlexMojoTest.java
index c07e41f4a..65a0b5b3e 100644
--- a/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/JFlexMojoTest.java
+++ b/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/JFlexMojoTest.java
@@ -8,8 +8,8 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package de.jflex.plugin.maven;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import com.google.common.base.Predicate;
import java.io.File;
@@ -48,8 +48,9 @@ public void testTestResources() throws IOException {
String actualResDir = testResources.getBasedir("single-file-test").getAbsolutePath();
String expectedSuffix =
"/jflex-maven-plugin/target/test-projects/JFlexMojoTest_testTestResources_single-file-test";
- assertTrue(
- actualResDir + " ends with " + expectedSuffix, actualResDir.endsWith(expectedSuffix));
+ assertWithMessage(actualResDir + " ends with " + expectedSuffix)
+ .that(actualResDir.endsWith(expectedSuffix))
+ .isTrue();
}
/** Tests configuration with a single input file. */
@@ -59,7 +60,7 @@ public void testSingleFile() throws Exception {
mojo.execute();
File produced = getExpectedOutputFile(mojo);
- assertTrue("produced file is a file: " + produced, produced.isFile());
+ assertWithMessage("produced file is a file: " + produced).that(produced.isFile()).isTrue();
long size = produced.length();
/*
@@ -68,7 +69,9 @@ public void testSingleFile() throws Exception {
* Windows platform ("\r\n") than on a Unix platform ("\n").
*/
boolean correctSize = (size > 26624) && (size < 36696);
- assertTrue("size of produced file between 26k and 36k. Actual is " + size, correctSize);
+ assertWithMessage("size of produced file between 26k and 36k. Actual is " + size)
+ .that(correctSize)
+ .isTrue();
}
/** Tests configuration with a single input directory. */
@@ -78,7 +81,7 @@ public void testSingleDir() throws Exception {
mojo.execute();
File produced = getExpectedOutputFile(mojo);
- assertTrue("produced file is a file: " + produced, produced.isFile());
+ assertWithMessage("produced file is a file: " + produced).that(produced.isFile()).isTrue();
}
/** Tests configuration with a single input directory containing sub directories. */
@@ -88,16 +91,16 @@ public void testRecursion() throws Exception {
mojo.execute();
File produced = getExpectedOutputFile(mojo);
- assertTrue("produced file is a file: " + produced, produced.isFile());
+ assertWithMessage("produced file is a file: " + produced).that(produced.isFile()).isTrue();
}
@Test
public void extensionPredicate() {
Predicate predicate = new JFlexMojo.ExtensionPredicate("bar", "baz");
- assertTrue(predicate.apply(new File("/tmp/foo.bar")));
- assertTrue(predicate.apply(new File("/tmp/foo.baz")));
- assertFalse(predicate.apply(new File("/tmp/foo.bar.too")));
- assertFalse(predicate.apply(new File("/tmp/foo.blahblahbar")));
+ assertThat(predicate.apply(new File("/tmp/foo.bar"))).isTrue();
+ assertThat(predicate.apply(new File("/tmp/foo.baz"))).isTrue();
+ assertThat(predicate.apply(new File("/tmp/foo.bar.too"))).isFalse();
+ assertThat(predicate.apply(new File("/tmp/foo.blahblahbar"))).isFalse();
}
/**
diff --git a/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/LexSimpleAnalyzerTest.java b/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/LexSimpleAnalyzerTest.java
new file mode 100644
index 000000000..561f2a669
--- /dev/null
+++ b/jflex-maven-plugin/src/test/java/de/jflex/plugin/maven/LexSimpleAnalyzerTest.java
@@ -0,0 +1,87 @@
+package de.jflex.plugin.maven;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.IOException;
+import java.io.StringReader;
+import org.junit.Test;
+
+/** Test for {@link LexSimpleAnalyzer}. */
+public class LexSimpleAnalyzerTest {
+
+ @Test
+ public void guessPackageAndClass_givenClass_defaultPackage() throws Exception {
+ String lex =
+ "\n"
+ + "%%\n"
+ + "\n"
+ + "%public\n"
+ + "%class Foo\n"
+ + "\n"
+ + "%apiprivate\n"
+ + "%int\n"
+ + "\n"
+ + "%%\n"
+ + "\n"
+ + "[^] { /* no action */ }\n";
+ assertThat(guessPackageAndClass(lex)).isEqualTo(new ClassInfo("Foo", null));
+ }
+
+ @Test
+ public void guessPackageAndClass_defaultClass_defaultPackage() throws Exception {
+ String lex =
+ "\n"
+ + "%%\n"
+ + "\n"
+ + "%public\n"
+ + "\n"
+ + "%%\n"
+ + "\n"
+ + "^\"hello\"$ { System.out.println(\"hello\"); }\n"
+ + "\n";
+ assertThat(guessPackageAndClass(lex)).isEqualTo(new ClassInfo("Yylex", null));
+ }
+
+ @Test
+ public void guessPackageAndClass_defaultClass_hintPackage() throws Exception {
+ String lex =
+ "\n"
+ + "package org.example;\n"
+ + "\n"
+ + "import java.io.File;\n"
+ + "\n"
+ + "%%\n"
+ + "\n"
+ + "%final\n"
+ + "%public\n"
+ + "\n";
+ assertThat(guessPackageAndClass(lex)).isEqualTo(new ClassInfo("Yylex", "org.example"));
+ }
+
+ /**
+ * Tests that a random "package" string doesn't mislead JFlex in finding a package name.
+ *
+ *
See issue #104.
+ */
+ @Test
+ public void guessPackageAndClass_defaultClass_misleadingPackage() throws Exception {
+ String lex =
+ "\n"
+ + "%%\n"
+ + "\n"
+ + "%public\n"
+ + "\n"
+ + "%%\n"
+ + "\n"
+ + " {"
+ + " \"package\" { return symbol(PACKAGE); }\n"
+ + " \"private\" { return symbol(PRIVATE); }"
+ + "}\n"
+ + "\n";
+ assertThat(guessPackageAndClass(lex)).isEqualTo(new ClassInfo("Yylex", null));
+ }
+
+ private ClassInfo guessPackageAndClass(String lex) throws IOException {
+ return LexSimpleAnalyzer.guessPackageAndClass(new StringReader(lex));
+ }
+}
diff --git a/jflex-unicode-maven-plugin/README.md b/jflex-unicode-maven-plugin/README.md
new file mode 100644
index 000000000..f12031c71
--- /dev/null
+++ b/jflex-unicode-maven-plugin/README.md
@@ -0,0 +1,8 @@
+# Unicode maven plugin
+
+If you are not a JFlex developer, you don't need this plugin.
+
+This plugin fetches Unicode from unicode.org and generate their corresponding Java sources.
+
+Because this process takes time, we have actually checked-in the code in [jflex.unicode.data](..//jflex/src/main/java/jflex/unicode/data).
+
diff --git a/jflex-unicode-maven-plugin/src/main/java/jflex/DataFileType.java b/jflex-unicode-maven-plugin/src/main/java/jflex/DataFileType.java
index 4eddea2c5..c44d7f550 100644
--- a/jflex-unicode-maven-plugin/src/main/java/jflex/DataFileType.java
+++ b/jflex-unicode-maven-plugin/src/main/java/jflex/DataFileType.java
@@ -5,56 +5,62 @@
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public enum DataFileType {
PROPERTY_ALIASES("PropertyAliases") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- PropertyAliasesScanner scanner = new PropertyAliasesScanner(reader, version);
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ PropertyAliasesScanner scanner = new PropertyAliasesScanner(reader, version);
+ scanner.scan();
+ }
}
},
PROPERTY_VALUE_ALIASES("PropertyValueAliases") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- PropertyValueAliasesScanner scanner = new PropertyValueAliasesScanner(reader, version);
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ PropertyValueAliasesScanner scanner = new PropertyValueAliasesScanner(reader, version);
+ scanner.scan();
+ }
}
},
UNICODE_DATA("UnicodeData") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- UnicodeDataScanner scanner = new UnicodeDataScanner(reader, version);
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ UnicodeDataScanner scanner = new UnicodeDataScanner(reader, version);
+ scanner.scan();
+ }
}
},
PROPLIST("PropList") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- // Before Unicode 3.1, PropList-X.X.X.txt used a different format.
- // Before Unicode 2.0, PropList-X.X.X.txt did not exist.
- if (version.majorMinorVersion.equals("2.0")
- || version.majorMinorVersion.equals("2.1")
- || version.majorMinorVersion.equals("3.0")) {
- ArchaicPropListScanner scanner = new ArchaicPropListScanner(reader, version);
- scanner.scan();
- } else {
- BinaryPropertiesFileScanner scanner = new BinaryPropertiesFileScanner(reader, version);
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ // Before Unicode 3.1, PropList-X.X.X.txt used a different format.
+ // Before Unicode 2.0, PropList-X.X.X.txt did not exist.
+ if (Objects.equals(version.majorMinorVersion, "2.0")
+ || Objects.equals(version.majorMinorVersion, "2.1")
+ || Objects.equals(version.majorMinorVersion, "3.0")) {
+ ArchaicPropListScanner scanner = new ArchaicPropListScanner(reader, version);
+ scanner.scan();
+ } else {
+ BinaryPropertiesFileScanner scanner = new BinaryPropertiesFileScanner(reader, version);
+ scanner.scan();
+ }
}
}
},
DERIVED_CORE_PROPERTIES("DerivedCoreProperties") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- BinaryPropertiesFileScanner scanner = new BinaryPropertiesFileScanner(reader, version);
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ BinaryPropertiesFileScanner scanner = new BinaryPropertiesFileScanner(reader, version);
+ scanner.scan();
+ }
}
},
@@ -64,95 +70,103 @@ public void scan(URL url, UnicodeVersion version) throws IOException {
// From Unicode 5.0 onward, the default Script property value is "Unknown".
// Prior to Unicode 3.1, Scripts(-X.X.X).txt did not exist.
String defaultPropertyValue = "Unknown";
- if (version.majorMinorVersion.equals("3.1")
- || version.majorMinorVersion.equals("3.2")
- || version.majorMinorVersion.equals("4.0")
- || version.majorMinorVersion.equals("4.1")) {
+ if (Objects.equals(version.majorMinorVersion, "3.1")
+ || Objects.equals(version.majorMinorVersion, "3.2")
+ || Objects.equals(version.majorMinorVersion, "4.0")
+ || Objects.equals(version.majorMinorVersion, "4.1")) {
defaultPropertyValue = "Common";
}
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- EnumeratedPropertyFileScanner scanner =
- new EnumeratedPropertyFileScanner(reader, version, "Script", defaultPropertyValue);
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ EnumeratedPropertyFileScanner scanner =
+ new EnumeratedPropertyFileScanner(reader, version, "Script", defaultPropertyValue);
+ scanner.scan();
+ }
}
},
// SCRIPT_EXTENSIONS must follow SCRIPTS
SCRIPT_EXTENSIONS("ScriptExtensions") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- ScriptExtensionsScanner scanner =
- new ScriptExtensionsScanner(reader, version, "Script_Extensions");
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ ScriptExtensionsScanner scanner =
+ new ScriptExtensionsScanner(reader, version, "Script_Extensions");
+ scanner.scan();
+ }
}
},
BLOCKS("Blocks") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- // Before Unicode 3.1, Blocks-X.txt used a different format.
- // Before Unicode 2.0, Blocks-X.txt did not exist.
- if (version.majorMinorVersion.equals("2.0")
- || version.majorMinorVersion.equals("2.1")
- || version.majorMinorVersion.equals("3.0")) {
- ArchaicBlocksScanner scanner = new ArchaicBlocksScanner(reader, version);
- scanner.scan();
- } else {
- EnumeratedPropertyFileScanner scanner =
- new EnumeratedPropertyFileScanner(reader, version, "Block", "No_Block");
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ // Before Unicode 3.1, Blocks-X.txt used a different format.
+ // Before Unicode 2.0, Blocks-X.txt did not exist.
+ if (Objects.equals(version.majorMinorVersion, "2.0")
+ || Objects.equals(version.majorMinorVersion, "2.1")
+ || Objects.equals(version.majorMinorVersion, "3.0")) {
+ ArchaicBlocksScanner scanner = new ArchaicBlocksScanner(reader, version);
+ scanner.scan();
+ } else {
+ EnumeratedPropertyFileScanner scanner =
+ new EnumeratedPropertyFileScanner(reader, version, "Block", "No_Block");
+ scanner.scan();
+ }
}
}
},
LINE_BREAK("LineBreak") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- // In Unicode 3.0, LineBreak-X.txt used a different format.
- // Before Unicode 3.0, LineBreak-X.txt did not exist.
- if (version.majorMinorVersion.equals("3.0")) {
- ArchaicLineBreakScanner scanner = new ArchaicLineBreakScanner(reader, version);
- scanner.scan();
- } else {
- EnumeratedPropertyFileScanner scanner =
- new EnumeratedPropertyFileScanner(reader, version, "Line_Break", "XX");
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ // In Unicode 3.0, LineBreak-X.txt used a different format.
+ // Before Unicode 3.0, LineBreak-X.txt did not exist.
+ if (Objects.equals(version.majorMinorVersion, "3.0")) {
+ ArchaicLineBreakScanner scanner = new ArchaicLineBreakScanner(reader, version);
+ scanner.scan();
+ } else {
+ EnumeratedPropertyFileScanner scanner =
+ new EnumeratedPropertyFileScanner(reader, version, "Line_Break", "XX");
+ scanner.scan();
+ }
}
}
},
GRAPHEME_BREAK_PROPERTY("GraphemeBreakProperty") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- EnumeratedPropertyFileScanner scanner =
- new EnumeratedPropertyFileScanner(reader, version, "Grapheme_Cluster_Break", "Other");
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ EnumeratedPropertyFileScanner scanner =
+ new EnumeratedPropertyFileScanner(reader, version, "Grapheme_Cluster_Break", "Other");
+ scanner.scan();
+ }
}
},
SENTENCE_BREAK_PROPERTY("SentenceBreakProperty") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- EnumeratedPropertyFileScanner scanner =
- new EnumeratedPropertyFileScanner(reader, version, "Sentence_Break", "Other");
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ EnumeratedPropertyFileScanner scanner =
+ new EnumeratedPropertyFileScanner(reader, version, "Sentence_Break", "Other");
+ scanner.scan();
+ }
}
},
WORD_BREAK_PROPERTY("WordBreakProperty") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- EnumeratedPropertyFileScanner scanner =
- new EnumeratedPropertyFileScanner(reader, version, "Word_Break", "Other");
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ EnumeratedPropertyFileScanner scanner =
+ new EnumeratedPropertyFileScanner(reader, version, "Word_Break", "Other");
+ scanner.scan();
+ }
}
},
DERIVED_AGE("DerivedAge") {
public void scan(URL url, UnicodeVersion version) throws IOException {
- Reader reader = new InputStreamReader(url.openStream(), "UTF-8");
- DerivedAgeScanner scanner = new DerivedAgeScanner(reader, version);
- scanner.scan();
+ try (Reader reader = new InputStreamReader(url.openStream(), "UTF-8")) {
+ DerivedAgeScanner scanner = new DerivedAgeScanner(reader, version);
+ scanner.scan();
+ }
}
/**
* Always return the URL for the latest Unicode version's DerivedAge.txt, except for Unicode
diff --git a/jflex-unicode-maven-plugin/src/main/java/jflex/NamedRange.java b/jflex-unicode-maven-plugin/src/main/java/jflex/NamedRange.java
index 567b70db4..dea4f86be 100644
--- a/jflex-unicode-maven-plugin/src/main/java/jflex/NamedRange.java
+++ b/jflex-unicode-maven-plugin/src/main/java/jflex/NamedRange.java
@@ -1,7 +1,10 @@
package jflex;
+import java.util.Objects;
+
/** Internal-use class to represent code point intervals. */
public class NamedRange implements Comparable {
+
int start;
int end;
String name;
@@ -17,11 +20,27 @@ public class NamedRange implements Comparable {
this.name = name;
}
- public boolean equals(NamedRange other) {
- return null != other
- && (start == other.start
- && end == other.end
- && ((null == name && null == other.name) || (null != name && name.equals(other.name))));
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof NamedRange)) {
+ return false;
+ }
+ NamedRange other = (NamedRange) obj;
+ return start == other.start && end == other.end && Objects.equals(name, other.name);
+ }
+
+ @Override
+ public int hashCode() {
+ int h = 1;
+ h *= 1_000_003;
+ h ^= start;
+ h *= 1_000_003;
+ h ^= end;
+ if (name != null) {
+ h *= 1_000_003;
+ h ^= name.hashCode();
+ }
+ return h;
}
public int compareTo(NamedRange other) {
diff --git a/jflex-unicode-maven-plugin/src/main/java/jflex/UnicodePropertiesSkeleton.java b/jflex-unicode-maven-plugin/src/main/java/jflex/UnicodePropertiesSkeleton.java
index 8e768e51c..937e44501 100644
--- a/jflex-unicode-maven-plugin/src/main/java/jflex/UnicodePropertiesSkeleton.java
+++ b/jflex-unicode-maven-plugin/src/main/java/jflex/UnicodePropertiesSkeleton.java
@@ -22,7 +22,7 @@
* portion of generated code between every two parts of skeleton code.
*
*
There is a static part (the skeleton code) and state based iterator part to this class. The
- * iterator part is used to emit consecutive skeleton sections to some StringBuilder.
+ * iterator part is used to emit consecutive skeleton sections to some {@code StringBuilder}.
*
*
Copied from the version used for scanner generation.
*/
diff --git a/jflex-unicode-maven-plugin/src/main/java/jflex/UnicodeVersion.java b/jflex-unicode-maven-plugin/src/main/java/jflex/UnicodeVersion.java
index f81f1d164..c56dcbbd3 100644
--- a/jflex-unicode-maven-plugin/src/main/java/jflex/UnicodeVersion.java
+++ b/jflex-unicode-maven-plugin/src/main/java/jflex/UnicodeVersion.java
@@ -23,6 +23,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
@@ -302,7 +303,7 @@ void addInterval(String propName, int startCodePoint, int endCodePoint) {
// U+4E00 is listed in UnicodeData-1.1.5.txt as having the "Lo" property
// value, as are the previous code points, so to include
// [ U+4E00 - U+9FFF ], this interval should be extended to U+9FFF.
- if (range.end == 0x4E00 && majorMinorVersion.equals("1.1")) {
+ if (range.end == 0x4E00 && Objects.equals(majorMinorVersion, "1.1")) {
range.end = 0x9FFF;
}
intervals.add(new NamedRangeSet(range));
@@ -355,7 +356,8 @@ void addInterval(String propName, String propValue, int startCodePoint, int endC
List ranges = removeSurrogates(startCodePoint, endCodePoint);
if (!ranges.isEmpty()) {
String canonicalValue = propName + '=' + propValue;
- if (propName.equals(NORMALIZED_GENERAL_CATEGORY) || propName.equals(NORMALIZED_SCRIPT)) {
+ if (Objects.equals(propName, NORMALIZED_GENERAL_CATEGORY)
+ || Objects.equals(propName, NORMALIZED_SCRIPT)) {
canonicalValue = propValue;
}
NamedRangeSet intervals = propertyValueIntervals.get(canonicalValue);
@@ -374,7 +376,9 @@ void addInterval(String propName, String propValue, int startCodePoint, int endC
// FE70; FEFF; Arabic Presentation Forms-B
// ...
// FEFF; FEFF; Specials
- if (range.start == 0xFE70 && range.end == 0xFEFF && majorMinorVersion.equals("2.0")) {
+ if (range.start == 0xFE70
+ && range.end == 0xFEFF
+ && Objects.equals(majorMinorVersion, "2.0")) {
range.end = 0xFEFE;
}
intervals.add(new NamedRangeSet(range));
@@ -388,7 +392,7 @@ void addInterval(String propName, String propValue, int startCodePoint, int endC
// Initial letters of two-letter General Category property values
// should be put on the used property values list
- if (propName.equals(NORMALIZED_GENERAL_CATEGORY) && propValue.length() == 2) {
+ if (Objects.equals(propName, NORMALIZED_GENERAL_CATEGORY) && propValue.length() == 2) {
String firstLetter = propValue.substring(0, 1);
usedValues.add(firstLetter);
}
@@ -493,7 +497,7 @@ SortedMap getUsedPropertyValueAliases() {
SortedMap usedPropertyValueAliases = new TreeMap<>();
for (String binaryProperty : usedBinaryProperties) {
for (String nameAlias : getPropertyAliases(binaryProperty)) {
- if (!nameAlias.equals(binaryProperty)) {
+ if (!Objects.equals(nameAlias, binaryProperty)) {
usedPropertyValueAliases.put(nameAlias, binaryProperty);
}
}
@@ -509,10 +513,11 @@ SortedMap getUsedPropertyValueAliases() {
String canonicalValue = propName + '=' + propValue;
// Add value-only aliases for General Category and Script properties.
- if (propName.equals(NORMALIZED_SCRIPT) || propName.equals(NORMALIZED_GENERAL_CATEGORY)) {
+ if (Objects.equals(propName, NORMALIZED_SCRIPT)
+ || Objects.equals(propName, NORMALIZED_GENERAL_CATEGORY)) {
canonicalValue = propValue;
for (String valueAlias : getPropertyValueAliases(propName, propValue)) {
- if (!valueAlias.equals(propValue)) {
+ if (!Objects.equals(valueAlias, propValue)) {
usedPropertyValueAliases.put(valueAlias, propValue);
}
}
@@ -523,9 +528,10 @@ SortedMap getUsedPropertyValueAliases() {
// all possible alias combinations, exclude the one that is the same
// as the full property name + full property value, unless the
// property is General Category or Script.
- if (propName.equals(NORMALIZED_SCRIPT)
- || propName.equals(NORMALIZED_GENERAL_CATEGORY)
- || !(nameAlias.equals(propName) && valueAlias.equals(propValue))) {
+ if (Objects.equals(propName, NORMALIZED_SCRIPT)
+ || Objects.equals(propName, NORMALIZED_GENERAL_CATEGORY)
+ || !(Objects.equals(nameAlias, propName)
+ && Objects.equals(valueAlias, propValue))) {
String alias = nameAlias + '=' + valueAlias;
usedPropertyValueAliases.put(alias, canonicalValue);
}
diff --git a/jflex/.gitignore b/jflex/.gitignore
deleted file mode 100644
index c3ebe0a51..000000000
--- a/jflex/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Generated by ant
-build
-
diff --git a/jflex/BUILD b/jflex/BUILD
new file mode 100644
index 000000000..27ab922c3
--- /dev/null
+++ b/jflex/BUILD
@@ -0,0 +1,43 @@
+package(default_visibility = ["//visibility:public"])
+
+load("//cup:cup.bzl", "cup")
+load("@jflex_rules//jflex:jflex.bzl", "jflex")
+
+java_binary(
+ name = "jflex_bin",
+ main_class = "jflex.Main",
+ runtime_deps = [
+ ":jflex",
+ "//cup:cup_runtime",
+ ],
+)
+
+java_library(
+ name = "jflex",
+ srcs = glob(["src/main/java/**/*.java"]) + [
+ ":gen_parser",
+ ":gen_scanner",
+ ],
+ resources = glob(["src/main/resources/**"]),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//cup",
+ "//third_party/org/apache/ant",
+ ],
+)
+
+cup(
+ name = "gen_parser",
+ src = "src/main/cup/LexParse.cup",
+ interface = True,
+ parser = "LexParse",
+ symbols = "sym",
+)
+
+# Use bootstrap version defined in @jflex_rules
+jflex(
+ name = "gen_scanner",
+ srcs = ["src/main/jflex/LexScan.flex"],
+ outputs = ["LexScan.java"],
+ skeleton = "src/main/jflex/skeleton.nested",
+)
diff --git a/jflex/README.md b/jflex/README.md
index b5262df9d..5bc26debb 100644
--- a/jflex/README.md
+++ b/jflex/README.md
@@ -3,33 +3,27 @@
This directory contains JFlex, a fast scanner generator for Java.
To run JFlex, run `bin/jflex` from the command line or double click on the
-JFLex jar file in the `lib/` directory. You need JDK 1.7 installed and set up.
+JFLex jar file in the `lib/` directory.
See the manual in `doc/` or the website at for more
information and for how to get started.
-## Contents ##
+## Contents
- bin/ command line start scripts
- doc/ manual
- examples/ some example scanners
- lib/ JFlex jar file, syntax highlighting files
- src/ JFLex sources
-
- pom.xml Maven project object model, useful commands:
- mvn compile build and compile JFlex
- mvn test run unit tests
- mvn package generate the JFlex jar
-
- build.xml Ant build file, useful commands:
- ant gettools get tools to run Ant build
- ant compile build and compile JFlex
- ant test run unit tests
- ant jar generate the JFlex jar
+ ├── build.xml script to build with ant
+ ├── changelog.md summary of the changes
+ ├── pom.xml project object model to build with Maven
+ ├── README.md this file
+ ├── bin command line start scripts
+ ├── [build] build directory if you used ant
+ ├── doc user manual
+ ├── examples example scanners and parsers
+ ├── lib syntax highlighting files ; also JFlex jar in binary distribution
+ ├── src JFLex sources
+ └── target
-
-## Dependencies ##
+## Dependencies
* To run JFlex, you need at least JDK 1.7.
* To build JFlex, you need JDK 1.7+ and Maven 3.
diff --git a/jflex/bin/jflex.bat b/jflex/bin/jflex.bat
index 70bc776fe..50d848467 100755
--- a/jflex/bin/jflex.bat
+++ b/jflex/bin/jflex.bat
@@ -1,8 +1,8 @@
@echo off
-REM Please adjust JFLEX_HOME to suit your needs
+REM Please adjust JFLEX_HOME and JFLEX_VERSION to suit your needs
REM (please do not add a trailing backslash)
-set JFLEX_HOME=C:\JFLEX
-set JFLEX_VERSION=1.7.1-SNAPSHOT
+if not defined JFLEX_HOME set JFLEX_HOME=C:\JFLEX
+if not defined JFLEX_VERSION set JFLEX_VERSION=1.7.1-SNAPSHOT
-java -Xmx128m -jar "%JFLEX_HOME%"\lib\jflex-full-%JFLEX_VERSION%.jar %*
+java -Xmx128m -jar "%JFLEX_HOME%\lib\jflex-full-%JFLEX_VERSION%.jar" %*
diff --git a/jflex/build.xml b/jflex/build.xml
deleted file mode 100644
index 12ab2fb05..000000000
--- a/jflex/build.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/jflex/examples/.gitignore b/jflex/examples/.gitignore
index cdb8ba5c2..b03ceed63 100644
--- a/jflex/examples/.gitignore
+++ b/jflex/examples/.gitignore
@@ -1,10 +1,5 @@
-*/output.txt
-interpreter/Yylex.java
-java/Scanner.java
-java/UnicodeEscapes.java
-java/lexer-output.txt
-cup/Lexer.java
-byaccj/Yylex.java
-zero-reader/ZeroLexer.java
-*/parser.java
-*/sym.java
+antbuild
+target
+out
+cup_runtime.jar
+jflex.jar
diff --git a/jflex/examples/README.md b/jflex/examples/README.md
new file mode 100644
index 000000000..63bcc486a
--- /dev/null
+++ b/jflex/examples/README.md
@@ -0,0 +1,94 @@
+# JFlex examples
+
+## The Examples
+
+* **byaccj**:
+ integration between JFlex and byacc/j on a simple parser for an arithmetic calculator
+* **cup-interpreter**:
+ integration between JFlex and CUP on a complex interpreter
+* **cup-java**:
+ integration between JFlex and CUP on a a Java parser
+* **cup-lcalc**:
+ integration between JFlex and CUP on a simple parser for a arithmetic calculator
+* **simple**:
+ a simple lexer with no parser integration
+* **standalone**:
+ an "hello world" parser for which the `main` is generated automatically
+* **zero-reader**:
+ This example shows how to work with input Readers that sometimes return 0
+ characters.
+
+Every example also provides its own `README.md` with more context.
+
+
+## Build systems
+
+All examples (try to) support multiple build systems:
+- [Maven](https://maven.apache.org/).
+- [ant](https://ant.apache.org/).
+- [bazel](https://bazel.build/).
+- [make](https://www.gnu.org/software/make).
+
+All examples follow the Maven layout, in particular:
+- `src` contains the source files
+ - `src/main` contains the source files for the actual programm
+ - `src/main/java` contains the Java sources
+ - `src/main/jflex` contains the flex definitions that should be used by JFlex
+ to generate java code
+ - `src/main/cup` contains the CUP definitions that should be used by CUP
+ - `src/test` contains the source files for tests
+ - `src/test/data` contains an input file for the scanner; as well as a _golden file_
+ of the expected output for this input.
+
+
+### Maven
+
+When the example can be build with Maven, there is a `pom.xml`.
+
+Please use `mvn package` to
+- generate the Java source from flex and cup definitions
+- compile all Java source
+- run unit tests
+
+Build artifacts are in `target` (in subdirectories depending on their nature).
+
+In the end run the compiled lexer with:
+`java -jar target/` _BUILD-ARTEFACT.jar_ ``
+
+
+### ant
+
+When the example can be build with Maven, there is a `build.xml`.
+
+We place build artifacts in the `antbuild` directory.
+
+Also, we consistently use:
+- `ant` _default action_ for **compile**
+- `ant compile` to generate the source code form flex and cup definitions
+ and compile all Java code
+- `ant run` to run the lexer on a sample input
+- `ant test` to run the lexer on the sample input and check it produces
+ the expected output.
+
+
+### Bazel
+
+We test the examples with Bazel.
+
+In order to use the Skylark "jflex()" rule and see example, please see
+[jflex-de/bazel_rules](https://github.com/jflex-de/bazel_rules).
+
+
+### GNU make
+
+When the example can be build with make, there is a `Makefile`.
+
+We place build artifacts in the `out` directory.
+
+Also, we consistently use:
+- `make` _default action_ for **compile**
+- `make compile` to generate the source code form flex and cup definitions
+ and compile all Java code
+- `make run` to run the lexer on a sample input
+- `make test` to run the lexer on the sample input and check it produces
+ the expected output.
diff --git a/jflex/examples/byaccj/Makefile b/jflex/examples/byaccj/Makefile
index 3312221b7..8597b57ec 100644
--- a/jflex/examples/byaccj/Makefile
+++ b/jflex/examples/byaccj/Makefile
@@ -1,27 +1,23 @@
-# only works with the Java extension of yacc:
-# byacc/j from http://troi.lincom-asg.com/~rjamison/byacc/
+# Be sure to use yacc/j ; not unix yacc nor bison.
+BYACCJ = yaccj -J
+ROOT = ../../..
+JFLEX = $(ROOT)/jflex/bin/jflex
-JFLEX = ../../bin/jflex
-BYACCJ = yacc -J
-JAVAC = javac
+run: all
+ java -cp out Parser
-# targets:
+all: build
-all: Parser.class
-
-run: Parser.class
- java Parser
-
-build: clean Parser.class
+build: Parser.class
clean:
- rm -f *~ *.class *.java
+ rm -rf out
Parser.class: Yylex.java Parser.java
- $(JAVAC) Parser.java
+ javac -d out out/*.java
-Yylex.java: calc.flex
- $(JFLEX) calc.flex
+Yylex.java: src/main/jflex/calc.flex
+ $(JFLEX) -d out $<
-Parser.java: calc.y
- $(BYACCJ) calc.y
+Parser.java: src/main/yacc/calc.y
+ $(BYACCJ) $< ; mv Parser.java ParserVal.java out
diff --git a/jflex/examples/byaccj/README.md b/jflex/examples/byaccj/README.md
index 4e04bf92a..1ba0d3b59 100644
--- a/jflex/examples/byaccj/README.md
+++ b/jflex/examples/byaccj/README.md
@@ -1,30 +1,32 @@
JFlex with Yacc
===============
-This directory contains an interoperability example for BYacc/J and JFlex.
+This directory contains an interoperability example for [BYacc/J][byaccj] and JFlex.
This example implements a small calculator.
-## Build and run
+## Build, run, test
+
+### Build with Make
Use the Makefile to generate the lexer and parser.
```
-make
+make all
```
The example can then be started with
```
-java Parser
+make run
```
## Files
-* `calc.flex`
+* `src/main/jflex/calc.flex`
JFlex specification for the lexical part of the arithmetic expressions.
-* `calc.y`
+* `src/main/yacc/calc.y`
BYacc/J specification and main program for the calculator.
diff --git a/jflex/examples/byaccj/calc.flex b/jflex/examples/byaccj/src/main/jflex/calc.flex
similarity index 100%
rename from jflex/examples/byaccj/calc.flex
rename to jflex/examples/byaccj/src/main/jflex/calc.flex
diff --git a/jflex/examples/byaccj/calc.y b/jflex/examples/byaccj/src/main/yacc/calc.y
similarity index 100%
rename from jflex/examples/byaccj/calc.y
rename to jflex/examples/byaccj/src/main/yacc/calc.y
diff --git a/jflex/examples/cup-interpreter/Makefile b/jflex/examples/cup-interpreter/Makefile
new file mode 100644
index 000000000..debf5e2c8
--- /dev/null
+++ b/jflex/examples/cup-interpreter/Makefile
@@ -0,0 +1,40 @@
+# uses JFlex >= 1.3.2, and CUP >= 0.10j
+#
+# targets:
+#
+# make all (or just: make)
+# generates lexer, and parser, and compiles all *.java files
+#
+# make test
+# starts the program on a test example
+#
+
+ROOT = ../../..
+JFLEX = $(ROOT)/jflex/bin/jflex
+CUPJAR = $(ROOT)/cup/cup/java-cup-11b.jar
+CUP = java -jar $(CUPJAR)
+
+all: clean compile
+
+compile: gen_cup gen_jflex src/main/java/*.java
+ javac -cp $(CUPJAR):out -d out src/main/java/*.java out/genfiles/*.java
+
+# writes parser.java sym.java
+gen_jflex: src/main/jflex/scanner.flex outdir
+ $(JFLEX) -d out/genfiles $<
+
+gen_cup: src/main/cup/parser.cup outdir
+ $(CUP) -interface < $<
+ mv parser.java sym.java out/genfiles
+
+output: compile src/test/data/example.as outdir
+ java -cp $(CUPJAR):out Main < src/test/data/example.as > out/output.txt
+
+test: output
+ @(diff out/output.txt src/test/data/output.good && echo "Test OK!") || (echo "Test FAILED"; exit 1)
+
+clean:
+ rm -rf out
+
+outdir:
+ mkdir -p out/genfiles
diff --git a/jflex/examples/interpreter/README.md b/jflex/examples/cup-interpreter/README.md
similarity index 73%
rename from jflex/examples/interpreter/README.md
rename to jflex/examples/cup-interpreter/README.md
index 2db90695f..ca3b5a49b 100644
--- a/jflex/examples/interpreter/README.md
+++ b/jflex/examples/cup-interpreter/README.md
@@ -4,6 +4,28 @@ FJlex complex example (with CUP)
This directory contains an interpreter for a small functional
programming language (called "AS"). It uses JFlex and CUP.
+## Build, run, test
+
+### Using Maven
+
+ ../../../mvnw package
+
+To run the interpreter on a sample input.
+
+ java -jar target/cup-interpreter-full-1.0.jar src/test/data/example.as
+
+You can expect `src/test/data/output.good`.
+
+### Using ant
+
+ ant compile
+ ant run
+
+### Using make
+
+ make test
+ java -cp java -cp ../../../cup/cup/java-cup-11b.jar:out src/test/data/example.as
+
## Files
- `Main.java` is the main program. It reads an AS program from
diff --git a/jflex/examples/cup-interpreter/build.xml b/jflex/examples/cup-interpreter/build.xml
new file mode 100644
index 000000000..79de2a52e
--- /dev/null
+++ b/jflex/examples/cup-interpreter/build.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jflex/examples/cup-interpreter/pom.xml b/jflex/examples/cup-interpreter/pom.xml
new file mode 100644
index 000000000..facef23ce
--- /dev/null
+++ b/jflex/examples/cup-interpreter/pom.xml
@@ -0,0 +1,105 @@
+
+
+ 4.0.0
+ de.flex.examples
+ cup-interpreter
+ 1.0
+ A parser for the AS language
+ An interpreter for a small functional
+ programming language (called "AS").
+ It uses JFlex and CUP.
+
+
+ de.jflex
+ cup_runtime
+ 11b
+
+
+ junit
+ junit
+ 3.8.2
+ test
+
+
+ com.google.truth
+ truth
+ 0.36
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.6
+ 1.6
+
+
+
+ de.jflex
+ jflex-maven-plugin
+ 1.7.1-SNAPSHOT
+
+
+
+ generate
+
+
+
+
+
+
+
+ de.jflex
+ cup-maven-plugin
+ 1.0
+
+
+
+ generate
+
+
+ true
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+ ${project.artifactId}-full-${project.version}
+
+
+ Main
+
+
+
+
+ de.jflex:cup_runtime
+
+
+
+
+
+
+
+
+
+ UTF-8
+
+
diff --git a/jflex/examples/interpreter/parser.cup b/jflex/examples/cup-interpreter/src/main/cup/parser.cup
similarity index 100%
rename from jflex/examples/interpreter/parser.cup
rename to jflex/examples/cup-interpreter/src/main/cup/parser.cup
diff --git a/jflex/examples/interpreter/AST.java b/jflex/examples/cup-interpreter/src/main/java/AST.java
similarity index 71%
rename from jflex/examples/interpreter/AST.java
rename to jflex/examples/cup-interpreter/src/main/java/AST.java
index efa183df6..19638abc8 100644
--- a/jflex/examples/interpreter/AST.java
+++ b/jflex/examples/cup-interpreter/src/main/java/AST.java
@@ -8,12 +8,10 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
- * General interface for nodes in the abstract syntax tree. Contains
- * only the method toString which is already inherited from Object,
- * so the interface doesn't add any functionality. It only provides
- * a common super type for all elements in the AST.
+ * General interface for nodes in the abstract syntax tree. Contains only the method toString which
+ * is already inherited from Object, so the interface doesn't add any functionality. It only
+ * provides a common super type for all elements in the AST.
*/
interface AST {
- public String toString(); // already inherited from Object
+ public String toString(); // already inherited from Object
}
-
diff --git a/jflex/examples/cup-interpreter/src/main/java/Main.java b/jflex/examples/cup-interpreter/src/main/java/Main.java
new file mode 100644
index 000000000..f61da8caa
--- /dev/null
+++ b/jflex/examples/cup-interpreter/src/main/java/Main.java
@@ -0,0 +1,71 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright (C) 2001 Gerwin Klein *
+ * Copyright (C) 2001 Bernhard Rumpe *
+ * All rights reserved. *
+ * *
+ * License: BSD *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+import java.io.*;
+
+/**
+ * Main program of the interpreter for the AS programming language. Based on JFlex/CUP.
+ *
+ *
Steps:
+ *
+ *
+ *
scanning (Yylex)
+ *
context free parsing and AST building (yyparse)
+ *
build up symbol table (setSymtabs)
+ *
check context conditions (checkcontext)
+ *
prepare interpretation (prepInterp)
+ *
start interpretation (interpret)
+ *
+ */
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+ Reader reader = null;
+
+ if (args.length == 1) {
+ File input = new File(args[0]);
+ if (!input.canRead()) {
+ System.err.println("Error: could not read [" + input + "]");
+ }
+ reader = new FileReader(input);
+ } else {
+ reader = new InputStreamReader(System.in);
+ }
+
+ Yylex scanner = new Yylex(reader); // create scanner
+ SymTab symtab = new SymTab(); // set global symbol table
+ scanner.setSymtab(symtab);
+
+ parser parser = new parser(scanner); // create parser
+ Tprogram syntaxbaum = null;
+
+ try {
+ syntaxbaum = (Tprogram) parser.parse().value; // parse
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ System.out.println(syntaxbaum);
+
+ syntaxbaum.setSymtabs(); // set symbol table
+
+ syntaxbaum.checkcontext(); // CoCo (DefVar, DefFun, Arity)
+ if (contexterror > 0) return;
+
+ syntaxbaum.prepInterp(); // var. indices and function pointers
+ // im Syntaxbaum setzen
+ syntaxbaum.interpret(); // interpretation
+ }
+
+ static int contexterror = 0; // number of errors in context conditions
+
+ public static void error(String s) {
+ System.out.println((contexterror++) + ". " + s);
+ }
+}
diff --git a/jflex/examples/interpreter/STEfun.java b/jflex/examples/cup-interpreter/src/main/java/STEfun.java
similarity index 68%
rename from jflex/examples/interpreter/STEfun.java
rename to jflex/examples/cup-interpreter/src/main/java/STEfun.java
index 46e47f53b..9bbee819b 100644
--- a/jflex/examples/interpreter/STEfun.java
+++ b/jflex/examples/cup-interpreter/src/main/java/STEfun.java
@@ -7,37 +7,34 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
/**
* Symbol table entry for functions.
- *
- * Contains arity and reference to location of definition
- */
+ *
+ *
Contains arity and reference to location of definition
+ */
class STEfun extends SymtabEntry {
int arity;
Tdekl dekl; // location of definition
-
- public STEfun(String f, Tdekl d, int a) {
+
+ public STEfun(String f, Tdekl d, int a) {
super(f);
- dekl=d;
- arity=a;
+ dekl = d;
+ arity = a;
}
-
- public int kind() {
- return SymtabEntry.FUN;
+
+ public int kind() {
+ return SymtabEntry.FUN;
}
- public String toString() {
- return "function "+name+", arity "+arity;
+ public String toString() {
+ return "function " + name + ", arity " + arity;
}
- public int arity() {
- return arity;
+ public int arity() {
+ return arity;
}
- public Tdekl getDekl() {
- return dekl;
+ public Tdekl getDekl() {
+ return dekl;
}
}
-
-
diff --git a/jflex/examples/interpreter/STEvar.java b/jflex/examples/cup-interpreter/src/main/java/STEvar.java
similarity index 69%
rename from jflex/examples/interpreter/STEvar.java
rename to jflex/examples/cup-interpreter/src/main/java/STEvar.java
index e813edc11..03bb80dde 100644
--- a/jflex/examples/interpreter/STEvar.java
+++ b/jflex/examples/cup-interpreter/src/main/java/STEvar.java
@@ -7,40 +7,35 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
/**
* Symbol table entry for variables.
- *
- * Contains index in the parameter list and a flag if it
- * is an input variable.
- */
+ *
+ *
Contains index in the parameter list and a flag if it is an input variable.
+ */
class STEvar extends SymtabEntry {
- boolean is_input;
- int index;
+ boolean is_input;
+ int index;
public STEvar(String v, boolean ii, int ind) {
super(v);
- is_input=ii;
- index=ind;
+ is_input = ii;
+ index = ind;
}
public int kind() {
- return SymtabEntry.VAR;
+ return SymtabEntry.VAR;
}
public String toString() {
- if (is_input)
- return "input var "+name+" ("+index+")";
- else
- return "parameter "+name+" ("+index+")";
+ if (is_input) return "input var " + name + " (" + index + ")";
+ else return "parameter " + name + " (" + index + ")";
}
public int getIndex() {
- return index;
+ return index;
}
public boolean isInput() {
- return is_input;
+ return is_input;
}
}
-
diff --git a/jflex/examples/interpreter/SymTab.java b/jflex/examples/cup-interpreter/src/main/java/SymTab.java
similarity index 60%
rename from jflex/examples/interpreter/SymTab.java
rename to jflex/examples/cup-interpreter/src/main/java/SymTab.java
index c82d11713..7f2634e22 100644
--- a/jflex/examples/interpreter/SymTab.java
+++ b/jflex/examples/cup-interpreter/src/main/java/SymTab.java
@@ -7,56 +7,53 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
import java.util.*;
/**
- * Symbol table for the interpreter, contains information about
- * variables and functions.
- *
- * For every binding location of a name a symbol will be created.
- * The symbol tables are connected hierarchically by pointers to
- * the predecessor. Lookup takes predecessors into account.
- */
+ * Symbol table for the interpreter, contains information about variables and functions.
+ *
+ *
For every binding location of a name a symbol will be created. The symbol tables are connected
+ * hierarchically by pointers to the predecessor. Lookup takes predecessors into account.
+ */
public class SymTab {
- Map m; // contains the list of words
- SymTab pred; // predecessor symbol table (if exists)
+ /** contains the list of words. */
+ Map m;
+ /** predecessor symbol table (if exists) */
+ SymTab pred;
public SymTab() {
- this(null);
+ this(null);
}
public SymTab(SymTab p) {
- m = new HashMap();
+ m = new HashMap();
pred = p;
}
public boolean enter(String s, SymtabEntry e) {
Object value = lookup(s);
m.put(s, e);
- return(value==null);
+ return (value == null);
}
public SymtabEntry lookup(String s) {
SymtabEntry value = m.get(s);
- if (value==null && pred!=null)
- value = pred.lookup(s);
+ if (value == null && pred != null) value = pred.lookup(s);
return value;
}
- public String toString() { // for output with print
+ public String toString() { // for output with print
StringBuilder res = new StringBuilder("symbol table\n=============\n");
-
- for (Map.Entry entry : m.entrySet())
+
+ for (Map.Entry entry : m.entrySet())
res.append(entry.getKey()).append(" \t").append(entry.getValue()).append("\n");
- if (pred != null)
- res.append("++ predecessor!\n");
+ if (pred != null) res.append("++ predecessor!\n");
return res.toString();
}
public int size() {
- return(m.size());
+ return (m.size());
}
}
diff --git a/jflex/examples/interpreter/SymtabEntry.java b/jflex/examples/cup-interpreter/src/main/java/SymtabEntry.java
similarity index 77%
rename from jflex/examples/interpreter/SymtabEntry.java
rename to jflex/examples/cup-interpreter/src/main/java/SymtabEntry.java
index f196b4fae..d1aa0c8fd 100644
--- a/jflex/examples/interpreter/SymtabEntry.java
+++ b/jflex/examples/cup-interpreter/src/main/java/SymtabEntry.java
@@ -7,31 +7,27 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
/**
- * Symbol table entry for names, there are subclasses for
- * variables and functions.
- *
- * Defines constants UNKNOWN, VAR and FUN as kinds of
- * symbol table entries.
- */
+ * Symbol table entry for names, there are subclasses for variables and functions.
+ *
+ *
Defines constants UNKNOWN, VAR and FUN as kinds of symbol table entries.
+ */
class SymtabEntry {
String name;
public SymtabEntry(String v) {
- name=v;
+ name = v;
}
public int kind() {
- return UNKNOWN;
+ return UNKNOWN;
}
public String toString() {
- return("unknown "+name);
+ return ("unknown " + name);
}
static final int UNKNOWN = 12;
static final int VAR = 13;
static final int FUN = 14;
}
-
diff --git a/jflex/examples/interpreter/Tboolexp.java b/jflex/examples/cup-interpreter/src/main/java/Tboolexp.java
similarity index 56%
rename from jflex/examples/interpreter/Tboolexp.java
rename to jflex/examples/cup-interpreter/src/main/java/Tboolexp.java
index f532a0a03..b87568f2f 100644
--- a/jflex/examples/interpreter/Tboolexp.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Tboolexp.java
@@ -7,47 +7,48 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/**
- * AST node for bool expressions
- */
+/** AST node for bool expressions */
class Tboolexp implements AST {
- Texp exp1, exp2; // left and right subexpression
- char kind; // '=', '<' and '!' for "<="
+ /** Left subexpression. */
+ Texp exp1;
+ /** Right subexpression. */
+ Texp exp2;
+ /** {@code '='}, {@code '<'} and {@code '!'} for "<=". */
+ char kind;
public Tboolexp(Texp e1, char k, Texp e2) {
- exp1=e1;
- kind=k;
- exp2=e2;
+ exp1 = e1;
+ kind = k;
+ exp2 = e2;
}
public String toString() {
- if (kind!='!')
- return(""+exp1+kind+exp2);
- else
- return(exp1+"<="+exp2);
+ if (kind != '!') return ("" + exp1 + kind + exp2);
+ else return (exp1 + "<=" + exp2);
}
- public void checkcontext(SymTab st) { // context conditions
+ public void checkcontext(SymTab st) { // context conditions
exp1.checkcontext(st);
exp2.checkcontext(st);
}
- public void prepInterp(SymTab st) { // set pointers and indices
+ public void prepInterp(SymTab st) { // set pointers and indices
exp1.prepInterp(st);
exp2.prepInterp(st);
}
public boolean interpret(int[] in, int[] par) {
- int e1 = exp1.interpret(in,par);
- int e2 = exp2.interpret(in,par);
- switch(kind) {
- case '=': return(e1==e2);
- case '<': return(e1 *
+ * Copyright (C) 2001 Bernhard Rumpe *
+ * All rights reserved. *
+ * *
+ * License: BSD *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/**
+ * AST node for function declarations.
+ *
+ *
Also contains a reference to the symbol table of the parameters and their arity.
+ */
+class Tdekl implements AST {
+ /** identifier */
+ Tident ident; //
+ /** list of parameters */
+ Tparlist parlist;
+ /** function body */
+ Texp exp;
+
+ public Tdekl(Tident i, Tparlist p, Texp e) {
+ parlist = p;
+ ident = i;
+ exp = e;
+ }
+
+ public String toString() {
+ return (ident + "(" + parlist + ") = \n " + exp);
+ }
+
+ SymTab params; // symbol table of the parameters
+ int arity;
+
+ public void setSymtab(SymTab st) {
+ params = new SymTab(st);
+ parlist.setSymtab(params, false, 0);
+ arity = params.size();
+
+ boolean isNew = st.enter(ident.toString(), new STEfun(ident.toString(), this, arity));
+ // CoCo (Fun)
+ if (!isNew) Main.error("funktion " + ident + " defined twice!");
+ }
+
+ public void printSymtabs() {
+ System.out.print("funktion " + ident.toString() + "\n" + params);
+ }
+
+ public void checkcontext() {
+ exp.checkcontext(params); // CoCo (DefFun,DefVar,Arity)
+ }
+
+ public void prepInterp(SymTab st) { // set pointers and indices
+ exp.prepInterp(params);
+ }
+
+ public int interpret(int[] in, int[] par) {
+ return (exp.interpret(in, par));
+ }
+
+ public int arity() {
+ return (arity);
+ }
+}
diff --git a/jflex/examples/interpreter/Tdekllist.java b/jflex/examples/cup-interpreter/src/main/java/Tdekllist.java
similarity index 56%
rename from jflex/examples/interpreter/Tdekllist.java
rename to jflex/examples/cup-interpreter/src/main/java/Tdekllist.java
index a6e126904..6ffca6657 100644
--- a/jflex/examples/interpreter/Tdekllist.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Tdekllist.java
@@ -7,52 +7,45 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/**
- * AST node for declaration lists of functions
- */
+/** AST node for declaration lists of functions */
class Tdekllist implements AST {
- Tdekllist dekllist; // rest list (optional null)
- Tdekl dekl; // declaration
+ /** rest list (optional null) */
+ Tdekllist dekllist;
+ /** declaration */
+ Tdekl dekl;
public Tdekllist(Tdekllist p, Tdekl e) {
- dekllist=p;
- dekl=e;
+ dekllist = p;
+ dekl = e;
}
public Tdekllist(Tdekl e) {
- dekllist=null;
- dekl=e;
+ dekllist = null;
+ dekl = e;
}
public String toString() {
- if (dekllist!=null)
- return(dekllist+",\n"+dekl);
- else
- return(dekl.toString());
+ if (dekllist != null) return (dekllist + ",\n" + dekl);
+ else return (dekl.toString());
}
public void setSymtab(SymTab st) {
- if (dekllist!=null)
- dekllist.setSymtab(st);
+ if (dekllist != null) dekllist.setSymtab(st);
dekl.setSymtab(st);
}
public void printSymtabs() {
- if (dekllist!=null)
- dekllist.printSymtabs();
+ if (dekllist != null) dekllist.printSymtabs();
dekl.printSymtabs();
}
-
+
public void checkcontext() {
- if (dekllist!=null)
- dekllist.checkcontext();
- dekl.checkcontext(); // CoCo (DefFun,DefVar,Arity)
- } // in function body
+ if (dekllist != null) dekllist.checkcontext();
+ dekl.checkcontext(); // CoCo (DefFun,DefVar,Arity)
+ } // in function body
- public void prepInterp(SymTab st) { // set pointers and indices
+ public void prepInterp(SymTab st) { // set pointers and indices
dekl.prepInterp(st);
- if (dekllist!=null) dekllist.prepInterp(st);
+ if (dekllist != null) dekllist.prepInterp(st);
}
}
-
diff --git a/jflex/examples/interpreter/Texp.java b/jflex/examples/cup-interpreter/src/main/java/Texp.java
similarity index 61%
rename from jflex/examples/interpreter/Texp.java
rename to jflex/examples/cup-interpreter/src/main/java/Texp.java
index a5ebae093..59bbc9602 100644
--- a/jflex/examples/interpreter/Texp.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Texp.java
@@ -7,26 +7,23 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
/**
* AST node for an integer expression.
- *
- * The non terminal exp is the sum of multiple variants and
- * therefore modelled as an abstract class.
- *
- * The interpretation function interpret is called with
- * valuations of input variables in and parameters
- * par. Before interpret can be called, pointers
- * and variable indices must be set with prepInterp.
- */
+ *
+ *
The non terminal exp is the sum of multiple variants and therefore modelled as an abstract
+ * class.
+ *
+ *
The interpretation function interpret is called with valuations of input variables
+ * in and parameters par. Before interpret can be called, pointers and variable
+ * indices must be set with prepInterp.
+ */
abstract class Texp implements AST {
// test context conditions (DefFun,DefVar,Arity)
- abstract public void checkcontext(SymTab st);
-
+ public abstract void checkcontext(SymTab st);
+
// set pointers and indices for variables and functions
- abstract public void prepInterp(SymTab st);
-
+ public abstract void prepInterp(SymTab st);
+
// interpretation
- abstract public int interpret(int[] in, int[] par);
+ public abstract int interpret(int[] in, int[] par);
}
-
diff --git a/jflex/examples/interpreter/Texpinfix.java b/jflex/examples/cup-interpreter/src/main/java/Texpinfix.java
similarity index 61%
rename from jflex/examples/interpreter/Texpinfix.java
rename to jflex/examples/cup-interpreter/src/main/java/Texpinfix.java
index a12222ed7..d3aae47ca 100644
--- a/jflex/examples/interpreter/Texpinfix.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Texpinfix.java
@@ -7,22 +7,20 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/**
- * AST node for infix expressions
- */
+/** AST node for infix expressions */
class Texpinfix extends Texp implements AST {
- Texp exp1, exp2; // left and right sub expression
- char kind; // kind ('+', '-', '*', '/')
+ Texp exp1, exp2; // left and right sub expression
+ /** kind ('+', '-', '*', '/') */
+ char kind;
public Texpinfix(Texp e1, char k, Texp e2) {
- exp1=e1;
- kind=k;
- exp2=e2;
+ exp1 = e1;
+ kind = k;
+ exp2 = e2;
}
public String toString() {
- return("("+exp1+kind+exp2+")");
+ return ("(" + exp1 + kind + exp2 + ")");
}
public void checkcontext(SymTab st) { // context conditions
@@ -30,24 +28,26 @@ public void checkcontext(SymTab st) { // context conditions
exp2.checkcontext(st);
}
- public void prepInterp(SymTab st) { // set pointers und indices
+ public void prepInterp(SymTab st) { // set pointers und indices
exp1.prepInterp(st);
exp2.prepInterp(st);
}
- public int interpret(int[] in, int[] par) {
- int e1 = exp1.interpret(in,par);
- int e2 = exp2.interpret(in,par);
+ public int interpret(int[] in, int[] par) {
+ int e1 = exp1.interpret(in, par);
+ int e2 = exp2.interpret(in, par);
switch (kind) {
- case '+': return(e1+e2);
- case '-': return(e1-e2);
- case '*': return(e1*e2);
- case '/': return(e1/e2);
+ case '+':
+ return (e1 + e2);
+ case '-':
+ return (e1 - e2);
+ case '*':
+ return (e1 * e2);
+ case '/':
+ return (e1 / e2);
}
- return -1; // error
+ return -1; // error
}
}
-
-
diff --git a/jflex/examples/interpreter/Texplist.java b/jflex/examples/cup-interpreter/src/main/java/Texplist.java
similarity index 51%
rename from jflex/examples/interpreter/Texplist.java
rename to jflex/examples/cup-interpreter/src/main/java/Texplist.java
index fc48a29b7..97e1214da 100644
--- a/jflex/examples/interpreter/Texplist.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Texplist.java
@@ -7,56 +7,48 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
/**
* AST node for a list of expressions.
- *
- * The interpretation of a list of expressions stores the
- * results of the expressions in an array that can be used
- * as parameter list for function calls.
- */
+ *
+ *
The interpretation of a list of expressions stores the results of the expressions in an array
+ * that can be used as parameter list for function calls.
+ */
class Texplist implements AST {
- Texplist explist; // next list element (optional null)
- Texp exp; // expression of this list node
+ Texplist explist; // next list element (optional null)
+ Texp exp; // expression of this list node
public Texplist(Texplist p, Texp e) {
- explist=p;
- exp=e;
+ explist = p;
+ exp = e;
}
public Texplist(Texp e) {
- explist=null;
- exp=e;
+ explist = null;
+ exp = e;
}
public String toString() {
- if (explist!=null)
- return explist+","+exp;
- else
- return exp.toString();
+ if (explist != null) return explist + "," + exp;
+ else return exp.toString();
}
public void checkcontext(SymTab st) {
- if (explist!=null)
- explist.checkcontext(st);
- exp.checkcontext(st); // CoCo (DefFun,DefVar,Arity)
- } // in expression
+ if (explist != null) explist.checkcontext(st);
+ exp.checkcontext(st); // CoCo (DefFun,DefVar,Arity)
+ } // in expression
public int length() {
- if (explist!=null)
- return 1+explist.length();
- else
- return 1;
+ if (explist != null) return 1 + explist.length();
+ else return 1;
}
-
- public void prepInterp(SymTab st) { // set pointers and indices
+
+ public void prepInterp(SymTab st) { // set pointers and indices
exp.prepInterp(st);
- if (explist!=null) explist.prepInterp(st);
+ if (explist != null) explist.prepInterp(st);
}
-
+
public void interpret(int[] in, int[] par, int[] res, int index) {
- res[index] = exp.interpret(in,par);
- if (explist!=null) explist.interpret(in,par,res,index+1);
+ res[index] = exp.interpret(in, par);
+ if (explist != null) explist.interpret(in, par, res, index + 1);
}
}
-
diff --git a/jflex/examples/interpreter/Tfun.java b/jflex/examples/cup-interpreter/src/main/java/Tfun.java
similarity index 57%
rename from jflex/examples/interpreter/Tfun.java
rename to jflex/examples/cup-interpreter/src/main/java/Tfun.java
index 8b329db13..2f5d9a5a3 100644
--- a/jflex/examples/interpreter/Tfun.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Tfun.java
@@ -7,49 +7,44 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
/**
* AST node for function application.
- *
- * Also contains pointer to declaration location of the function.
- */
+ *
+ *
Also contains pointer to declaration location of the function.
+ */
class Tfun extends Texp implements AST {
- Tident ident; // name of the function
- Texplist explist; // parameter list
+ Tident ident; // name of the function
+ Texplist explist; // parameter list
public Tfun(Tident i, Texplist e) {
- ident=i;
- explist=e;
+ ident = i;
+ explist = e;
}
public String toString() {
- return ident+"("+explist+")";
+ return ident + "(" + explist + ")";
}
public void checkcontext(SymTab st) { // CoCo (DefFun,Arity)
explist.checkcontext(st);
SymtabEntry ste = st.lookup(ident.toString());
- if (ste==null)
- Main.error("function not defined: "+ident);
- else if (ste.kind() != SymtabEntry.FUN)
- Main.error("variable used as funktion: "+ident);
- else if (((STEfun)ste).arity() != explist.length())
- Main.error("wrong arity at function call: "+ident);
+ if (ste == null) Main.error("function not defined: " + ident);
+ else if (ste.kind() != SymtabEntry.FUN) Main.error("variable used as funktion: " + ident);
+ else if (((STEfun) ste).arity() != explist.length())
+ Main.error("wrong arity at function call: " + ident);
}
- Tdekl fundekl; // pointer to location of function declaration
+ Tdekl fundekl; // pointer to location of function declaration
- // set pointers and indices
+ // set pointers and indices
public void prepInterp(SymTab st) {
- fundekl = ((STEfun)st.lookup(ident.toString())).getDekl();
+ fundekl = ((STEfun) st.lookup(ident.toString())).getDekl();
explist.prepInterp(st);
}
public int interpret(int[] in, int[] par) {
int[] newparams = new int[fundekl.arity()];
- explist.interpret(in,par,newparams,0);
- return fundekl.interpret(in,newparams);
+ explist.interpret(in, par, newparams, 0);
+ return fundekl.interpret(in, newparams);
}
}
-
-
diff --git a/jflex/examples/interpreter/Tident.java b/jflex/examples/cup-interpreter/src/main/java/Tident.java
similarity index 57%
rename from jflex/examples/interpreter/Tident.java
rename to jflex/examples/cup-interpreter/src/main/java/Tident.java
index a33fc4485..215d2f4e0 100644
--- a/jflex/examples/interpreter/Tident.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Tident.java
@@ -7,45 +7,36 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/**
- * AST node for an identifier
- */
+/** AST node for an identifier */
class Tident extends Texp implements AST {
- String name;
+ String name;
public Tident(String s) {
- name = s;
+ name = s;
}
public String toString() {
- return name;
+ return name;
}
- public void checkcontext(SymTab st) { // CoCo (DefVar)
+ public void checkcontext(SymTab st) { // CoCo (DefVar)
SymtabEntry ste = st.lookup(name);
- if (ste==null)
- Main.error("variable not defined: "+name);
- else if (ste.kind() != SymtabEntry.VAR)
- Main.error("function used as variable: "+name);
+ if (ste == null) Main.error("variable not defined: " + name);
+ else if (ste.kind() != SymtabEntry.VAR) Main.error("function used as variable: " + name);
}
- int index; // number of ident in environment
- boolean is_input; // is it an input variable?
+ int index; // number of ident in environment
+ boolean is_input; // is it an input variable?
- public void prepInterp(SymTab st) { // set index for environment
- STEvar ste = (STEvar)st.lookup(name);
+ public void prepInterp(SymTab st) { // set index for environment
+ STEvar ste = (STEvar) st.lookup(name);
index = ste.getIndex();
is_input = ste.isInput();
}
public int interpret(int[] in, int[] par) {
- if (is_input)
- return(in[index]);
- else
- return(par[index]);
+ if (is_input) return (in[index]);
+ else return (par[index]);
}
}
-
-
diff --git a/jflex/examples/interpreter/Tifthenelse.java b/jflex/examples/cup-interpreter/src/main/java/Tifthenelse.java
similarity index 72%
rename from jflex/examples/interpreter/Tifthenelse.java
rename to jflex/examples/cup-interpreter/src/main/java/Tifthenelse.java
index 03aefa3fc..6028be6f2 100644
--- a/jflex/examples/interpreter/Tifthenelse.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Tifthenelse.java
@@ -7,22 +7,23 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/**
- * AST node for if-then-else expressions
- */
+/** AST node for if-then-else expressions */
class Tifthenelse extends Texp implements AST {
- Tboolexp boolexp; // condition
- Texp exp1, exp2; // then and else branch
-
+ /** condition* */
+ Tboolexp boolexp;
+ /** then branch */
+ Texp exp1;
+ /** else branch */
+ Texp exp2;
+
public Tifthenelse(Tboolexp b, Texp e1, Texp e2) {
- boolexp=b;
- exp1=e1;
- exp2=e2;
+ boolexp = b;
+ exp1 = e1;
+ exp2 = e2;
}
-
+
public String toString() {
- return "if "+boolexp+" then "+exp1+" else "+exp2+" fi";
+ return "if " + boolexp + " then " + exp1 + " else " + exp2 + " fi";
}
public void checkcontext(SymTab st) {
@@ -38,11 +39,8 @@ public void prepInterp(SymTab st) {
}
public int interpret(int[] in, int[] par) {
- boolean b = boolexp.interpret(in,par);
- if (b)
- return exp1.interpret(in,par);
- else
- return exp2.interpret(in,par);
+ boolean b = boolexp.interpret(in, par);
+ if (b) return exp1.interpret(in, par);
+ else return exp2.interpret(in, par);
}
}
-
diff --git a/jflex/examples/interpreter/Tnumber.java b/jflex/examples/cup-interpreter/src/main/java/Tnumber.java
similarity index 73%
rename from jflex/examples/interpreter/Tnumber.java
rename to jflex/examples/cup-interpreter/src/main/java/Tnumber.java
index 149907130..83b467b70 100644
--- a/jflex/examples/interpreter/Tnumber.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Tnumber.java
@@ -7,30 +7,27 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/**
- * AST node for a number
- */
+/** AST node for a number */
class Tnumber extends Texp implements AST {
- int n; // value of the number
+ int n; // value of the number
public Tnumber(String s) {
- try { n = Integer.parseInt(s); }
- catch (NumberFormatException e) { n=-1; };
+ try {
+ n = Integer.parseInt(s);
+ } catch (NumberFormatException e) {
+ n = -1;
+ }
}
public String toString() {
- return(""+n);
+ return String.valueOf(n);
}
- public void checkcontext(SymTab st) {
- }
+ public void checkcontext(SymTab st) {}
- public void prepInterp(SymTab st) {
- }
+ public void prepInterp(SymTab st) {}
public int interpret(int[] in, int[] par) {
- return(n);
+ return n;
}
}
-
diff --git a/jflex/examples/interpreter/Tparlist.java b/jflex/examples/cup-interpreter/src/main/java/Tparlist.java
similarity index 59%
rename from jflex/examples/interpreter/Tparlist.java
rename to jflex/examples/cup-interpreter/src/main/java/Tparlist.java
index 5ab3aa23c..5658deb39 100644
--- a/jflex/examples/interpreter/Tparlist.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Tparlist.java
@@ -7,37 +7,32 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/**
- * AST node for a parameter list.
- */
+/** AST node for a parameter list. */
class Tparlist implements AST {
- Tparlist parlist; // rest of the liste (optional null)
- Tident ident; // identifier
+ /** Rest of the list (optional null) */
+ Tparlist parlist;
+ /** identifier */
+ Tident ident;
public Tparlist(Tparlist p, Tident i) {
- parlist=p;
- ident=i;
+ parlist = p;
+ ident = i;
}
public Tparlist(Tident i) {
- parlist=null;
- ident=i;
+ parlist = null;
+ ident = i;
}
public String toString() {
- if (parlist!=null)
- return parlist+","+ident;
- else
- return ident.toString();
+ if (parlist != null) return parlist + "," + ident;
+ else return ident.toString();
}
public void setSymtab(SymTab st, boolean isInput, int index) {
- boolean isNew = st.enter(ident.toString(),
- new STEvar(ident.toString(), isInput, index));
-
- if (!isNew) Main.error("Variable "+ident+" defined twice!");
- if (parlist!=null) parlist.setSymtab(st, isInput, index+1);
+ boolean isNew = st.enter(ident.toString(), new STEvar(ident.toString(), isInput, index));
+
+ if (!isNew) Main.error("Variable " + ident + " defined twice!");
+ if (parlist != null) parlist.setSymtab(st, isInput, index + 1);
}
}
-
diff --git a/jflex/examples/cup-interpreter/src/main/java/Tprogram.java b/jflex/examples/cup-interpreter/src/main/java/Tprogram.java
new file mode 100644
index 000000000..2c1e9f97a
--- /dev/null
+++ b/jflex/examples/cup-interpreter/src/main/java/Tprogram.java
@@ -0,0 +1,89 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright (C) 2001 Gerwin Klein *
+ * Copyright (C) 2001 Bernhard Rumpe *
+ * All rights reserved. *
+ * *
+ * License: BSD *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/**
+ * AST node for the whole program (top node).
+ *
+ *
Also contains two symbol tables, one for input variables, one for function names.
+ *
+ *
All operations like context check, symbol table build up etc. start here.
+ */
+class Tprogram implements AST {
+
+ Tparlist parlist; // input variables
+ Tdekllist dekllist; // function declarations
+ Texplist explist; // result expressions
+ Texplist arguments; // input values
+
+ public Tprogram(Tparlist p, Tdekllist d, Texplist e, Texplist a) {
+ parlist = p;
+ dekllist = d;
+ explist = e;
+ arguments = a;
+ }
+
+ public String toString() {
+ return ("Program:\n=============\ninput "
+ + parlist
+ + "\nfunctions\n"
+ + dekllist
+ + "\noutput "
+ + explist
+ + "\narguments "
+ + arguments
+ + "\nend");
+ }
+
+ SymTab inputs; // table of input variables
+ SymTab functions; // table of functions
+
+ public void setSymtabs() { // calculate symbol table entries
+ inputs = new SymTab(); // set input variables
+ parlist.setSymtab(inputs, true, 0);
+ functions = new SymTab(inputs);
+ dekllist.setSymtab(functions);
+ }
+
+ public void printSymtabs() {
+ System.out.print("Input variables-\n" + inputs);
+ System.out.print("Functions-\n" + functions);
+ dekllist.printSymtabs();
+ }
+
+ public void checkcontext() {
+ dekllist.checkcontext(); // CoCo (DefFun,DefVar,Arity)
+ // in function bodies
+ explist.checkcontext(functions); // CoCo (DefFun,DefVar,Arity)
+ // in result expressions
+ arguments.checkcontext(new SymTab()); // CoCo (constants)
+ // in arguments
+ if (arguments.length() != inputs.size())
+ Main.error("Argument list and input variables list differ!");
+ }
+
+ public void prepInterp() { // set pointers and indices
+ dekllist.prepInterp(functions);
+ explist.prepInterp(functions);
+ }
+
+ public void interpret() {
+ int[] inputEnv = new int[inputs.size()]; // set input
+
+ arguments.interpret(null, null, inputEnv, 0);
+
+ System.out.println("Result:\n=============");
+
+ int[] ergebnis = new int[explist.length()];
+ explist.interpret(inputEnv, null, ergebnis, 0); // calculate result
+
+ int i;
+ for (i = explist.length() - 1; i > 0; i--) System.out.print(ergebnis[i] + ", ");
+ System.out.println(ergebnis[i]);
+ }
+}
diff --git a/jflex/examples/interpreter/Tuminus.java b/jflex/examples/cup-interpreter/src/main/java/Tuminus.java
similarity index 74%
rename from jflex/examples/interpreter/Tuminus.java
rename to jflex/examples/cup-interpreter/src/main/java/Tuminus.java
index 3d2212cbc..9bc44dc8f 100644
--- a/jflex/examples/interpreter/Tuminus.java
+++ b/jflex/examples/cup-interpreter/src/main/java/Tuminus.java
@@ -7,32 +7,28 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/**
- * AST node for unary minus expressions.
- */
+/** AST node for unary minus expressions. */
class Tuminus extends Texp implements AST {
-
- Texp exp; // the negated expression
+ /** the negated expression */
+ Texp exp;
public Tuminus(Texp e) {
- exp=e;
+ exp = e;
}
public String toString() {
- return "-"+exp;
+ return "-" + exp;
}
public void checkcontext(SymTab st) {
- exp.checkcontext(st);
+ exp.checkcontext(st);
}
- public void prepInterp(SymTab st) {
- exp.prepInterp(st);
+ public void prepInterp(SymTab st) {
+ exp.prepInterp(st);
}
public int interpret(int[] in, int[] par) {
- return -(exp.interpret(in,par));
+ return -(exp.interpret(in, par));
}
}
-
diff --git a/jflex/examples/interpreter/scanner.flex b/jflex/examples/cup-interpreter/src/main/jflex/scanner.flex
similarity index 100%
rename from jflex/examples/interpreter/scanner.flex
rename to jflex/examples/cup-interpreter/src/main/jflex/scanner.flex
diff --git a/jflex/examples/interpreter/example.as b/jflex/examples/cup-interpreter/src/test/data/example.as
similarity index 100%
rename from jflex/examples/interpreter/example.as
rename to jflex/examples/cup-interpreter/src/test/data/example.as
diff --git a/jflex/examples/interpreter/output.good b/jflex/examples/cup-interpreter/src/test/data/output.good
similarity index 100%
rename from jflex/examples/interpreter/output.good
rename to jflex/examples/cup-interpreter/src/test/data/output.good
diff --git a/jflex/examples/cup-java/Makefile b/jflex/examples/cup-java/Makefile
new file mode 100644
index 000000000..124f532a5
--- /dev/null
+++ b/jflex/examples/cup-java/Makefile
@@ -0,0 +1,38 @@
+# You need CUP v0.10j (or newer) for this makefile to work (for java12.cup)
+#
+# CUP classes should be included in CLASSPATH
+
+ROOT = ../../..
+JFLEX = $(ROOT)/jflex/bin/jflex
+CUPJAR = $(ROOT)/cup/cup/java-cup-11b.jar
+CUP = java -jar $(CUPJAR)
+
+
+all: clean compile
+
+compile: gen_all src/main/java/*.java
+ javac -d out -cp $(CUPJAR) out/genfiles/*.java src/main/java/*.java
+
+test: out/lexer-output.txt
+ @(diff $< src/test/data/lexer-output.good && echo "Test OK") || (echo "Test FAILED"; exit 1)
+
+out/lexer-output.txt: compile outdir
+ java -cp out:$(CUPJAR) TestLexer src/main/java/TestLexer.java > out/lexer-output.txt
+
+gen_all: gen_parser gen_scanner gen_unicode
+
+gen_parser: src/main/cup/java12.cup outdir
+ $(CUP) -interface $<
+ mv parser.java sym.java out/genfiles
+
+gen_scanner: src/main/jflex/java.flex outdir
+ $(JFLEX) -d out/genfiles $<
+
+gen_unicode: src/main/jflex/unicode.flex outdir
+ $(JFLEX) -d out/genfiles $<
+
+clean:
+ rm -rf out
+
+outdir:
+ mkdir -p out/genfiles
diff --git a/jflex/examples/java/README.md b/jflex/examples/cup-java/README.md
similarity index 63%
rename from jflex/examples/java/README.md
rename to jflex/examples/cup-java/README.md
index aca25bbf3..c21e9bd40 100644
--- a/jflex/examples/java/README.md
+++ b/jflex/examples/cup-java/README.md
@@ -3,33 +3,42 @@ JFlex: Complex example (with CUP)
This directory contains a scanner and parser for the Java programming language (Java 1.2).
-## Prerequisite
+## Build, run, test
-You need the parser generator CUP v0.11a for the parser to work.
+### Using Maven
-## Build and run
+ ../../mvnw package
+
+To run the parser:
+
+ java -cp target/cup-java-1.0.jar:../../../cup/cup/java-cup-11b.jar JavaParser
+
+or more simply the uberjar version:
+
+ java -jar target/cup-java-full-1.0.jar
+
+
+### Using ant
+
+ ant compile
+ ant run
+ java -jar build:../../../cup/cup/java-cup-11b.jar JavaParser
+
+### Using make
Use the Makefile or Ant (via 'ant run') to generate the lexer and
parser, or type:
-```
-jflex unicode.flex
-jflex java.flex
-java java_cup.Main -interface < java12.cup
-javac JavaParser.java TestLexer.java
-```
+ make compile
+ make test
The parser can be tested with:
-```
-java JavaParser
-```
+ java -cp out:../../../cup/cup/java-cup-11b.jar JavaParser
The scanner (without parser attached) can be test with:
-```
-java TestLexer
-```
+ java -cp out:../../../cup/cup/java-cup-11b.jar TestLexer
## Files
diff --git a/jflex/examples/cup-java/build.xml b/jflex/examples/cup-java/build.xml
new file mode 100644
index 000000000..5d566d926
--- /dev/null
+++ b/jflex/examples/cup-java/build.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jflex/examples/cup-java/pom.xml b/jflex/examples/cup-java/pom.xml
new file mode 100644
index 000000000..3e37e6fa9
--- /dev/null
+++ b/jflex/examples/cup-java/pom.xml
@@ -0,0 +1,99 @@
+
+
+ 4.0.0
+ de.flex.examples
+ cup-java
+ 1.0
+ A parser for Java
+ An parser for the Java programming language.
+ This simple grammar can only parse Java up to version 1.2.
+ It uses JFlex and CUP.
+
+
+ de.jflex
+ cup_runtime
+ 11b
+
+
+ junit
+ junit
+ 3.8.2
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.6
+ 1.6
+
+
+
+ de.jflex
+ jflex-maven-plugin
+ 1.7.1-SNAPSHOT
+
+
+
+ generate
+
+
+
+
+
+
+
+ de.jflex
+ cup-maven-plugin
+ 1.0
+
+
+
+ generate
+
+
+ true
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+ ${project.artifactId}-full-${project.version}
+
+
+ JavaParser
+
+
+
+
+ de.jflex:cup_runtime
+
+
+
+
+
+
+
+
+
+ UTF-8
+
+
diff --git a/jflex/examples/java/java12.cup b/jflex/examples/cup-java/src/main/cup/java12.cup
similarity index 100%
rename from jflex/examples/java/java12.cup
rename to jflex/examples/cup-java/src/main/cup/java12.cup
diff --git a/jflex/examples/java/JavaParser.java b/jflex/examples/cup-java/src/main/java/JavaParser.java
similarity index 79%
rename from jflex/examples/java/JavaParser.java
rename to jflex/examples/cup-java/src/main/java/JavaParser.java
index 131b10463..4e26597e0 100644
--- a/jflex/examples/java/JavaParser.java
+++ b/jflex/examples/cup-java/src/main/java/JavaParser.java
@@ -8,10 +8,8 @@
import java.io.*;
-
/**
- * Simple test driver for the java parser. Just runs it on some
- * input files, gives no useful output.
+ * Simple test driver for the java parser. Just runs it on some input files, gives no useful output.
*/
public class JavaParser {
@@ -19,18 +17,16 @@ public static void main(String argv[]) {
for (int i = 0; i < argv.length; i++) {
try {
- System.out.println("Parsing ["+argv[i]+"]");
+ System.out.println("Parsing [" + argv[i] + "]");
Scanner s = new Scanner(new UnicodeEscapes(new FileReader(argv[i])));
parser p = new parser(s);
p.parse();
-
+
System.out.println("No errors.");
- }
- catch (Exception e) {
- e.printStackTrace(System.out);
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
System.exit(1);
}
}
}
-
}
diff --git a/jflex/examples/java/JavaSymbol.java b/jflex/examples/cup-java/src/main/java/JavaSymbol.java
similarity index 75%
rename from jflex/examples/java/JavaSymbol.java
rename to jflex/examples/cup-java/src/main/java/JavaSymbol.java
index d27b63dfe..af100fc33 100644
--- a/jflex/examples/java/JavaSymbol.java
+++ b/jflex/examples/cup-java/src/main/java/JavaSymbol.java
@@ -1,4 +1,3 @@
-
public class JavaSymbol extends java_cup.runtime.Symbol {
private int line;
private int column;
@@ -25,7 +24,13 @@ public int getColumn() {
return column;
}
- public String toString() {
- return "line "+line+", column "+column+", sym: "+sym+(value == null ? "" : (", value: '"+value+"'"));
+ public String toString() {
+ return "line "
+ + line
+ + ", column "
+ + column
+ + ", sym: "
+ + sym
+ + (value == null ? "" : (", value: '" + value + "'"));
}
}
diff --git a/jflex/examples/java/TestLexer.java b/jflex/examples/cup-java/src/main/java/TestLexer.java
similarity index 78%
rename from jflex/examples/java/TestLexer.java
rename to jflex/examples/cup-java/src/main/java/TestLexer.java
index ce98fc5b9..ab3cd4c18 100644
--- a/jflex/examples/java/TestLexer.java
+++ b/jflex/examples/cup-java/src/main/java/TestLexer.java
@@ -9,39 +9,37 @@
import java.io.*;
import java_cup.runtime.Symbol;
-
/**
- * Simple test driver for the java lexer. Just runs it on some
- * input files and produces debug output. Needs symbol class from
- * parser.
+ * Simple test driver for the java lexer. Just runs it on some input files and produces debug
+ * output. Needs symbol class from parser.
*/
public class TestLexer {
/** some numerals to for lexer testing */
int intDec = 37;
+
long longDec = 37l;
int intHex = 0x0001;
long longHex = 0xFFFFl;
int intOct = 0377;
long longOc = 007l;
- int smallest = -2147483648;
+ int smallest = -2147483648;
public static void main(String argv[]) {
for (int i = 0; i < argv.length; i++) {
try {
- System.out.println("Lexing ["+argv[i]+"]");
+ System.out.println("Lexing [" + argv[i] + "]");
Scanner scanner = new Scanner(new UnicodeEscapes(new FileReader(argv[i])));
-
+
Symbol s;
do {
s = scanner.debug_next_token();
- System.out.println("token: "+s);
+ System.out.println("token: " + s);
} while (s.sym != sym.EOF);
-
+
System.out.println("No errors.");
- }
- catch (Exception e) {
+ } catch (Exception e) {
e.printStackTrace(System.out);
System.exit(1);
}
diff --git a/jflex/examples/java/java.flex b/jflex/examples/cup-java/src/main/jflex/java.flex
similarity index 100%
rename from jflex/examples/java/java.flex
rename to jflex/examples/cup-java/src/main/jflex/java.flex
diff --git a/jflex/examples/java/unicode.flex b/jflex/examples/cup-java/src/main/jflex/unicode.flex
similarity index 100%
rename from jflex/examples/java/unicode.flex
rename to jflex/examples/cup-java/src/main/jflex/unicode.flex
diff --git a/jflex/examples/cup-java/src/test/data/lexer-output.good b/jflex/examples/cup-java/src/test/data/lexer-output.good
new file mode 100644
index 000000000..be0bf4d78
--- /dev/null
+++ b/jflex/examples/cup-java/src/test/data/lexer-output.good
@@ -0,0 +1,386 @@
+Lexing [src/main/java/TestLexer.java]
+line:9 col:1 --import--IMPORT--
+token: line 9, column 1, sym: 23
+line:9 col:8 --java--IDENTIFIER--
+token: line 9, column 8, sym: 98, value: 'java'
+line:9 col:12 --.--DOT--
+token: line 9, column 12, sym: 12
+line:9 col:13 --io--IDENTIFIER--
+token: line 9, column 13, sym: 98, value: 'io'
+line:9 col:15 --.--DOT--
+token: line 9, column 15, sym: 12
+line:9 col:16 --*--MULT--
+token: line 9, column 16, sym: 14
+line:9 col:17 --;--SEMICOLON--
+token: line 9, column 17, sym: 13
+line:10 col:1 --import--IMPORT--
+token: line 10, column 1, sym: 23
+line:10 col:8 --java_cup--IDENTIFIER--
+token: line 10, column 8, sym: 98, value: 'java_cup'
+line:10 col:16 --.--DOT--
+token: line 10, column 16, sym: 12
+line:10 col:17 --runtime--IDENTIFIER--
+token: line 10, column 17, sym: 98, value: 'runtime'
+line:10 col:24 --.--DOT--
+token: line 10, column 24, sym: 12
+line:10 col:25 --Symbol--IDENTIFIER--
+token: line 10, column 25, sym: 98, value: 'Symbol'
+line:10 col:31 --;--SEMICOLON--
+token: line 10, column 31, sym: 13
+line:16 col:1 --public--PUBLIC--
+token: line 16, column 1, sym: 24
+line:16 col:8 --class--CLASS--
+token: line 16, column 8, sym: 34
+line:16 col:14 --TestLexer--IDENTIFIER--
+token: line 16, column 14, sym: 98, value: 'TestLexer'
+line:16 col:24 --{--LBRACE--
+token: line 16, column 24, sym: 16
+line:19 col:3 --int--INT--
+token: line 19, column 3, sym: 5
+line:19 col:7 --intDec--IDENTIFIER--
+token: line 19, column 7, sym: 98, value: 'intDec'
+line:19 col:14 --=--EQ--
+token: line 19, column 14, sym: 18
+line:19 col:16 --37--INTEGER_LITERAL--
+token: line 19, column 16, sym: 93, value: '37'
+line:19 col:18 --;--SEMICOLON--
+token: line 19, column 18, sym: 13
+line:21 col:3 --long--LONG--
+token: line 21, column 3, sym: 6
+line:21 col:8 --longDec--IDENTIFIER--
+token: line 21, column 8, sym: 98, value: 'longDec'
+line:21 col:16 --=--EQ--
+token: line 21, column 16, sym: 18
+line:21 col:18 --37l--INTEGER_LITERAL--
+token: line 21, column 18, sym: 93, value: '37'
+line:21 col:21 --;--SEMICOLON--
+token: line 21, column 21, sym: 13
+line:22 col:3 --int--INT--
+token: line 22, column 3, sym: 5
+line:22 col:7 --intHex--IDENTIFIER--
+token: line 22, column 7, sym: 98, value: 'intHex'
+line:22 col:14 --=--EQ--
+token: line 22, column 14, sym: 18
+line:22 col:16 --0x0001--INTEGER_LITERAL--
+token: line 22, column 16, sym: 93, value: '1'
+line:22 col:22 --;--SEMICOLON--
+token: line 22, column 22, sym: 13
+line:23 col:3 --long--LONG--
+token: line 23, column 3, sym: 6
+line:23 col:8 --longHex--IDENTIFIER--
+token: line 23, column 8, sym: 98, value: 'longHex'
+line:23 col:16 --=--EQ--
+token: line 23, column 16, sym: 18
+line:23 col:18 --0xFFFFl--INTEGER_LITERAL--
+token: line 23, column 18, sym: 93, value: '65535'
+line:23 col:25 --;--SEMICOLON--
+token: line 23, column 25, sym: 13
+line:24 col:3 --int--INT--
+token: line 24, column 3, sym: 5
+line:24 col:7 --intOct--IDENTIFIER--
+token: line 24, column 7, sym: 98, value: 'intOct'
+line:24 col:14 --=--EQ--
+token: line 24, column 14, sym: 18
+line:24 col:16 --0377--INTEGER_LITERAL--
+token: line 24, column 16, sym: 93, value: '255'
+line:24 col:20 --;--SEMICOLON--
+token: line 24, column 20, sym: 13
+line:25 col:3 --long--LONG--
+token: line 25, column 3, sym: 6
+line:25 col:8 --longOc--IDENTIFIER--
+token: line 25, column 8, sym: 98, value: 'longOc'
+line:25 col:15 --=--EQ--
+token: line 25, column 15, sym: 18
+line:25 col:17 --007l--INTEGER_LITERAL--
+token: line 25, column 17, sym: 93, value: '7'
+line:25 col:21 --;--SEMICOLON--
+token: line 25, column 21, sym: 13
+line:26 col:3 --int--INT--
+token: line 26, column 3, sym: 5
+line:26 col:7 --smallest--IDENTIFIER--
+token: line 26, column 7, sym: 98, value: 'smallest'
+line:26 col:16 --=--EQ--
+token: line 26, column 16, sym: 18
+line:26 col:18 ---2147483648--INTEGER_LITERAL--
+token: line 26, column 18, sym: 93, value: '-2147483648'
+line:26 col:29 --;--SEMICOLON--
+token: line 26, column 29, sym: 13
+line:28 col:3 --public--PUBLIC--
+token: line 28, column 3, sym: 24
+line:28 col:10 --static--STATIC--
+token: line 28, column 10, sym: 27
+line:28 col:17 --void--VOID--
+token: line 28, column 17, sym: 37
+line:28 col:22 --main--IDENTIFIER--
+token: line 28, column 22, sym: 98, value: 'main'
+line:28 col:26 --(--LPAREN--
+token: line 28, column 26, sym: 19
+line:28 col:27 --String--IDENTIFIER--
+token: line 28, column 27, sym: 98, value: 'String'
+line:28 col:34 --argv--IDENTIFIER--
+token: line 28, column 34, sym: 98, value: 'argv'
+line:28 col:38 --[--LBRACK--
+token: line 28, column 38, sym: 10
+line:28 col:39 --]--RBRACK--
+token: line 28, column 39, sym: 11
+line:28 col:40 --)--RPAREN--
+token: line 28, column 40, sym: 20
+line:28 col:42 --{--LBRACE--
+token: line 28, column 42, sym: 16
+line:30 col:5 --for--FOR--
+token: line 30, column 5, sym: 49
+line:30 col:9 --(--LPAREN--
+token: line 30, column 9, sym: 19
+line:30 col:10 --int--INT--
+token: line 30, column 10, sym: 5
+line:30 col:14 --i--IDENTIFIER--
+token: line 30, column 14, sym: 98, value: 'i'
+line:30 col:16 --=--EQ--
+token: line 30, column 16, sym: 18
+line:30 col:18 --0--INTEGER_LITERAL--
+token: line 30, column 18, sym: 93, value: '0'
+line:30 col:19 --;--SEMICOLON--
+token: line 30, column 19, sym: 13
+line:30 col:21 --i--IDENTIFIER--
+token: line 30, column 21, sym: 98, value: 'i'
+line:30 col:23 --<--LT--
+token: line 30, column 23, sym: 69
+line:30 col:25 --argv--IDENTIFIER--
+token: line 30, column 25, sym: 98, value: 'argv'
+line:30 col:29 --.--DOT--
+token: line 30, column 29, sym: 12
+line:30 col:30 --length--IDENTIFIER--
+token: line 30, column 30, sym: 98, value: 'length'
+line:30 col:36 --;--SEMICOLON--
+token: line 30, column 36, sym: 13
+line:30 col:38 --i--IDENTIFIER--
+token: line 30, column 38, sym: 98, value: 'i'
+line:30 col:39 --++--PLUSPLUS--
+token: line 30, column 39, sym: 58
+line:30 col:41 --)--RPAREN--
+token: line 30, column 41, sym: 20
+line:30 col:43 --{--LBRACE--
+token: line 30, column 43, sym: 16
+line:31 col:7 --try--TRY--
+token: line 31, column 7, sym: 54
+line:31 col:11 --{--LBRACE--
+token: line 31, column 11, sym: 16
+line:32 col:9 --System--IDENTIFIER--
+token: line 32, column 9, sym: 98, value: 'System'
+line:32 col:15 --.--DOT--
+token: line 32, column 15, sym: 12
+line:32 col:16 --out--IDENTIFIER--
+token: line 32, column 16, sym: 98, value: 'out'
+line:32 col:19 --.--DOT--
+token: line 32, column 19, sym: 12
+line:32 col:20 --println--IDENTIFIER--
+token: line 32, column 20, sym: 98, value: 'println'
+line:32 col:27 --(--LPAREN--
+token: line 32, column 27, sym: 19
+line:32 col:37 --"--STRING_LITERAL--
+token: line 32, column 37, sym: 97, value: 'Lexing ['
+line:32 col:39 --+--PLUS--
+token: line 32, column 39, sym: 60
+line:32 col:41 --argv--IDENTIFIER--
+token: line 32, column 41, sym: 98, value: 'argv'
+line:32 col:45 --[--LBRACK--
+token: line 32, column 45, sym: 10
+line:32 col:46 --i--IDENTIFIER--
+token: line 32, column 46, sym: 98, value: 'i'
+line:32 col:47 --]--RBRACK--
+token: line 32, column 47, sym: 11
+line:32 col:49 --+--PLUS--
+token: line 32, column 49, sym: 60
+line:32 col:53 --"--STRING_LITERAL--
+token: line 32, column 53, sym: 97, value: ']'
+line:32 col:54 --)--RPAREN--
+token: line 32, column 54, sym: 20
+line:32 col:55 --;--SEMICOLON--
+token: line 32, column 55, sym: 13
+line:33 col:9 --Scanner--IDENTIFIER--
+token: line 33, column 9, sym: 98, value: 'Scanner'
+line:33 col:17 --scanner--IDENTIFIER--
+token: line 33, column 17, sym: 98, value: 'scanner'
+line:33 col:25 --=--EQ--
+token: line 33, column 25, sym: 18
+line:33 col:27 --new--NEW--
+token: line 33, column 27, sym: 57
+line:33 col:31 --Scanner--IDENTIFIER--
+token: line 33, column 31, sym: 98, value: 'Scanner'
+line:33 col:38 --(--LPAREN--
+token: line 33, column 38, sym: 19
+line:33 col:39 --new--NEW--
+token: line 33, column 39, sym: 57
+line:33 col:43 --UnicodeEscapes--IDENTIFIER--
+token: line 33, column 43, sym: 98, value: 'UnicodeEscapes'
+line:33 col:57 --(--LPAREN--
+token: line 33, column 57, sym: 19
+line:33 col:58 --new--NEW--
+token: line 33, column 58, sym: 57
+line:33 col:62 --FileReader--IDENTIFIER--
+token: line 33, column 62, sym: 98, value: 'FileReader'
+line:33 col:72 --(--LPAREN--
+token: line 33, column 72, sym: 19
+line:33 col:73 --argv--IDENTIFIER--
+token: line 33, column 73, sym: 98, value: 'argv'
+line:33 col:77 --[--LBRACK--
+token: line 33, column 77, sym: 10
+line:33 col:78 --i--IDENTIFIER--
+token: line 33, column 78, sym: 98, value: 'i'
+line:33 col:79 --]--RBRACK--
+token: line 33, column 79, sym: 11
+line:33 col:80 --)--RPAREN--
+token: line 33, column 80, sym: 20
+line:33 col:81 --)--RPAREN--
+token: line 33, column 81, sym: 20
+line:33 col:82 --)--RPAREN--
+token: line 33, column 82, sym: 20
+line:33 col:83 --;--SEMICOLON--
+token: line 33, column 83, sym: 13
+line:35 col:9 --Symbol--IDENTIFIER--
+token: line 35, column 9, sym: 98, value: 'Symbol'
+line:35 col:16 --s--IDENTIFIER--
+token: line 35, column 16, sym: 98, value: 's'
+line:35 col:17 --;--SEMICOLON--
+token: line 35, column 17, sym: 13
+line:36 col:9 --do--DO--
+token: line 36, column 9, sym: 47
+line:36 col:12 --{--LBRACE--
+token: line 36, column 12, sym: 16
+line:37 col:11 --s--IDENTIFIER--
+token: line 37, column 11, sym: 98, value: 's'
+line:37 col:13 --=--EQ--
+token: line 37, column 13, sym: 18
+line:37 col:15 --scanner--IDENTIFIER--
+token: line 37, column 15, sym: 98, value: 'scanner'
+line:37 col:22 --.--DOT--
+token: line 37, column 22, sym: 12
+line:37 col:23 --debug_next_token--IDENTIFIER--
+token: line 37, column 23, sym: 98, value: 'debug_next_token'
+line:37 col:39 --(--LPAREN--
+token: line 37, column 39, sym: 19
+line:37 col:40 --)--RPAREN--
+token: line 37, column 40, sym: 20
+line:37 col:41 --;--SEMICOLON--
+token: line 37, column 41, sym: 13
+line:38 col:11 --System--IDENTIFIER--
+token: line 38, column 11, sym: 98, value: 'System'
+line:38 col:17 --.--DOT--
+token: line 38, column 17, sym: 12
+line:38 col:18 --out--IDENTIFIER--
+token: line 38, column 18, sym: 98, value: 'out'
+line:38 col:21 --.--DOT--
+token: line 38, column 21, sym: 12
+line:38 col:22 --println--IDENTIFIER--
+token: line 38, column 22, sym: 98, value: 'println'
+line:38 col:29 --(--LPAREN--
+token: line 38, column 29, sym: 19
+line:38 col:38 --"--STRING_LITERAL--
+token: line 38, column 38, sym: 97, value: 'token: '
+line:38 col:40 --+--PLUS--
+token: line 38, column 40, sym: 60
+line:38 col:42 --s--IDENTIFIER--
+token: line 38, column 42, sym: 98, value: 's'
+line:38 col:43 --)--RPAREN--
+token: line 38, column 43, sym: 20
+line:38 col:44 --;--SEMICOLON--
+token: line 38, column 44, sym: 13
+line:39 col:9 --}--RBRACE--
+token: line 39, column 9, sym: 17
+line:39 col:11 --while--WHILE--
+token: line 39, column 11, sym: 48
+line:39 col:17 --(--LPAREN--
+token: line 39, column 17, sym: 19
+line:39 col:18 --s--IDENTIFIER--
+token: line 39, column 18, sym: 98, value: 's'
+line:39 col:19 --.--DOT--
+token: line 39, column 19, sym: 12
+line:39 col:20 --sym--IDENTIFIER--
+token: line 39, column 20, sym: 98, value: 'sym'
+line:39 col:24 --!=--NOTEQ--
+token: line 39, column 24, sym: 75
+line:39 col:27 --sym--IDENTIFIER--
+token: line 39, column 27, sym: 98, value: 'sym'
+line:39 col:30 --.--DOT--
+token: line 39, column 30, sym: 12
+line:39 col:31 --EOF--IDENTIFIER--
+token: line 39, column 31, sym: 98, value: 'EOF'
+line:39 col:34 --)--RPAREN--
+token: line 39, column 34, sym: 20
+line:39 col:35 --;--SEMICOLON--
+token: line 39, column 35, sym: 13
+line:41 col:9 --System--IDENTIFIER--
+token: line 41, column 9, sym: 98, value: 'System'
+line:41 col:15 --.--DOT--
+token: line 41, column 15, sym: 12
+line:41 col:16 --out--IDENTIFIER--
+token: line 41, column 16, sym: 98, value: 'out'
+line:41 col:19 --.--DOT--
+token: line 41, column 19, sym: 12
+line:41 col:20 --println--IDENTIFIER--
+token: line 41, column 20, sym: 98, value: 'println'
+line:41 col:27 --(--LPAREN--
+token: line 41, column 27, sym: 19
+line:41 col:39 --"--STRING_LITERAL--
+token: line 41, column 39, sym: 97, value: 'No errors.'
+line:41 col:40 --)--RPAREN--
+token: line 41, column 40, sym: 20
+line:41 col:41 --;--SEMICOLON--
+token: line 41, column 41, sym: 13
+line:42 col:7 --}--RBRACE--
+token: line 42, column 7, sym: 17
+line:42 col:9 --catch--CATCH--
+token: line 42, column 9, sym: 55
+line:42 col:15 --(--LPAREN--
+token: line 42, column 15, sym: 19
+line:42 col:16 --Exception--IDENTIFIER--
+token: line 42, column 16, sym: 98, value: 'Exception'
+line:42 col:26 --e--IDENTIFIER--
+token: line 42, column 26, sym: 98, value: 'e'
+line:42 col:27 --)--RPAREN--
+token: line 42, column 27, sym: 20
+line:42 col:29 --{--LBRACE--
+token: line 42, column 29, sym: 16
+line:43 col:9 --e--IDENTIFIER--
+token: line 43, column 9, sym: 98, value: 'e'
+line:43 col:10 --.--DOT--
+token: line 43, column 10, sym: 12
+line:43 col:11 --printStackTrace--IDENTIFIER--
+token: line 43, column 11, sym: 98, value: 'printStackTrace'
+line:43 col:26 --(--LPAREN--
+token: line 43, column 26, sym: 19
+line:43 col:27 --System--IDENTIFIER--
+token: line 43, column 27, sym: 98, value: 'System'
+line:43 col:33 --.--DOT--
+token: line 43, column 33, sym: 12
+line:43 col:34 --out--IDENTIFIER--
+token: line 43, column 34, sym: 98, value: 'out'
+line:43 col:37 --)--RPAREN--
+token: line 43, column 37, sym: 20
+line:43 col:38 --;--SEMICOLON--
+token: line 43, column 38, sym: 13
+line:44 col:9 --System--IDENTIFIER--
+token: line 44, column 9, sym: 98, value: 'System'
+line:44 col:15 --.--DOT--
+token: line 44, column 15, sym: 12
+line:44 col:16 --exit--IDENTIFIER--
+token: line 44, column 16, sym: 98, value: 'exit'
+line:44 col:20 --(--LPAREN--
+token: line 44, column 20, sym: 19
+line:44 col:21 --1--INTEGER_LITERAL--
+token: line 44, column 21, sym: 93, value: '1'
+line:44 col:22 --)--RPAREN--
+token: line 44, column 22, sym: 20
+line:44 col:23 --;--SEMICOLON--
+token: line 44, column 23, sym: 13
+line:45 col:7 --}--RBRACE--
+token: line 45, column 7, sym: 17
+line:46 col:5 --}--RBRACE--
+token: line 46, column 5, sym: 17
+line:47 col:3 --}--RBRACE--
+token: line 47, column 3, sym: 17
+line:48 col:1 --}--RBRACE--
+token: line 48, column 1, sym: 17
+line:49 col:1 ----EOF--
+token: line 49, column 1, sym: 0
+No errors.
diff --git a/jflex/examples/cup-maven/README.md b/jflex/examples/cup-lcalc/README.md
similarity index 90%
rename from jflex/examples/cup-maven/README.md
rename to jflex/examples/cup-lcalc/README.md
index 4fb9feeb5..16d5552ca 100644
--- a/jflex/examples/cup-maven/README.md
+++ b/jflex/examples/cup-lcalc/README.md
@@ -1,5 +1,4 @@
-JFlex with cup
-==============
+# JFlex with cup
This directory contains a small example of integration
between JFlex and [CUP][cup].
@@ -10,7 +9,9 @@ titled _Compiler Construction Tools_.
Small changes and updates to newest JFlex+Cup versions by Gerwin Klein.
-## Build and run
+## Build, run, test
+
+### Using Maven
To compile:
@@ -25,10 +26,10 @@ To run:
```
mvn package
-java -jar target/simple-maven-full-1.0.jar Main test.txt
+java -jar target/cup-lcalc-full-1.0.jar Main test.txt
```
-## Files:
+## Files
* `src/main/java/Main.java` demo of a main program
* `src/main/flex/lcalc.flex` the lexer spec
diff --git a/jflex/examples/cup-maven/pom.xml b/jflex/examples/cup-lcalc/pom.xml
similarity index 86%
rename from jflex/examples/cup-maven/pom.xml
rename to jflex/examples/cup-lcalc/pom.xml
index 975da5991..e7709d32c 100644
--- a/jflex/examples/cup-maven/pom.xml
+++ b/jflex/examples/cup-lcalc/pom.xml
@@ -18,6 +18,12 @@
3.8.2test
+
+ com.google.truth
+ truth
+ 0.36
+ test
+ de.jflexcup_runtime
@@ -26,6 +32,15 @@
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.6
+ 1.6
+
+ de.jflexjflex-maven-plugin
@@ -36,7 +51,6 @@
generate
- true
diff --git a/jflex/examples/cup-maven/src/main/cup/ycalc.cup b/jflex/examples/cup-lcalc/src/main/cup/ycalc.cup
similarity index 100%
rename from jflex/examples/cup-maven/src/main/cup/ycalc.cup
rename to jflex/examples/cup-lcalc/src/main/cup/ycalc.cup
diff --git a/jflex/examples/cup-maven/src/main/java/Main.java b/jflex/examples/cup-lcalc/src/main/java/Main.java
similarity index 52%
rename from jflex/examples/cup-maven/src/main/java/Main.java
rename to jflex/examples/cup-lcalc/src/main/java/Main.java
index a0529ae77..c3253c7b4 100644
--- a/jflex/examples/cup-maven/src/main/java/Main.java
+++ b/jflex/examples/cup-lcalc/src/main/java/Main.java
@@ -1,39 +1,35 @@
/*
- This example comes from a short article series in the Linux
+ This example comes from a short article series in the Linux
Gazette by Richard A. Sevenich and Christopher Lopes, titled
"Compiler Construction Tools". The article series starts at
http://www.linuxgazette.com/issue39/sevenich.html
- Small changes and updates to newest JFlex+Cup versions
+ Small changes and updates to newest JFlex+Cup versions
by Gerwin Klein
*/
/*
Commented By: Christopher Lopes
- File Name: Main.java
- To Create:
- After the scanner, lcalc.flex, and the parser, ycalc.cup, have been created.
- > javac Main.java
-
- To Run:
- > java Main test.txt
- where test.txt is an test input file for the calculator.
+
+
To Run:
+
+ java Main test.txt
+
+ where {@code test.txt} is an test input file for the calculator.
*/
-
+
import java.io.*;
-
+
public class Main {
- static public void main(String argv[]) {
+ public static void main(String argv[]) {
/* Start the parser */
try {
parser p = new parser(new Lexer(new FileReader(argv[0])));
- Object result = p.parse().value;
+ Object result = p.parse().value;
} catch (Exception e) {
/* do cleanup here -- possibly rethrow e */
e.printStackTrace();
}
}
}
-
-
diff --git a/jflex/examples/cup-maven/src/main/jflex/lcalc.flex b/jflex/examples/cup-lcalc/src/main/jflex/lcalc.flex
similarity index 100%
rename from jflex/examples/cup-maven/src/main/jflex/lcalc.flex
rename to jflex/examples/cup-lcalc/src/main/jflex/lcalc.flex
diff --git a/jflex/examples/cup-maven/src/test/java/LexerTest.java b/jflex/examples/cup-lcalc/src/test/java/LexerTest.java
similarity index 80%
rename from jflex/examples/cup-maven/src/test/java/LexerTest.java
rename to jflex/examples/cup-lcalc/src/test/java/LexerTest.java
index 51d27533c..c09d45082 100644
--- a/jflex/examples/cup-maven/src/test/java/LexerTest.java
+++ b/jflex/examples/cup-lcalc/src/test/java/LexerTest.java
@@ -1,10 +1,12 @@
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
-
import junit.framework.TestCase;
/**
@@ -16,9 +18,7 @@ public class LexerTest extends TestCase {
private static final String OUTPUT_FILE = "target/output.actual";
- /**
- * Tests that Lexer parses the calculator syntax correctly.
- */
+ /** Tests that Lexer parses the calculator syntax correctly. */
public void testOutput() throws Exception {
String[] argv = new String[1];
argv[0] = "src/test/resources/test.txt";
@@ -40,8 +40,8 @@ public void testOutput() throws Exception {
}
private void checkFileContent(File expected, File actual) throws IOException {
- assertTrue(expected.isFile());
- assertTrue(actual.isFile());
+ assertThat(expected.isFile()).isTrue();
+ assertThat(actual.isFile()).isTrue();
BufferedReader actualContent = new BufferedReader(new FileReader(actual));
BufferedReader expectedContent = new BufferedReader(new FileReader(expected));
@@ -49,7 +49,7 @@ private void checkFileContent(File expected, File actual) throws IOException {
for (int lineNumber = 1; lineNumber != -1; lineNumber++) {
String expectedLine = expectedContent.readLine();
String actualLine = actualContent.readLine();
- assertEquals("Line " + lineNumber, expectedLine, actualLine);
+ assertWithMessage("Line " + lineNumber).that(actualLine).isEqualTo(expectedLine);
if (expectedLine == null) {
lineNumber = -2; // EOF
}
diff --git a/jflex/examples/cup-maven/src/test/resources/output.good b/jflex/examples/cup-lcalc/src/test/resources/output.good
similarity index 100%
rename from jflex/examples/cup-maven/src/test/resources/output.good
rename to jflex/examples/cup-lcalc/src/test/resources/output.good
diff --git a/jflex/examples/cup-maven/src/test/resources/test.txt b/jflex/examples/cup-lcalc/src/test/resources/test.txt
similarity index 100%
rename from jflex/examples/cup-maven/src/test/resources/test.txt
rename to jflex/examples/cup-lcalc/src/test/resources/test.txt
diff --git a/jflex/examples/interpreter/Main.java b/jflex/examples/interpreter/Main.java
deleted file mode 100644
index dfb47be38..000000000
--- a/jflex/examples/interpreter/Main.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Copyright (C) 2001 Gerwin Klein *
- * Copyright (C) 2001 Bernhard Rumpe *
- * All rights reserved. *
- * *
- * License: BSD *
- * *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-
-import java.io.*;
-
-/**
- * Main program of the interpreter for the AS programming language.
- * Based on JFlex/CUP.
- *
- * Steps:
- * - scanning (Yylex)
- * - context free parsing and AST building (yyparse)
- * - build up symbol table (setSymtabs)
- * - check context conditions (checkcontext)
- * - prepare interpretation (prepInterp)
- * - start interpretation (interpret)
- */
-public class Main {
-
- public static void main(String [] args) throws Exception {
- Reader reader = null;
-
- if (args.length == 1) {
- File input = new File(args[0]);
- if (!input.canRead()) {
- System.out.println("Error: could not read ["+input+"]");
- }
- reader = new FileReader(input);
- }
- else {
- reader = new InputStreamReader(System.in);
- }
-
- Yylex scanner = new Yylex(reader); // create scanner
- SymTab symtab = new SymTab(); // set global symbol table
- scanner.setSymtab(symtab);
-
- parser parser = new parser(scanner); // create parser
- Tprogram syntaxbaum = null;
-
- try {
- syntaxbaum = (Tprogram) parser.parse().value; // parse
- }
- catch (Exception e) {
- e.printStackTrace();
- }
-
- // System.out.println(symtab);
- System.out.println(syntaxbaum);
-
- syntaxbaum.setSymtabs(); // set symbol table
- // syntaxbaum.printSymtabs(); // print symbol table
-
- syntaxbaum.checkcontext(); // CoCo (DefVar, DefFun, Arity)
- if(contexterror>0) return;
-
- syntaxbaum.prepInterp(); // var. indices and function pointers
- // im Syntaxbaum setzen
- syntaxbaum.interpret(); // interpretation
- }
-
- static int contexterror = 0; // number of errors in context conditions
-
- public static void error(String s) {
- System.out.println((contexterror++)+". "+s);
- }
-}
diff --git a/jflex/examples/interpreter/Makefile b/jflex/examples/interpreter/Makefile
deleted file mode 100644
index 5f0b3d880..000000000
--- a/jflex/examples/interpreter/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-# uses JFlex >= 1.3.2, and CUP >= 0.10j
-#
-# targets:
-#
-# make all
-# generates lexer, and parser, and compiles all *.java files
-#
-# make run (or just: make)
-# starts the program on a test example
-#
-
-JAVA=java
-JAVAC=javac
-# Root of the project
-ROOT=../../..
-JFLEX=$(ROOT)/jflex/bin/jflex
-CUPJAR=$(ROOT)/cup/cup/java-cup-11b.jar
-CUP=$(JAVA) -jar $(CUPJAR)
-CP=.:$(CUPJAR)
-
-default: test
-
-.SUFFIXES: $(SUFFIXES) .class .java
-
-.java.class:
- $(JAVAC) -cp $(CP) $*.java
-
-FILE= Yylex.java parser.java sym.java \
- SymTab.java AST.java \
- Tnumber.java Tident.java Texp.java \
- Tfun.java Texpinfix.java Tuminus.java \
- Tboolexp.java Tifthenelse.java \
- Tdekl.java Tdekllist.java \
- Tparlist.java Texplist.java Tprogram.java \
- Main.java \
- SymtabEntry.java STEfun.java STEvar.java
-
-run: output.txt
-
-output.txt: all
- $(JAVA) -cp $(CP) Main < example.as > output.txt
- cat output.txt
-
-all: Yylex.java parser.java $(FILE:java=class)
-
-clean:
- rm -f *.class *~ *.bak Yylex.java parser.java sym.java
-
-Yylex.java: scanner.flex
- $(JFLEX) scanner.flex
-
-parser.java: parser.cup
- $(CUP) -interface < parser.cup
-
-test: output.txt
- @(diff output.txt output.good && echo "Test OK!") || echo "Test failed!"
diff --git a/jflex/examples/interpreter/Tdekl.java b/jflex/examples/interpreter/Tdekl.java
deleted file mode 100644
index 60a474b84..000000000
--- a/jflex/examples/interpreter/Tdekl.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Copyright (C) 2001 Gerwin Klein *
- * Copyright (C) 2001 Bernhard Rumpe *
- * All rights reserved. *
- * *
- * License: BSD *
- * *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-
-/**
- * AST node for function declarations.
- *
- * Also contains a reference to the symbol table of
- * the parameters and their arity.
- */
-class Tdekl implements AST {
- Tident ident; // identifier
- Tparlist parlist; // liste of parameter
- Texp exp; // function body
-
- public Tdekl(Tident i, Tparlist p, Texp e) {
- parlist=p;
- ident=i;
- exp=e;
- }
-
- public String toString() {
- return(ident+"("+parlist+") = \n "+exp);
- }
-
- SymTab params; // symbol table of the parameters
- int arity;
-
- public void setSymtab(SymTab st) {
- params = new SymTab(st);
- parlist.setSymtab(params,false,0);
- arity = params.size();
-
- boolean isNew = st.enter(ident.toString(),
- new STEfun(ident.toString(),this,arity));
- // CoCo (Fun)
- if(!isNew) Main.error("funktion "+ident+" defined twice!");
- }
-
- public void printSymtabs() {
- System.out.print("funktion "+ident.toString()+"\n"+params);
- }
-
- public void checkcontext() {
- exp.checkcontext(params); // CoCo (DefFun,DefVar,Arity)
- }
-
- public void prepInterp(SymTab st) { // set pointers and indices
- exp.prepInterp(params);
- }
-
- public int interpret(int[] in, int[] par) {
- return(exp.interpret(in,par));
- }
-
- public int arity() { return(arity); }
-}
-
diff --git a/jflex/examples/interpreter/Tprogram.java b/jflex/examples/interpreter/Tprogram.java
deleted file mode 100644
index e663b1a77..000000000
--- a/jflex/examples/interpreter/Tprogram.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Copyright (C) 2001 Gerwin Klein *
- * Copyright (C) 2001 Bernhard Rumpe *
- * All rights reserved. *
- * *
- * License: BSD *
- * *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-
-/**
- * AST node for the whole program (top node).
- *
- * Also contains two symbol tables, one for input variables,
- * one for function names.
- *
- * All operations like context check, symbol table build up
- * etc. start here.
- */
-class Tprogram implements AST {
-
- Tparlist parlist; // input variables
- Tdekllist dekllist; // function declarations
- Texplist explist; // result expressions
- Texplist arguments; // input values
-
- public Tprogram(Tparlist p, Tdekllist d, Texplist e, Texplist a) {
- parlist=p;
- dekllist=d;
- explist=e;
- arguments=a;
- }
-
- public String toString() {
- return("Program:\n=============\ninput "+parlist+
- "\nfunctions\n"+dekllist+"\noutput "+explist+
- "\narguments "+arguments+"\nend");
- }
-
- SymTab inputs; // table of input variables
- SymTab functions; // table of functions
-
- public void setSymtabs() { // calculate symbol table entries
- inputs = new SymTab(); // set input variables
- parlist.setSymtab(inputs, true, 0);
- functions = new SymTab(inputs);
- dekllist.setSymtab(functions);
- }
-
- public void printSymtabs() {
- System.out.print("Input variables-\n"+inputs);
- System.out.print("Functions-\n"+functions);
- dekllist.printSymtabs();
- }
-
- public void checkcontext() {
- dekllist.checkcontext(); // CoCo (DefFun,DefVar,Arity)
- // in function bodies
- explist.checkcontext(functions); // CoCo (DefFun,DefVar,Arity)
- // in result expressions
- arguments.checkcontext(new SymTab()); // CoCo (constants)
- // in arguments
- if (arguments.length()!=inputs.size())
- Main.error("Argument list and input variables list differ!");
- }
-
- public void prepInterp() { // set pointers and indices
- dekllist.prepInterp(functions);
- explist.prepInterp(functions);
- }
-
- public void interpret() {
- int[] inputEnv = new int[inputs.size()]; // set input
-
- arguments.interpret(null,null,inputEnv,0);
-
- System.out.println("Result:\n=============");
-
- int[] ergebnis = new int[explist.length()];
- explist.interpret(inputEnv,null,ergebnis,0); // calculate result
-
- int i;
- for (i=explist.length()-1; i > 0; i--)
- System.out.print(ergebnis[i]+", ");
- System.out.println(ergebnis[i]);
- }
-}
-
diff --git a/jflex/examples/interpreter/build.xml b/jflex/examples/interpreter/build.xml
deleted file mode 100644
index e8e78dbf2..000000000
--- a/jflex/examples/interpreter/build.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/jflex/examples/java/Makefile b/jflex/examples/java/Makefile
deleted file mode 100644
index 40b27856b..000000000
--- a/jflex/examples/java/Makefile
+++ /dev/null
@@ -1,54 +0,0 @@
-# You need CUP v0.10j (or newer) for this makefile to work (for java12.cup)
-#
-# CUP classes should be included in CLASSPATH
-
-CUP = java java_cup.Main -interface <
-# Root of the project
-ROOT = ../../..
-JFLEX = $(ROOT)/jflex/bin/jflex
-CUPJAR = $(ROOT)/cup/cup/java-cup-11b.jar
-CP = .:$(CUPJAR)
-JAVA = java
-JAVAC = javac
-JAVACFLAGS = -cp $(CP)
-CUP = $(JAVA) -jar $(CUPJAR)
-
-
-
-# --------------------------------------------------
-
-all: test
-
-test: lexer-output.txt
- @(diff lexer-output.txt lexer-output.good && echo "Test OK!") || echo "Test failed!"
-
-lexer-output.txt: compile
- $(JAVA) -cp $(CP) TestLexer TestLexer.java > lexer-output.txt
-
-
-compile: scanner parser unicode
- $(JAVAC) $(JAVACFLAGS) JavaParser.java TestLexer.java
-
-parser: parser.java
-
-parser.java: java12.cup
- $(CUP) -interface java12.cup
-
-scanner: Scanner.java
-
-Scanner.java: java.flex
- $(JFLEX) java.flex
-
-unicode: UnicodeEscapes.java
-
-UnicodeEscapes.java: unicode.flex
- $(JFLEX) unicode.flex
-
-clean:
- rm -f *.class
- rm -f *~
- rm -f Scanner.java
- rm -f parser.java
- rm -f sym.java
- rm -f UnicodeEscapes.java
- rm -f lexer-output.txt
diff --git a/jflex/examples/java/build.xml b/jflex/examples/java/build.xml
deleted file mode 100644
index 96ba39aad..000000000
--- a/jflex/examples/java/build.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/jflex/examples/java/lexer-output.good b/jflex/examples/java/lexer-output.good
deleted file mode 100644
index 7a70ebc34..000000000
--- a/jflex/examples/java/lexer-output.good
+++ /dev/null
@@ -1,386 +0,0 @@
-Lexing [TestLexer.java]
-line:9 col:1 --import--IMPORT--
-token: line 9, column 1, sym: 23
-line:9 col:8 --java--IDENTIFIER--
-token: line 9, column 8, sym: 98, value: 'java'
-line:9 col:12 --.--DOT--
-token: line 9, column 12, sym: 12
-line:9 col:13 --io--IDENTIFIER--
-token: line 9, column 13, sym: 98, value: 'io'
-line:9 col:15 --.--DOT--
-token: line 9, column 15, sym: 12
-line:9 col:16 --*--MULT--
-token: line 9, column 16, sym: 14
-line:9 col:17 --;--SEMICOLON--
-token: line 9, column 17, sym: 13
-line:10 col:1 --import--IMPORT--
-token: line 10, column 1, sym: 23
-line:10 col:8 --java_cup--IDENTIFIER--
-token: line 10, column 8, sym: 98, value: 'java_cup'
-line:10 col:16 --.--DOT--
-token: line 10, column 16, sym: 12
-line:10 col:17 --runtime--IDENTIFIER--
-token: line 10, column 17, sym: 98, value: 'runtime'
-line:10 col:24 --.--DOT--
-token: line 10, column 24, sym: 12
-line:10 col:25 --Symbol--IDENTIFIER--
-token: line 10, column 25, sym: 98, value: 'Symbol'
-line:10 col:31 --;--SEMICOLON--
-token: line 10, column 31, sym: 13
-line:18 col:1 --public--PUBLIC--
-token: line 18, column 1, sym: 24
-line:18 col:8 --class--CLASS--
-token: line 18, column 8, sym: 34
-line:18 col:14 --TestLexer--IDENTIFIER--
-token: line 18, column 14, sym: 98, value: 'TestLexer'
-line:18 col:24 --{--LBRACE--
-token: line 18, column 24, sym: 16
-line:21 col:3 --int--INT--
-token: line 21, column 3, sym: 5
-line:21 col:7 --intDec--IDENTIFIER--
-token: line 21, column 7, sym: 98, value: 'intDec'
-line:21 col:14 --=--EQ--
-token: line 21, column 14, sym: 18
-line:21 col:16 --37--INTEGER_LITERAL--
-token: line 21, column 16, sym: 93, value: '37'
-line:21 col:18 --;--SEMICOLON--
-token: line 21, column 18, sym: 13
-line:22 col:3 --long--LONG--
-token: line 22, column 3, sym: 6
-line:22 col:8 --longDec--IDENTIFIER--
-token: line 22, column 8, sym: 98, value: 'longDec'
-line:22 col:16 --=--EQ--
-token: line 22, column 16, sym: 18
-line:22 col:18 --37l--INTEGER_LITERAL--
-token: line 22, column 18, sym: 93, value: '37'
-line:22 col:21 --;--SEMICOLON--
-token: line 22, column 21, sym: 13
-line:23 col:3 --int--INT--
-token: line 23, column 3, sym: 5
-line:23 col:7 --intHex--IDENTIFIER--
-token: line 23, column 7, sym: 98, value: 'intHex'
-line:23 col:14 --=--EQ--
-token: line 23, column 14, sym: 18
-line:23 col:16 --0x0001--INTEGER_LITERAL--
-token: line 23, column 16, sym: 93, value: '1'
-line:23 col:22 --;--SEMICOLON--
-token: line 23, column 22, sym: 13
-line:24 col:3 --long--LONG--
-token: line 24, column 3, sym: 6
-line:24 col:8 --longHex--IDENTIFIER--
-token: line 24, column 8, sym: 98, value: 'longHex'
-line:24 col:16 --=--EQ--
-token: line 24, column 16, sym: 18
-line:24 col:18 --0xFFFFl--INTEGER_LITERAL--
-token: line 24, column 18, sym: 93, value: '65535'
-line:24 col:25 --;--SEMICOLON--
-token: line 24, column 25, sym: 13
-line:25 col:3 --int--INT--
-token: line 25, column 3, sym: 5
-line:25 col:7 --intOct--IDENTIFIER--
-token: line 25, column 7, sym: 98, value: 'intOct'
-line:25 col:14 --=--EQ--
-token: line 25, column 14, sym: 18
-line:25 col:16 --0377--INTEGER_LITERAL--
-token: line 25, column 16, sym: 93, value: '255'
-line:25 col:20 --;--SEMICOLON--
-token: line 25, column 20, sym: 13
-line:26 col:3 --long--LONG--
-token: line 26, column 3, sym: 6
-line:26 col:8 --longOc--IDENTIFIER--
-token: line 26, column 8, sym: 98, value: 'longOc'
-line:26 col:15 --=--EQ--
-token: line 26, column 15, sym: 18
-line:26 col:17 --007l--INTEGER_LITERAL--
-token: line 26, column 17, sym: 93, value: '7'
-line:26 col:21 --;--SEMICOLON--
-token: line 26, column 21, sym: 13
-line:27 col:3 --int--INT--
-token: line 27, column 3, sym: 5
-line:27 col:7 --smallest--IDENTIFIER--
-token: line 27, column 7, sym: 98, value: 'smallest'
-line:27 col:16 --=--EQ--
-token: line 27, column 16, sym: 18
-line:27 col:18 ---2147483648--INTEGER_LITERAL--
-token: line 27, column 18, sym: 93, value: '-2147483648'
-line:27 col:29 --;--SEMICOLON--
-token: line 27, column 29, sym: 13
-line:29 col:3 --public--PUBLIC--
-token: line 29, column 3, sym: 24
-line:29 col:10 --static--STATIC--
-token: line 29, column 10, sym: 27
-line:29 col:17 --void--VOID--
-token: line 29, column 17, sym: 37
-line:29 col:22 --main--IDENTIFIER--
-token: line 29, column 22, sym: 98, value: 'main'
-line:29 col:26 --(--LPAREN--
-token: line 29, column 26, sym: 19
-line:29 col:27 --String--IDENTIFIER--
-token: line 29, column 27, sym: 98, value: 'String'
-line:29 col:34 --argv--IDENTIFIER--
-token: line 29, column 34, sym: 98, value: 'argv'
-line:29 col:38 --[--LBRACK--
-token: line 29, column 38, sym: 10
-line:29 col:39 --]--RBRACK--
-token: line 29, column 39, sym: 11
-line:29 col:40 --)--RPAREN--
-token: line 29, column 40, sym: 20
-line:29 col:42 --{--LBRACE--
-token: line 29, column 42, sym: 16
-line:31 col:5 --for--FOR--
-token: line 31, column 5, sym: 49
-line:31 col:9 --(--LPAREN--
-token: line 31, column 9, sym: 19
-line:31 col:10 --int--INT--
-token: line 31, column 10, sym: 5
-line:31 col:14 --i--IDENTIFIER--
-token: line 31, column 14, sym: 98, value: 'i'
-line:31 col:16 --=--EQ--
-token: line 31, column 16, sym: 18
-line:31 col:18 --0--INTEGER_LITERAL--
-token: line 31, column 18, sym: 93, value: '0'
-line:31 col:19 --;--SEMICOLON--
-token: line 31, column 19, sym: 13
-line:31 col:21 --i--IDENTIFIER--
-token: line 31, column 21, sym: 98, value: 'i'
-line:31 col:23 --<--LT--
-token: line 31, column 23, sym: 69
-line:31 col:25 --argv--IDENTIFIER--
-token: line 31, column 25, sym: 98, value: 'argv'
-line:31 col:29 --.--DOT--
-token: line 31, column 29, sym: 12
-line:31 col:30 --length--IDENTIFIER--
-token: line 31, column 30, sym: 98, value: 'length'
-line:31 col:36 --;--SEMICOLON--
-token: line 31, column 36, sym: 13
-line:31 col:38 --i--IDENTIFIER--
-token: line 31, column 38, sym: 98, value: 'i'
-line:31 col:39 --++--PLUSPLUS--
-token: line 31, column 39, sym: 58
-line:31 col:41 --)--RPAREN--
-token: line 31, column 41, sym: 20
-line:31 col:43 --{--LBRACE--
-token: line 31, column 43, sym: 16
-line:32 col:7 --try--TRY--
-token: line 32, column 7, sym: 54
-line:32 col:11 --{--LBRACE--
-token: line 32, column 11, sym: 16
-line:33 col:9 --System--IDENTIFIER--
-token: line 33, column 9, sym: 98, value: 'System'
-line:33 col:15 --.--DOT--
-token: line 33, column 15, sym: 12
-line:33 col:16 --out--IDENTIFIER--
-token: line 33, column 16, sym: 98, value: 'out'
-line:33 col:19 --.--DOT--
-token: line 33, column 19, sym: 12
-line:33 col:20 --println--IDENTIFIER--
-token: line 33, column 20, sym: 98, value: 'println'
-line:33 col:27 --(--LPAREN--
-token: line 33, column 27, sym: 19
-line:33 col:37 --"--STRING_LITERAL--
-token: line 33, column 37, sym: 97, value: 'Lexing ['
-line:33 col:38 --+--PLUS--
-token: line 33, column 38, sym: 60
-line:33 col:39 --argv--IDENTIFIER--
-token: line 33, column 39, sym: 98, value: 'argv'
-line:33 col:43 --[--LBRACK--
-token: line 33, column 43, sym: 10
-line:33 col:44 --i--IDENTIFIER--
-token: line 33, column 44, sym: 98, value: 'i'
-line:33 col:45 --]--RBRACK--
-token: line 33, column 45, sym: 11
-line:33 col:46 --+--PLUS--
-token: line 33, column 46, sym: 60
-line:33 col:49 --"--STRING_LITERAL--
-token: line 33, column 49, sym: 97, value: ']'
-line:33 col:50 --)--RPAREN--
-token: line 33, column 50, sym: 20
-line:33 col:51 --;--SEMICOLON--
-token: line 33, column 51, sym: 13
-line:34 col:9 --Scanner--IDENTIFIER--
-token: line 34, column 9, sym: 98, value: 'Scanner'
-line:34 col:17 --scanner--IDENTIFIER--
-token: line 34, column 17, sym: 98, value: 'scanner'
-line:34 col:25 --=--EQ--
-token: line 34, column 25, sym: 18
-line:34 col:27 --new--NEW--
-token: line 34, column 27, sym: 57
-line:34 col:31 --Scanner--IDENTIFIER--
-token: line 34, column 31, sym: 98, value: 'Scanner'
-line:34 col:38 --(--LPAREN--
-token: line 34, column 38, sym: 19
-line:34 col:39 --new--NEW--
-token: line 34, column 39, sym: 57
-line:34 col:43 --UnicodeEscapes--IDENTIFIER--
-token: line 34, column 43, sym: 98, value: 'UnicodeEscapes'
-line:34 col:57 --(--LPAREN--
-token: line 34, column 57, sym: 19
-line:34 col:58 --new--NEW--
-token: line 34, column 58, sym: 57
-line:34 col:62 --FileReader--IDENTIFIER--
-token: line 34, column 62, sym: 98, value: 'FileReader'
-line:34 col:72 --(--LPAREN--
-token: line 34, column 72, sym: 19
-line:34 col:73 --argv--IDENTIFIER--
-token: line 34, column 73, sym: 98, value: 'argv'
-line:34 col:77 --[--LBRACK--
-token: line 34, column 77, sym: 10
-line:34 col:78 --i--IDENTIFIER--
-token: line 34, column 78, sym: 98, value: 'i'
-line:34 col:79 --]--RBRACK--
-token: line 34, column 79, sym: 11
-line:34 col:80 --)--RPAREN--
-token: line 34, column 80, sym: 20
-line:34 col:81 --)--RPAREN--
-token: line 34, column 81, sym: 20
-line:34 col:82 --)--RPAREN--
-token: line 34, column 82, sym: 20
-line:34 col:83 --;--SEMICOLON--
-token: line 34, column 83, sym: 13
-line:36 col:9 --Symbol--IDENTIFIER--
-token: line 36, column 9, sym: 98, value: 'Symbol'
-line:36 col:16 --s--IDENTIFIER--
-token: line 36, column 16, sym: 98, value: 's'
-line:36 col:17 --;--SEMICOLON--
-token: line 36, column 17, sym: 13
-line:37 col:9 --do--DO--
-token: line 37, column 9, sym: 47
-line:37 col:12 --{--LBRACE--
-token: line 37, column 12, sym: 16
-line:38 col:11 --s--IDENTIFIER--
-token: line 38, column 11, sym: 98, value: 's'
-line:38 col:13 --=--EQ--
-token: line 38, column 13, sym: 18
-line:38 col:15 --scanner--IDENTIFIER--
-token: line 38, column 15, sym: 98, value: 'scanner'
-line:38 col:22 --.--DOT--
-token: line 38, column 22, sym: 12
-line:38 col:23 --debug_next_token--IDENTIFIER--
-token: line 38, column 23, sym: 98, value: 'debug_next_token'
-line:38 col:39 --(--LPAREN--
-token: line 38, column 39, sym: 19
-line:38 col:40 --)--RPAREN--
-token: line 38, column 40, sym: 20
-line:38 col:41 --;--SEMICOLON--
-token: line 38, column 41, sym: 13
-line:39 col:11 --System--IDENTIFIER--
-token: line 39, column 11, sym: 98, value: 'System'
-line:39 col:17 --.--DOT--
-token: line 39, column 17, sym: 12
-line:39 col:18 --out--IDENTIFIER--
-token: line 39, column 18, sym: 98, value: 'out'
-line:39 col:21 --.--DOT--
-token: line 39, column 21, sym: 12
-line:39 col:22 --println--IDENTIFIER--
-token: line 39, column 22, sym: 98, value: 'println'
-line:39 col:29 --(--LPAREN--
-token: line 39, column 29, sym: 19
-line:39 col:38 --"--STRING_LITERAL--
-token: line 39, column 38, sym: 97, value: 'token: '
-line:39 col:39 --+--PLUS--
-token: line 39, column 39, sym: 60
-line:39 col:40 --s--IDENTIFIER--
-token: line 39, column 40, sym: 98, value: 's'
-line:39 col:41 --)--RPAREN--
-token: line 39, column 41, sym: 20
-line:39 col:42 --;--SEMICOLON--
-token: line 39, column 42, sym: 13
-line:40 col:9 --}--RBRACE--
-token: line 40, column 9, sym: 17
-line:40 col:11 --while--WHILE--
-token: line 40, column 11, sym: 48
-line:40 col:17 --(--LPAREN--
-token: line 40, column 17, sym: 19
-line:40 col:18 --s--IDENTIFIER--
-token: line 40, column 18, sym: 98, value: 's'
-line:40 col:19 --.--DOT--
-token: line 40, column 19, sym: 12
-line:40 col:20 --sym--IDENTIFIER--
-token: line 40, column 20, sym: 98, value: 'sym'
-line:40 col:24 --!=--NOTEQ--
-token: line 40, column 24, sym: 75
-line:40 col:27 --sym--IDENTIFIER--
-token: line 40, column 27, sym: 98, value: 'sym'
-line:40 col:30 --.--DOT--
-token: line 40, column 30, sym: 12
-line:40 col:31 --EOF--IDENTIFIER--
-token: line 40, column 31, sym: 98, value: 'EOF'
-line:40 col:34 --)--RPAREN--
-token: line 40, column 34, sym: 20
-line:40 col:35 --;--SEMICOLON--
-token: line 40, column 35, sym: 13
-line:42 col:9 --System--IDENTIFIER--
-token: line 42, column 9, sym: 98, value: 'System'
-line:42 col:15 --.--DOT--
-token: line 42, column 15, sym: 12
-line:42 col:16 --out--IDENTIFIER--
-token: line 42, column 16, sym: 98, value: 'out'
-line:42 col:19 --.--DOT--
-token: line 42, column 19, sym: 12
-line:42 col:20 --println--IDENTIFIER--
-token: line 42, column 20, sym: 98, value: 'println'
-line:42 col:27 --(--LPAREN--
-token: line 42, column 27, sym: 19
-line:42 col:39 --"--STRING_LITERAL--
-token: line 42, column 39, sym: 97, value: 'No errors.'
-line:42 col:40 --)--RPAREN--
-token: line 42, column 40, sym: 20
-line:42 col:41 --;--SEMICOLON--
-token: line 42, column 41, sym: 13
-line:43 col:7 --}--RBRACE--
-token: line 43, column 7, sym: 17
-line:44 col:7 --catch--CATCH--
-token: line 44, column 7, sym: 55
-line:44 col:13 --(--LPAREN--
-token: line 44, column 13, sym: 19
-line:44 col:14 --Exception--IDENTIFIER--
-token: line 44, column 14, sym: 98, value: 'Exception'
-line:44 col:24 --e--IDENTIFIER--
-token: line 44, column 24, sym: 98, value: 'e'
-line:44 col:25 --)--RPAREN--
-token: line 44, column 25, sym: 20
-line:44 col:27 --{--LBRACE--
-token: line 44, column 27, sym: 16
-line:45 col:9 --e--IDENTIFIER--
-token: line 45, column 9, sym: 98, value: 'e'
-line:45 col:10 --.--DOT--
-token: line 45, column 10, sym: 12
-line:45 col:11 --printStackTrace--IDENTIFIER--
-token: line 45, column 11, sym: 98, value: 'printStackTrace'
-line:45 col:26 --(--LPAREN--
-token: line 45, column 26, sym: 19
-line:45 col:27 --System--IDENTIFIER--
-token: line 45, column 27, sym: 98, value: 'System'
-line:45 col:33 --.--DOT--
-token: line 45, column 33, sym: 12
-line:45 col:34 --out--IDENTIFIER--
-token: line 45, column 34, sym: 98, value: 'out'
-line:45 col:37 --)--RPAREN--
-token: line 45, column 37, sym: 20
-line:45 col:38 --;--SEMICOLON--
-token: line 45, column 38, sym: 13
-line:46 col:9 --System--IDENTIFIER--
-token: line 46, column 9, sym: 98, value: 'System'
-line:46 col:15 --.--DOT--
-token: line 46, column 15, sym: 12
-line:46 col:16 --exit--IDENTIFIER--
-token: line 46, column 16, sym: 98, value: 'exit'
-line:46 col:20 --(--LPAREN--
-token: line 46, column 20, sym: 19
-line:46 col:21 --1--INTEGER_LITERAL--
-token: line 46, column 21, sym: 93, value: '1'
-line:46 col:22 --)--RPAREN--
-token: line 46, column 22, sym: 20
-line:46 col:23 --;--SEMICOLON--
-token: line 46, column 23, sym: 13
-line:47 col:7 --}--RBRACE--
-token: line 47, column 7, sym: 17
-line:48 col:5 --}--RBRACE--
-token: line 48, column 5, sym: 17
-line:49 col:3 --}--RBRACE--
-token: line 49, column 3, sym: 17
-line:50 col:1 --}--RBRACE--
-token: line 50, column 1, sym: 17
-line:51 col:1 ----EOF--
-token: line 51, column 1, sym: 0
-No errors.
diff --git a/jflex/examples/pom.xml b/jflex/examples/pom.xml
index 554dc0ebd..626d620b6 100644
--- a/jflex/examples/pom.xml
+++ b/jflex/examples/pom.xml
@@ -1,16 +1,21 @@
-
- 4.0.0
- de.flex.examples
- pom
- 1
-
- Examples on how to use JFlex and jflex-maven-plugin
-
- pom
-
- cup-maven
- simple-maven
- standalone-maven
-
+
+ 4.0.0
+ de.flex.examples
+ pom
+ 1
+
+ Examples on how to use JFlex and jflex-maven-plugin
+
+ pom
+
+ cup-interpreter
+ cup-java
+ cup-lcalc
+ simple
+ standalone
+ zero-reader
+
diff --git a/jflex/examples/simple-maven/README.md b/jflex/examples/simple-maven/README.md
deleted file mode 100644
index 4b1823bcc..000000000
--- a/jflex/examples/simple-maven/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-Simple usage of the jflex-maven-plugin
-======================================
-
-This is a small Maven project that demonstrates the use of `jflex-maven-plugin`.
-
-## Files
-
-* `main/flex/simple.flex`:
- the example specification
-* `test/resources/test.txt`:
- sample input
-* `test/resources/output.good`:
- expected output matching the sample input from `test.txt`
diff --git a/jflex/examples/simple-maven/src/main/java/Utility.java b/jflex/examples/simple-maven/src/main/java/Utility.java
deleted file mode 100644
index e6e495543..000000000
--- a/jflex/examples/simple-maven/src/main/java/Utility.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * A small utility class.
- * TODO: use resource bundle
- */
-class Utility {
-
- private static final String errorMsg[] = {
- "Error: Unmatched end-of-comment punctuation.",
- "Error: Unmatched start-of-comment punctuation.",
- "Error: Unclosed string.",
- "Error: Illegal character."
- };
-
- public static final int E_ENDCOMMENT = 0;
- public static final int E_STARTCOMMENT = 1;
- public static final int E_UNCLOSEDSTR = 2;
- public static final int E_UNMATCHED = 3;
-
- public static void error(int code) {
- System.err.println(errorMsg[code]);
- }
-}
-
diff --git a/jflex/examples/simple-maven/src/main/java/Yytoken.java b/jflex/examples/simple-maven/src/main/java/Yytoken.java
deleted file mode 100644
index 64ea3707f..000000000
--- a/jflex/examples/simple-maven/src/main/java/Yytoken.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * The tokens returned by the scanner.
- *
- */
-class Yytoken {
- public int m_index;
- public String m_text;
- public int m_line;
- public int m_charBegin;
- public int m_charEnd;
-
- Yytoken (int index, String text, int line, int charBegin, int charEnd) {
- m_index = index;
- m_text = text;
- m_line = line;
- m_charBegin = charBegin;
- m_charEnd = charEnd;
- }
-
- public String toString() {
- return "Text : "+m_text+
- "\nindex : "+m_index+
- "\nline : "+m_line+
- "\ncBeg. : "+m_charBegin+
- "\ncEnd. : "+m_charEnd;
- }
-}
-
diff --git a/jflex/examples/simple-maven/src/site/apt/usage.apt b/jflex/examples/simple-maven/src/site/apt/usage.apt
deleted file mode 100644
index 9f933295e..000000000
--- a/jflex/examples/simple-maven/src/site/apt/usage.apt
+++ /dev/null
@@ -1,100 +0,0 @@
- ------
- Usage
- ------
- Gerwin Klein
- Régis Décamps
- ------
- November 2, 2007
- ------
-
-
-About this project
-
- This sample project parses a grammar with JFlex.
-
- The project management is done with Maven.
-
- The project contains a simple grammar for the "Toy programming language".
- It is the example from the JLex web site with some small
- modifications, to make it a bit more readable.
- It does nothing really useful, because there is no parser for
- the toy programming language. It's just a demonstration how a
- small simple scanner looks like.
-
-
-* JFlex
-
- JFlex is a parser generator. Given a grammar, JFlex generate
- Java (TM) code to parse documents that follow this grammar.
-
-* Maven
-
- Maven is a project management framework.
- The project is described in as a POM (project object model,
- stored into <<>>).
- This document isn't intended to be a tutorial on the use of Maven 3,
- you should consult the {{{http://maven.apache.org/}Maven web site}}.
-
- The integration of JFlex and Maven is done with
- {{{http://jflex.sourceforge.net/jflex-maven-plugin/}jflex-maven-plugin}}.
-
-
-Usage
-
-* mvn generate-sources
-
- The jflex-maven-plugin will read the grammar
- <<>>
- and generate a Java scanner <<>>
- in <<>>
-
- This is defined by the following section
-
-+---------
-
-
-
- de.jflex
- jflex-maven-plugin
- 1.7.0
-
-
-
- generate
-
-
-
-
-
-
-+------------
-
- By default, the jflex-maven-plugin generates a scanner/parser for every file
- in <<>>.
-
-
-* mvn test
-
- This goal test the generated scanner (if required, the lexer will be
- generated and all Java classes will be compiled)
- by running all tests in <<>>.
-
- There is only one test in <<>>.
- In this test,
- the scanner is run with the input file <<>>.
-
- By default, the scanner outputs debugging information about each
- returned token to <<>> until the end of file is reached,
- or an error occurs.
- But in the test, the output is redirected into <<>>.
-
- The test is successful if every line match
- with <<>>,
- which is the expected scanner debugging information.
-
-
-References
-
- * {{{http://jflex.sourceforge.net/maven-flex-plugin/}maven-flex-plugin}}
-
- * {{{http://maven.apache.org/}Maven web site}}.
diff --git a/jflex/examples/simple-maven/src/site/site.xml b/jflex/examples/simple-maven/src/site/site.xml
deleted file mode 100644
index 78b4fbe53..000000000
--- a/jflex/examples/simple-maven/src/site/site.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/jflex/examples/simple-maven/src/test/java/YylexTest.java b/jflex/examples/simple-maven/src/test/java/YylexTest.java
deleted file mode 100644
index 635697874..000000000
--- a/jflex/examples/simple-maven/src/test/java/YylexTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.PrintStream;
-
-import junit.framework.TestCase;
-
-/**
- * This is an integration test.
- *
- * The class Yylex is generated by JFLex from
- * src/main/jflex/simple.flex.
- *
- * @author JFlex contributors.
- *
- */
-public class YylexTest extends TestCase {
-
- private static final String OUTPUT_FILE = "target/output.actual";
-
- /**
- * Test that Yylex parser behaves like expected.
- *
- * @throws IOException
- */
- public void testOutput() throws IOException {
- String[] argv = new String[1];
- argv[0] = "src/test/resources/test.txt";
-
- // the Yylex prints status on stdout
- File actual = new File("target/output.actual");
- actual.delete();
- FileOutputStream fos = new FileOutputStream(OUTPUT_FILE, true);
- System.setOut(new PrintStream(fos));
-
- Yylex.main(argv);
-
- fos.close();
-
- // test actual is expected
- File expected = new File("src/test/resources/output.good");
- assertTrue(expected.isFile());
- assertTrue(actual.isFile());
-
- BufferedReader actualContent = new BufferedReader(
- new FileReader(actual));
- BufferedReader expectedContent = new BufferedReader(new FileReader(
- expected));
-
- for (int lineNumber = 1;lineNumber!=-1; lineNumber++) {
- String expectedLine = expectedContent.readLine();
- String actualLine = actualContent.readLine();
- assertEquals("Line "+lineNumber, expectedLine, actualLine);
- if (expectedLine==null) lineNumber=-2; //EOF
- }
- }
-}
diff --git a/jflex/examples/simple/BUILD b/jflex/examples/simple/BUILD
new file mode 100644
index 000000000..83f0d765b
--- /dev/null
+++ b/jflex/examples/simple/BUILD
@@ -0,0 +1,30 @@
+package(default_visibility = ["//visibility:public"])
+
+load("@jflex_rules//jflex:jflex.bzl", "jflex")
+
+# The best practice is to define the rules in their respective directory in
+# - src/main/java/org/example/foo/BUILD
+# - src/main/jflex/BUILD
+# - src/test/java/org/example/foo/BUILD
+# - etc.
+# However, this example is simple enough and we can define all rules here.
+
+java_binary(
+ name = "simple_bin",
+ main_class = "Yylex",
+ runtime_deps = [":simple"],
+)
+
+java_library(
+ name = "simple",
+ # glob is not a best practice, but it's good enough for this example
+ srcs = glob(["src/main/java/**/*.java"]) + [":gen_lexer"],
+ deps = ["//cup:cup_runtime"],
+)
+
+jflex(
+ name = "gen_lexer",
+ srcs = ["src/main/jflex/simple.flex"],
+ jflex_bin = "//jflex:jflex_bin",
+ outputs = ["Yylex.java"],
+)
diff --git a/jflex/examples/simple/README.md b/jflex/examples/simple/README.md
new file mode 100644
index 000000000..eb748102e
--- /dev/null
+++ b/jflex/examples/simple/README.md
@@ -0,0 +1,139 @@
+# Simple usage
+
+This is a very simple example of how to generate a lexer with JFlex:
+
+- for a very simple grammar of the _Toy programmimg language_
+ described in the user manual.
+- without integration to a parser. As a result, the program
+ does nothing really useful, because there is no parser.
+
+The generated lexer has the default name **Yylex** because the flex
+specification doesn't define a name with the `%class`.
+
+The project comes with a test class for the lexer: `YylexTest`.
+The test:
+- runs the lexer in debug mode on `test.txt`
+- collects the output of JFlex by redirecting `System.out`
+- and verifies that the verbose logs of JFlex corresponds to
+ the expected content of `output.good`.
+
+## Files
+
+* `main/flex/simple.flex`:
+ the simple grammar specification
+* `test/resources/test.txt`:
+ sample input
+* `test/resources/output.good`:
+ _golden file_, i.e. expected output corresponding to the sample input from `test.txt`
+* `tests/java/YylexTest.java`:
+ jUnit integration test that running the lexer on the sample input produces
+ the same output as the _golden file_.
+
+## Compile and test
+
+### Using Maven
+
+**Tip** Jflex comes with the Maven wrapper.
+You can use `../../mvnw` instead of `mvn` if the later is not installed on your
+system.
+
+#### Generate the lexer
+
+ mvn generate-sources
+
+The **jflex-maven-plugin** will read the grammar `src/main/jflex/simple.jflex`
+and generate a Java scanner **Yylex** in
+`target/generated-sources/flex/Yylex.java`.
+
+This is defined by the following section
+```xml
+
+
+
+ de.jflex
+ jflex-maven-plugin
+ 1.7.0
+
+
+
+ generate
+
+
+
+
+
+
+```
+
+By default, the **jflex-maven-plugin** generates a lexer (scanner) for every file
+in `src/main/jflex/`.
+
+#### Build
+
+ mvn compile
+
+The compile phase will build all Java classes, including those generated automatically.
+
+You will find the class files in `target/classes`.
+
+**Tip** In fact, you don't have to invoke `mvn generate-sources` explicitly,
+the **compile** phase will do it automatically.
+
+#### Test
+
+ mvn test
+
+The **test** phase executes the test in `src/test/java`.
+
+ This goal test the generated scanner (if required, the lexer will be
+ generated and all Java classes will be compiled)
+ by running all tests in <<>>.
+
+ There is only one test in <<>>.
+ In this test,
+ the scanner is run with the input file <<>>.
+
+ By default, the scanner outputs debugging information about each
+ returned token to <<>> until the end of file is reached,
+ or an error occurs.
+ But in the test, the output is redirected into <<>>.
+
+ The test is successful if every line match
+ with <<>>,
+ which is the expected scanner debugging information.
+
+
+ ../../mvnw package
+
+Expected output:
+* `target/generated-sources/jflex/Yylex.java` Java code generated from the flex file.
+
+**Rem** Notice that Maven ran a test for you.
+
+### Build with Bazel
+
+#### Build
+
+ blaze build //simple
+
+Expected output:
+* (`examples/`)`bazel-genfiles/simple/Yylex.java` Java code generated from the flex file.
+
+#### Test
+
+To execute the tests
+
+ blaze test //simple/...
+
+To run the lexer on any file
+
+ bazel run //simple:simple_bin -- /full/path/to/src/test/resources/test.txt
+
+**N.B.** Relative path doesn't work in `bazel run`.
+
+**Rem:** The Bazel commands work from any directory in the workspace.
+
+Alternatively, use the generated artifact. From the `examples` directory:
+
+ bazel-bin/simple/simple_bin simple/src/test/resources/test.txt
+
\ No newline at end of file
diff --git a/jflex/examples/simple/build.xml b/jflex/examples/simple/build.xml
new file mode 100644
index 000000000..3a68e9344
--- /dev/null
+++ b/jflex/examples/simple/build.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jflex/examples/simple-maven/pom.xml b/jflex/examples/simple/pom.xml
similarity index 72%
rename from jflex/examples/simple-maven/pom.xml
rename to jflex/examples/simple/pom.xml
index f1d0a17db..7d160afa2 100644
--- a/jflex/examples/simple-maven/pom.xml
+++ b/jflex/examples/simple/pom.xml
@@ -2,7 +2,7 @@
4.0.0de.flex.examples
- simple-maven
+ simple1.0A scanner for a toy programming language.It is the example from the JLex website with some small
@@ -15,12 +15,27 @@
junitjunit
- 3.8.2
+ 4.12
+ test
+
+
+ com.google.truth
+ truth
+ 0.36test
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.6
+ 1.6
+
+ de.jflexjflex-maven-plugin
diff --git a/jflex/examples/simple/src/main/java/Utility.java b/jflex/examples/simple/src/main/java/Utility.java
new file mode 100644
index 000000000..d770230b4
--- /dev/null
+++ b/jflex/examples/simple/src/main/java/Utility.java
@@ -0,0 +1,20 @@
+/** A small utility class. */
+// TODO: use resource bundle
+class Utility {
+
+ private static final String errorMsg[] = {
+ "Error: Unmatched end-of-comment punctuation.",
+ "Error: Unmatched start-of-comment punctuation.",
+ "Error: Unclosed string.",
+ "Error: Illegal character."
+ };
+
+ public static final int E_ENDCOMMENT = 0;
+ public static final int E_STARTCOMMENT = 1;
+ public static final int E_UNCLOSEDSTR = 2;
+ public static final int E_UNMATCHED = 3;
+
+ public static void error(int code) {
+ System.err.println(errorMsg[code]);
+ }
+}
diff --git a/jflex/examples/simple/src/main/java/Yytoken.java b/jflex/examples/simple/src/main/java/Yytoken.java
new file mode 100644
index 000000000..568ef732a
--- /dev/null
+++ b/jflex/examples/simple/src/main/java/Yytoken.java
@@ -0,0 +1,29 @@
+/** The tokens returned by the scanner. */
+class Yytoken {
+ public int m_index;
+ public String m_text;
+ public int m_line;
+ public int m_charBegin;
+ public int m_charEnd;
+
+ Yytoken(int index, String text, int line, int charBegin, int charEnd) {
+ m_index = index;
+ m_text = text;
+ m_line = line;
+ m_charBegin = charBegin;
+ m_charEnd = charEnd;
+ }
+
+ public String toString() {
+ return "Text : "
+ + m_text
+ + "\nindex : "
+ + m_index
+ + "\nline : "
+ + m_line
+ + "\ncBeg. : "
+ + m_charBegin
+ + "\ncEnd. : "
+ + m_charEnd;
+ }
+}
diff --git a/jflex/examples/simple-maven/src/main/jflex/simple.flex b/jflex/examples/simple/src/main/jflex/simple.flex
similarity index 100%
rename from jflex/examples/simple-maven/src/main/jflex/simple.flex
rename to jflex/examples/simple/src/main/jflex/simple.flex
diff --git a/jflex/examples/simple/src/test/BUILD b/jflex/examples/simple/src/test/BUILD
new file mode 100644
index 000000000..16e157848
--- /dev/null
+++ b/jflex/examples/simple/src/test/BUILD
@@ -0,0 +1,12 @@
+java_test(
+ name = "YylexTest",
+ srcs = ["java/YylexTest.java"],
+ data = [
+ "data/output.good",
+ "data/test.txt",
+ ],
+ deps = [
+ "//jflex/examples/simple",
+ "//third_party/com/google/truth",
+ ],
+)
diff --git a/jflex/examples/simple-maven/src/test/resources/output.good b/jflex/examples/simple/src/test/data/output.good
similarity index 100%
rename from jflex/examples/simple-maven/src/test/resources/output.good
rename to jflex/examples/simple/src/test/data/output.good
diff --git a/jflex/examples/simple-maven/src/test/resources/test.txt b/jflex/examples/simple/src/test/data/test.txt
similarity index 100%
rename from jflex/examples/simple-maven/src/test/resources/test.txt
rename to jflex/examples/simple/src/test/data/test.txt
diff --git a/jflex/examples/simple/src/test/java/YylexTest.java b/jflex/examples/simple/src/test/java/YylexTest.java
new file mode 100644
index 000000000..420097521
--- /dev/null
+++ b/jflex/examples/simple/src/test/java/YylexTest.java
@@ -0,0 +1,95 @@
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.common.base.Objects;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import junit.framework.TestCase;
+
+/**
+ * This is an integration test.
+ *
+ *
The class Yylex is generated by JFLex from {@code src/main/jflex/simple.flex}.
+ *
+ * @author Régis Décamps
+ */
+public class YylexTest extends TestCase {
+
+ private ByteArrayOutputStream outputStream;
+
+ @Override
+ public void setUp() {
+ // the Yylex prints status on stdout. Redirect to ByteOutputStream.
+ outputStream = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(outputStream));
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ outputStream.close();
+ }
+
+ /** Tests that the generated {@link Yylex} lexer behaves like expected. */
+ public void testOutput() throws Exception {
+ File inputFile = openFile("src/test/data/test.txt");
+ assertThat(inputFile.isFile()).isTrue();
+
+ String[] argv = new String[] {inputFile.getPath()};
+
+ Yylex.main(argv);
+
+ // test actual is expected
+ File expected = openFile("src/test/data/output.good");
+ assertThat(expected.isFile()).isTrue();
+
+ BufferedReader actualContent = readOutputStream();
+ BufferedReader expectedContent = new BufferedReader(new FileReader(expected));
+
+ for (int lineNumber = 1; lineNumber != -1; lineNumber++) {
+ String expectedLine = expectedContent.readLine();
+ String actualLine = actualContent.readLine();
+ assertWithMessage("Line " + lineNumber).that(actualLine).isEqualTo(expectedLine);
+ if (expectedLine == null) lineNumber = -2; // EOF
+ }
+ }
+
+ private BufferedReader readOutputStream() {
+ byte[] rawOutput = outputStream.toByteArray();
+ return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(rawOutput)));
+ }
+
+ /**
+ * Opens the given file.
+ *
+ *
This method also works around a build difficulty:
+ *
+ *
+ *
Maven uses the directory that contains {@code pom.xml} as a working directory, i.e.
+ * {@code examples/simple}
+ *
ant uses the directory that contains {@code build.xml} as a working directory, i.e.
+ * {@code examples/simple}
+ *
bazel uses the directory that contains {@code WORKSPACE} as a working directory, i.e.
+ * {@code __main__} in runfiles.
+ *
+ */
+ private File openFile(String pathName) throws IOException {
+ String path = pathName;
+ File pwd = new File(".").getCanonicalFile();
+ assertThat(pwd.isDirectory()).isTrue();
+ if (Objects.equal(pwd.getName(), "__main__")) {
+ path = "jflex/examples/simple/" + path;
+ }
+ File file = new File(path);
+ if (!file.isFile()) {
+ throw new FileNotFoundException(path);
+ }
+ return file;
+ }
+}
diff --git a/jflex/examples/standalone-maven/src/test/java/de/jflex/example/standalone/SubstTest.java b/jflex/examples/standalone-maven/src/test/java/de/jflex/example/standalone/SubstTest.java
deleted file mode 100644
index f51675b55..000000000
--- a/jflex/examples/standalone-maven/src/test/java/de/jflex/example/standalone/SubstTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package de.jflex.example.standalone;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.Reader;
-import junit.framework.TestCase;
-
-
-
-public class SubstTest extends TestCase {
- private static final String OUTPUT_FILE = "target/sample.out";
-
- public void testSample() throws IOException {
- // the standalon Subst prints status on stdout
- // redirecte it into a file
- String[] argv = new String[1];
- argv[0] = "src/test/resources/sample.in";
- File actual = new File(OUTPUT_FILE);
- actual.delete();
- FileOutputStream fos = new FileOutputStream(OUTPUT_FILE, true);
- System.setOut(new PrintStream(fos));
-
- Subst.main(argv);
-
- fos.close();
-
- BufferedReader actualContent = new BufferedReader(new FileReader(
- actual));
-
- // the expected result is in a file
- Reader expected = new FileReader("src/test/resources/sample.expected");
- BufferedReader expectedContent = new BufferedReader(expected);
-
- String expectedLine, actualLine;
- do {
- expectedLine = expectedContent.readLine();
- actualLine = actualContent.readLine();
-
- assertEquals(expectedLine, actualLine);
- } while (expectedLine != null);
- }
-}
diff --git a/jflex/examples/standalone-maven/pom.xml b/jflex/examples/standalone/pom.xml
similarity index 74%
rename from jflex/examples/standalone-maven/pom.xml
rename to jflex/examples/standalone/pom.xml
index d6bdedd87..5d03314a7 100644
--- a/jflex/examples/standalone-maven/pom.xml
+++ b/jflex/examples/standalone/pom.xml
@@ -15,9 +15,24 @@ of "hello" by "hello <name> !".3.8.2test
+
+ com.google.truth
+ truth
+ 0.36
+ test
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.6
+ 1.6
+
+ de.jflexjflex-maven-plugin
diff --git a/jflex/examples/standalone-maven/src/main/jflex/standalone.flex b/jflex/examples/standalone/src/main/jflex/standalone.flex
similarity index 100%
rename from jflex/examples/standalone-maven/src/main/jflex/standalone.flex
rename to jflex/examples/standalone/src/main/jflex/standalone.flex
diff --git a/jflex/examples/standalone/src/test/java/de/jflex/example/standalone/SubstTest.java b/jflex/examples/standalone/src/test/java/de/jflex/example/standalone/SubstTest.java
new file mode 100644
index 000000000..a2895e97a
--- /dev/null
+++ b/jflex/examples/standalone/src/test/java/de/jflex/example/standalone/SubstTest.java
@@ -0,0 +1,45 @@
+package de.jflex.example.standalone;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.Reader;
+import junit.framework.TestCase;
+
+public class SubstTest extends TestCase {
+ private static final String OUTPUT_FILE = "target/sample.out";
+
+ public void testSample() throws IOException {
+ // the standalon Subst prints status on stdout
+ // redirecte it into a file
+ String[] argv = new String[1];
+ argv[0] = "src/test/resources/sample.in";
+ File actual = new File(OUTPUT_FILE);
+ actual.delete();
+ FileOutputStream fos = new FileOutputStream(OUTPUT_FILE, true);
+ System.setOut(new PrintStream(fos));
+
+ Subst.main(argv);
+
+ fos.close();
+
+ BufferedReader actualContent = new BufferedReader(new FileReader(actual));
+
+ // the expected result is in a file
+ Reader expected = new FileReader("src/test/resources/sample.expected");
+ BufferedReader expectedContent = new BufferedReader(expected);
+
+ String expectedLine, actualLine;
+ do {
+ expectedLine = expectedContent.readLine();
+ actualLine = actualContent.readLine();
+
+ assertThat(actualLine).isEqualTo(expectedLine);
+ } while (expectedLine != null);
+ }
+}
diff --git a/jflex/examples/standalone-maven/src/test/resources/sample.expected b/jflex/examples/standalone/src/test/resources/sample.expected
similarity index 100%
rename from jflex/examples/standalone-maven/src/test/resources/sample.expected
rename to jflex/examples/standalone/src/test/resources/sample.expected
diff --git a/jflex/examples/standalone-maven/src/test/resources/sample.in b/jflex/examples/standalone/src/test/resources/sample.in
similarity index 100%
rename from jflex/examples/standalone-maven/src/test/resources/sample.in
rename to jflex/examples/standalone/src/test/resources/sample.in
diff --git a/jflex/examples/zero-reader/Makefile b/jflex/examples/zero-reader/Makefile
index 1fafe4775..024b707e1 100644
--- a/jflex/examples/zero-reader/Makefile
+++ b/jflex/examples/zero-reader/Makefile
@@ -1,30 +1,26 @@
JFLEX = ../../bin/jflex
-JAVA = java
-JAVAC = javac
+
LEXER = ZeroLexer
# --------------------------------------------------
-all: test
+all: clean compile
-test: output.txt
- @(diff output.txt lexer-output.good && echo "Test OK!") || echo "Test failed!"
+test: out/output.txt
+ @(diff --strip-trailing-cr src/test/data/lexer-output.good $< && echo "Test OK") || (echo "Test FAILED"; exit 1)
-output.txt: $(LEXER).class test-input.txt
- $(JAVA) $(LEXER) test-input.txt > output.txt
+out/output.txt: out/$(LEXER).class src/test/data/test-input.txt
+ java -cp out $(LEXER) src/test/data/test-input.txt > $@
-compile: $(LEXER).class
+compile: out/$(LEXER).class
-$(LEXER).class: $(LEXER).java FunkyReader.java ZeroReader.java
- $(JAVAC) $^
+out/$(LEXER).class: out/$(LEXER).java src/main/java/*.java
+ javac -d out $^
-$(LEXER).java: zero-lexer.jflex
- $(JFLEX) $<
+out/$(LEXER).java: src/main/jflex/zero-lexer.jflex
+ $(JFLEX) -d out $<
clean:
- rm -f *.class
- rm -f *~
- rm -f $(LEXER).java
- rm -f output.txt
+ rm -rf out
diff --git a/jflex/examples/zero-reader/README.md b/jflex/examples/zero-reader/README.md
index 571d2ef61..a1cba619f 100644
--- a/jflex/examples/zero-reader/README.md
+++ b/jflex/examples/zero-reader/README.md
@@ -1,3 +1,5 @@
+# Readers returning 0 characters
+
This example shows what to do about input Readers that sometimes return 0
characters.
@@ -53,3 +55,23 @@ blocking if no input is available yet (if `read()` returns 0, it means the
character 0 has been read, not that 0 characters have been read). This method
is usually too inefficient to use always, but 0-character returns tend to be
rare, so the impact of using it only in those cases is small.
+
+Build
+-----
+
+### Build with maven
+
+ ../../mvnw package
+ java -jar target/zero-reader-1.0.jar
+
+e.g.
+
+ java -jar target/zero-reader-1.0.jar src/test/data/test-input.txt
+
+and expect `src/test/data/lexer-output.good`.
+
+### Build with make
+
+ make
+ make test
+ java -cp out ZeroLexer
diff --git a/jflex/examples/zero-reader/pom.xml b/jflex/examples/zero-reader/pom.xml
new file mode 100644
index 000000000..02aae689e
--- /dev/null
+++ b/jflex/examples/zero-reader/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+ de.flex.examples
+ zero-reader
+ 1.0
+ Example of a Reader wrapper that supports reading 0 character
+ This example shows what to do about input Readers that sometimes return 0
+ characters.
+
+
+ de.jflex
+ cup_runtime
+ 11b
+
+
+ junit
+ junit
+ 3.8.2
+ test
+
+
+
+
+
+ de.jflex
+ jflex-maven-plugin
+ 1.7.1-SNAPSHOT
+
+
+
+ generate
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.6
+ 1.6
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.0
+
+
+
+ true
+ ZeroLexer
+
+
+
+
+
+
+
+ UTF-8
+
+
diff --git a/jflex/examples/zero-reader/FunkyReader.java b/jflex/examples/zero-reader/src/main/java/FunkyReader.java
similarity index 85%
rename from jflex/examples/zero-reader/FunkyReader.java
rename to jflex/examples/zero-reader/src/main/java/FunkyReader.java
index 9f4d7f645..db04aa9bc 100644
--- a/jflex/examples/zero-reader/FunkyReader.java
+++ b/jflex/examples/zero-reader/src/main/java/FunkyReader.java
@@ -8,16 +8,14 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-import java.io.Reader;
import java.io.IOException;
-
+import java.io.Reader;
/**
* Reader that returns 0 chars read every once in a while.
- *
- * This is a demonstration of a problematic Reader that does not
- * implement the Reader specification correctly. Do not use.
+ *
+ *
This is a demonstration of a problematic Reader that does not implement the Reader
+ * specification correctly. Do not use.
*/
public class FunkyReader extends Reader {
@@ -31,9 +29,8 @@ public FunkyReader(Reader r) {
public int read(char[] cbuf, int off, int len) throws IOException {
if (!do_zero) {
do_zero = true;
- return reader.read(cbuf,off,Math.min(10,len));
- }
- else {
+ return reader.read(cbuf, off, Math.min(10, len));
+ } else {
do_zero = false;
return 0;
}
@@ -42,5 +39,4 @@ public int read(char[] cbuf, int off, int len) throws IOException {
public void close() throws IOException {
reader.close();
}
-
}
diff --git a/jflex/examples/zero-reader/ZeroReader.java b/jflex/examples/zero-reader/src/main/java/ZeroReader.java
similarity index 61%
rename from jflex/examples/zero-reader/ZeroReader.java
rename to jflex/examples/zero-reader/src/main/java/ZeroReader.java
index b2436d614..2e2f359f0 100644
--- a/jflex/examples/zero-reader/ZeroReader.java
+++ b/jflex/examples/zero-reader/src/main/java/ZeroReader.java
@@ -8,68 +8,59 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-import java.io.Reader;
import java.io.IOException;
-
+import java.io.Reader;
/**
- * A Reader wrapper that guards against Readers that sometimes
- * return 0 characters instead of blocking.
+ * A Reader wrapper that guards against Readers that sometimes return 0 characters instead of
+ * blocking.
*
- * If 0 character returns are rare, efficiency loss will be minimal.
+ *
If 0 character returns are rare, efficiency loss will be minimal.
*/
public class ZeroReader extends Reader {
- /**
- * The underlying Reader that is being wrapped.
- */
+ /** The underlying Reader that is being wrapped. */
private Reader reader;
-
/**
- * A new ZeroReader wrapper for a Reader that does not always
- * block appropriately in read(char[],int,int).
+ * A new ZeroReader wrapper for a Reader that does not always block appropriately in
+ * read(char[],int,int).
*
- * @param reader the original Reader to wrap
+ * @param reader the original Reader to wrap
*/
public ZeroReader(Reader reader) {
this.reader = reader;
}
-
/**
- * Read len characters from the underlying Reader into the buffer
- * cbuf at position off. Blocks until input is available.
- *
- * Relies on the method char read() of the underlying Reader to block
- * until at least one character is available.
- *
- * @param buf the buffer to write into
- * @param off the offset from where to write
- * @param len the maximum number of characters to write
+ * Read len characters from the underlying Reader into the buffer cbuf at position off. Blocks
+ * until input is available.
*
- * @return -1 for end of stream, number of characters read otherwise.
- * Returns 0 if and only if len is less than or equal to 0.
+ *
Relies on the method char read() of the underlying Reader to block until at least one
+ * character is available.
*
- * @throws IOException if the underlying reader throws one or if the
- * offset is outside the provided buffer.
+ * @param buf the buffer to write into
+ * @param off the offset from where to write
+ * @param len the maximum number of characters to write
+ * @return -1 for end of stream, number of characters read otherwise. Returns 0 if and only if len
+ * is less than or equal to 0.
+ * @throws IOException if the underlying reader throws one or if the offset is outside the
+ * provided buffer.
*/
public int read(char[] cbuf, int off, int len) throws IOException {
- int n = reader.read(cbuf,off,len);
+ int n = reader.read(cbuf, off, len);
if (n != 0 || len <= 0) {
return n;
- }
- else {
+ } else {
if (off < cbuf.length) {
// Returns the character read, as an integer in the range 0 to 65535
// (0x00-0xffff), or -1 if the end of the stream has been reached
int c = reader.read();
- if (c == -1) return -1;
+ if (c == -1) return -1;
cbuf[off] = (char) c;
return 1;
- }
- else throw new IOException("Offset outside buffer");
+ } else throw new IOException("Offset outside buffer");
}
}
@@ -81,5 +72,4 @@ public int read(char[] cbuf, int off, int len) throws IOException {
public void close() throws IOException {
reader.close();
}
-
}
diff --git a/jflex/examples/zero-reader/zero-lexer.jflex b/jflex/examples/zero-reader/src/main/jflex/zero-lexer.jflex
similarity index 100%
rename from jflex/examples/zero-reader/zero-lexer.jflex
rename to jflex/examples/zero-reader/src/main/jflex/zero-lexer.jflex
diff --git a/jflex/examples/zero-reader/lexer-output.good b/jflex/examples/zero-reader/src/test/data/lexer-output.good
similarity index 100%
rename from jflex/examples/zero-reader/lexer-output.good
rename to jflex/examples/zero-reader/src/test/data/lexer-output.good
diff --git a/jflex/examples/zero-reader/test-input.txt b/jflex/examples/zero-reader/src/test/data/test-input.txt
similarity index 100%
rename from jflex/examples/zero-reader/test-input.txt
rename to jflex/examples/zero-reader/src/test/data/test-input.txt
diff --git a/jflex/pom.xml b/jflex/pom.xml
index 85bcc88d8..5236bad1a 100644
--- a/jflex/pom.xml
+++ b/jflex/pom.xml
@@ -158,6 +158,25 @@
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+
+ prepare-agent
+
+
+
+
+ jflex/unicode/data/*.java
+
+
+
+
+
diff --git a/jflex/src/main/java/jflex/Action.java b/jflex/src/main/java/jflex/Action.java
index 6b3fc1e85..2d7d5ebd5 100644
--- a/jflex/src/main/java/jflex/Action.java
+++ b/jflex/src/main/java/jflex/Action.java
@@ -9,6 +9,8 @@
package jflex;
+import java.util.Objects;
+
/**
* Encapsulates an action in the specification.
*
@@ -41,8 +43,7 @@ public final class Action {
int priority;
/**
- * Which kind of action this is. (normal, a/b with fixed length a, fixed length b,
- * etc)
+ * Which kind of action this is. (normal, {@code a/b} with fixed length a, fixed length b, etc)
*/
private int kind = NORMAL;
@@ -110,14 +111,14 @@ public String toString() {
}
/**
- * Returns true iff the parameter is an Action with the same content as this one.
+ * Returns {@code true} iff the parameter is an Action with the same content as this one.
*
* @param a the object to compare this Action with
* @return true if the action strings are equal
*/
public boolean isEquiv(Action a) {
return this == a
- || (this.content.equals(a.content)
+ || (Objects.equals(this.content, a.content)
&& this.kind == a.kind
&& this.len == a.len
&& this.entryState == a.entryState);
diff --git a/jflex/src/main/java/jflex/CharClassInterval.java b/jflex/src/main/java/jflex/CharClassInterval.java
index 56581599a..2157da948 100644
--- a/jflex/src/main/java/jflex/CharClassInterval.java
+++ b/jflex/src/main/java/jflex/CharClassInterval.java
@@ -13,7 +13,7 @@
* Stores an interval of characters together with the character class
*
*
A character belongs to an interval, if its Unicode value is greater than or equal to the
- * Unicode value of start and smaller than or equal to the Unicode value of end
+ * Unicode value of {@code start} and smaller than or equal to the Unicode value of end
* .
*
*
All characters of the interval must belong to the same character class.
@@ -33,8 +33,8 @@ public class CharClassInterval {
int charClass;
/**
- * Creates a new CharClassInterval from start to end that belongs to
- * character class charClass.
+ * Creates a new CharClassInterval from {@code start
to end} that belongs to
+ * character class {@code charClass}.
*
* @param start The first character of the interval
* @param end The last character of the interval
diff --git a/jflex/src/main/java/jflex/CharClasses.java b/jflex/src/main/java/jflex/CharClasses.java
index dd4bf62f4..971b7eb0e 100644
--- a/jflex/src/main/java/jflex/CharClasses.java
+++ b/jflex/src/main/java/jflex/CharClasses.java
@@ -11,6 +11,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Character Classes.
@@ -111,8 +112,8 @@ public int getNumClasses() {
* Updates the current partition, so that the specified set of characters gets a new character
* class.
*
- *
Characters that are elements of set are not in the same equivalence class with
- * characters that are not elements of set.
+ *
Characters that are elements of {@code set} are not in the same equivalence class with
+ * characters that are not elements of {@code set}.
*
* @param set the set of characters to distinguish from the rest
* @param caseless if true upper/lower/title case are considered equivalent
@@ -129,15 +130,15 @@ public void makeClass(IntCharSet set, boolean caseless) {
for (int i = 0; i < oldSize; i++) {
IntCharSet x = classes.get(i);
- if (x.equals(set)) return;
+ if (Objects.equals(x, set)) return;
IntCharSet and = x.and(set);
if (and.containsElements()) {
- if (x.equals(and)) {
+ if (Objects.equals(x, and)) {
set.sub(and);
continue;
- } else if (set.equals(and)) {
+ } else if (Objects.equals(set, and)) {
x.sub(and);
classes.add(and);
if (DEBUG) {
@@ -213,7 +214,7 @@ public String toString() {
}
/**
- * Creates a new character class for the single character singleChar.
+ * Creates a new character class for the single character {@code singleChar}.
*
* @param caseless if true upper/lower/title case are considered equivalent
* @param singleChar character.
@@ -240,8 +241,8 @@ public void makeClass(String str, boolean caseless) {
* Updates the current partition, so that the specified set of characters gets a new character
* class.
*
- *
Characters that are elements of the set l are not in the same equivalence class
- * with characters that are not elements of the set l.
+ *
Characters that are elements of the set {@code l} are not in the same equivalence class with
+ * characters that are not elements of the set {@code l}.
*
* @param l a List of Interval objects. This List represents a set of characters. The set of
* characters is the union of all intervals in the List.
@@ -255,10 +256,10 @@ public void makeClass(List l, boolean caseless) {
* Updates the current partition, so that the set of all characters not contained in the specified
* set of characters gets a new character class.
*
- *
Characters that are elements of the set v are not in the same equivalence class
- * with characters that are not elements of the set v.
+ *
Characters that are elements of the set {@code v} are not in the same equivalence class with
+ * characters that are not elements of the set {@code v}.
*
- *
This method is equivalent to makeClass(v)
+ *
This method is equivalent to {@code makeClass(v)}
*
* @param l a List of Interval objects. This List represents a set of characters. The set of
* characters is the union of all intervals in the List.
@@ -359,8 +360,8 @@ public void check() {
/**
* Returns an array of all CharClassIntervals in this char class collection.
*
- *
The array is ordered by char code, i.e. result[i+1].start = result[i].end+1
- * Each CharClassInterval contains the number of the char class it belongs to.
+ *
The array is ordered by char code, i.e. {@code result[i+1].start = result[i].end+1} Each
+ * CharClassInterval contains the number of the char class it belongs to.
*
* @return an array of all {@link jflex.CharClassInterval} in this char class collection.
*/
diff --git a/jflex/src/main/java/jflex/CountEmitter.java b/jflex/src/main/java/jflex/CountEmitter.java
index d80d8f1c6..53a8dfe3f 100644
--- a/jflex/src/main/java/jflex/CountEmitter.java
+++ b/jflex/src/main/java/jflex/CountEmitter.java
@@ -84,8 +84,8 @@ public void emitUnpack() {
*
*
Use to move value interval from [0, 0xFFFF] to something different.
*
- * @param i amount the value will be translated by. Example: i = 1 allows values in
- * [-1, 0xFFFE].
+ * @param i amount the value will be translated by. Example: {@code i = 1} allows values in [-1,
+ * 0xFFFE].
*/
public void setValTranslation(int i) {
this.translate = i;
@@ -94,7 +94,7 @@ public void setValTranslation(int i) {
/**
* Emit one count/value pair.
*
- *
Automatically translates value by the translate value.
+ *
Automatically translates value by the {@code translate} value.
*
* @param count a int.
* @param value a int.
diff --git a/jflex/src/main/java/jflex/DFA.java b/jflex/src/main/java/jflex/DFA.java
index cfefea79f..d85b83bee 100644
--- a/jflex/src/main/java/jflex/DFA.java
+++ b/jflex/src/main/java/jflex/DFA.java
@@ -15,6 +15,7 @@
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
/**
* Deterministic finite automata representation in JFlex. Contains minimization algorithm.
@@ -31,18 +32,18 @@ public final class DFA {
public static final int NO_TARGET = -1;
/**
- * table[current_state][character] is the next state for current_state with input
- * character, NO_TARGET if there is no transition for this input in
- * current_state
+ * table[current_state][character] is the next state for {@code current_state} with input {@code
+ * character
, NO_TARGET} if there is no transition for this input in {@code
+ * current_state}
*/
int[][] table;
- /** isFinal[state] == true <=> the state state is a final state. */
+ /** {@code isFinal[state] == true <=> the state state} is a final state. */
boolean[] isFinal;
/**
- * action[state] is the action that is to be carried out in state state,
- * null if there is no action.
+ * {@code action[state] is the action that is to be carried out in state state},
+ * {@code null} if there is no action.
*/
Action[] action;
@@ -173,7 +174,7 @@ public String toString() {
if (isFinal[i]) {
result.append("[FINAL");
String l = action[i].lookString();
- if (!l.equals("")) {
+ if (!Objects.equals(l, "")) {
result.append(", ");
result.append(l);
}
@@ -255,7 +256,7 @@ public void checkActions(LexScan scanner, LexParse parser) {
EOFActions eofActions = parser.getEOFActions();
for (Action a : scanner.actions)
- if (!a.equals(usedActions.get(a)) && !eofActions.isEOFAction(a))
+ if (!Objects.equals(a, usedActions.get(a)) && !eofActions.isEOFAction(a))
Out.warning(scanner.file, ErrorMessages.NEVER_MATCH, a.priority - 1, -1);
}
diff --git a/jflex/src/main/java/jflex/Emitter.java b/jflex/src/main/java/jflex/Emitter.java
index abc9c2e07..de45e63d9 100644
--- a/jflex/src/main/java/jflex/Emitter.java
+++ b/jflex/src/main/java/jflex/Emitter.java
@@ -19,6 +19,7 @@
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import jflex.io.FileUtil;
/**
* This class manages the actual code generation, putting the scanner together, filling in skeleton
@@ -46,6 +47,7 @@ public final class Emitter {
private static final int NOLOOK = 8;
private File inputFile;
+ final String outputFileName;
private PrintWriter out;
private Skeleton skel;
@@ -85,6 +87,7 @@ public Emitter(File inputFile, LexParse parser, DFA dfa) throws IOException {
String name = getBaseName(parser.scanner.className) + ".java";
File outputFile = normalize(name, inputFile);
+ outputFileName = outputFile.getAbsolutePath();
Out.println("Writing code to \"" + outputFile + "\"");
@@ -406,7 +409,15 @@ private void emitNextInput() {
}
private void emitHeader() {
- println("/* The following code was generated by JFlex " + Main.version + " */");
+ println("// DO NOT EDIT");
+ println("// Generated by JFlex " + LexGenerator.VERSION + " http://jflex.de/");
+ String path = FileUtil.getRelativePath(Options.getRootDirectory(), inputFile);
+ if (File.separatorChar == '\\') {
+ path = FileUtil.slashify(path);
+ }
+ // Character '\' can be use for Unicode representation, e.g. \\u000A is new line
+ path = path.replace("\\", "\\\\");
+ println("// source: " + path);
println("");
}
@@ -423,20 +434,6 @@ private void emitUserCode() {
}
private void emitClassName() {
- if (!endsWithJavadoc(scanner.userCode)) {
- String path = inputFile.toString();
- // slashify path (avoid backslash u sequence = unicode escape)
- if (File.separatorChar != '/') {
- path = path.replace(File.separatorChar, '/');
- }
-
- println("/**");
- println(" * This class is a scanner generated by ");
- println(" * JFlex " + Main.version);
- println(" * from the specification file " + path + "");
- println(" */");
- }
-
if (scanner.isPublic) print("public ");
if (scanner.isAbstract) print("abstract ");
@@ -706,7 +703,7 @@ private void emitRowMapArray() {
private void emitAttributes() {
println(" /**");
- println(" * ZZ_ATTRIBUTE[aState] contains the attributes of state aState");
+ println(" * ZZ_ATTRIBUTE[aState] contains the attributes of state {@code aState}");
println(" */");
CountEmitter e = new CountEmitter("Attribute");
diff --git a/jflex/src/main/java/jflex/ErrorMessages.java b/jflex/src/main/java/jflex/ErrorMessages.java
index 28b4dac65..7cad6f261 100644
--- a/jflex/src/main/java/jflex/ErrorMessages.java
+++ b/jflex/src/main/java/jflex/ErrorMessages.java
@@ -61,172 +61,172 @@ public static String get(ErrorMessages msg, Object... args) {
}
// typesafe enumeration (generated, do not edit)
- /** Constant UNTERMINATED_STR */
+ /** Constant {@code UNTERMINATED_STR} */
public static ErrorMessages UNTERMINATED_STR = new ErrorMessages("UNTERMINATED_STR");
- /** Constant EOF_WO_ACTION */
+ /** Constant {@code EOF_WO_ACTION} */
public static ErrorMessages EOF_WO_ACTION = new ErrorMessages("EOF_WO_ACTION");
- /** Constant UNKNOWN_OPTION */
+ /** Constant {@code UNKNOWN_OPTION} */
public static ErrorMessages UNKNOWN_OPTION = new ErrorMessages("UNKNOWN_OPTION");
- /** Constant UNEXPECTED_CHAR */
+ /** Constant {@code UNEXPECTED_CHAR} */
public static ErrorMessages UNEXPECTED_CHAR = new ErrorMessages("UNEXPECTED_CHAR");
- /** Constant UNEXPECTED_NL */
+ /** Constant {@code UNEXPECTED_NL} */
public static ErrorMessages UNEXPECTED_NL = new ErrorMessages("UNEXPECTED_NL");
- /** Constant LEXSTATE_UNDECL */
+ /** Constant {@code LEXSTATE_UNDECL} */
public static ErrorMessages LEXSTATE_UNDECL = new ErrorMessages("LEXSTATE_UNDECL");
- /** Constant REPEAT_ZERO */
+ /** Constant {@code REPEAT_ZERO} */
public static ErrorMessages REPEAT_ZERO = new ErrorMessages("REPEAT_ZERO");
- /** Constant REPEAT_GREATER */
+ /** Constant {@code REPEAT_GREATER} */
public static ErrorMessages REPEAT_GREATER = new ErrorMessages("REPEAT_GREATER");
- /** Constant REGEXP_EXPECTED */
+ /** Constant {@code REGEXP_EXPECTED} */
public static ErrorMessages REGEXP_EXPECTED = new ErrorMessages("REGEXP_EXPECTED");
- /** Constant MACRO_UNDECL */
+ /** Constant {@code MACRO_UNDECL} */
public static ErrorMessages MACRO_UNDECL = new ErrorMessages("MACRO_UNDECL");
- /** Constant CHARSET_2_SMALL */
+ /** Constant {@code CHARSET_2_SMALL} */
public static ErrorMessages CHARSET_2_SMALL = new ErrorMessages("CHARSET_2_SMALL");
- /** Constant CS2SMALL_STRING */
+ /** Constant {@code CS2SMALL_STRING} */
public static ErrorMessages CS2SMALL_STRING = new ErrorMessages("CS2SMALL_STRING");
- /** Constant CS2SMALL_CHAR */
+ /** Constant {@code CS2SMALL_CHAR} */
public static ErrorMessages CS2SMALL_CHAR = new ErrorMessages("CS2SMALL_CHAR");
- /** Constant CHARCLASS_MACRO */
+ /** Constant {@code CHARCLASS_MACRO} */
public static ErrorMessages CHARCLASS_MACRO = new ErrorMessages("CHARCLASS_MACRO");
- /** Constant UNKNOWN_SYNTAX */
+ /** Constant {@code UNKNOWN_SYNTAX} */
public static ErrorMessages UNKNOWN_SYNTAX = new ErrorMessages("UNKNOWN_SYNTAX");
- /** Constant SYNTAX_ERROR */
+ /** Constant {@code SYNTAX_ERROR} */
public static ErrorMessages SYNTAX_ERROR = new ErrorMessages("SYNTAX_ERROR");
- /** Constant NOT_AT_BOL */
+ /** Constant {@code NOT_AT_BOL} */
public static ErrorMessages NOT_AT_BOL = new ErrorMessages("NOT_AT_BOL");
- /** Constant EOF_IN_ACTION */
+ /** Constant {@code EOF_IN_ACTION} */
public static ErrorMessages EOF_IN_ACTION = new ErrorMessages("EOF_IN_ACTION");
- /** Constant EOF_IN_COMMENT */
+ /** Constant {@code EOF_IN_COMMENT} */
public static ErrorMessages EOF_IN_COMMENT = new ErrorMessages("EOF_IN_COMMENT");
- /** Constant EOF_IN_STRING */
+ /** Constant {@code EOF_IN_STRING} */
public static ErrorMessages EOF_IN_STRING = new ErrorMessages("EOF_IN_STRING");
- /** Constant EOF_IN_MACROS */
+ /** Constant {@code EOF_IN_MACROS} */
public static ErrorMessages EOF_IN_MACROS = new ErrorMessages("EOF_IN_MACROS");
- /** Constant EOF_IN_STATES */
+ /** Constant {@code EOF_IN_STATES} */
public static ErrorMessages EOF_IN_STATES = new ErrorMessages("EOF_IN_STATES");
- /** Constant EOF_IN_REGEXP */
+ /** Constant {@code EOF_IN_REGEXP} */
public static ErrorMessages EOF_IN_REGEXP = new ErrorMessages("EOF_IN_REGEXP");
- /** Constant UNEXPECTED_EOF */
+ /** Constant {@code UNEXPECTED_EOF} */
public static ErrorMessages UNEXPECTED_EOF = new ErrorMessages("UNEXPECTED_EOF");
- /** Constant NO_LEX_SPEC */
+ /** Constant {@code NO_LEX_SPEC} */
public static ErrorMessages NO_LEX_SPEC = new ErrorMessages("NO_LEX_SPEC");
- /** Constant NO_LAST_ACTION */
+ /** Constant {@code NO_LAST_ACTION} */
public static ErrorMessages NO_LAST_ACTION = new ErrorMessages("NO_LAST_ACTION");
- /** Constant NO_DIRECTORY */
+ /** Constant {@code NO_DIRECTORY} */
public static ErrorMessages NO_DIRECTORY = new ErrorMessages("NO_DIRECTORY");
- /** Constant NO_SKEL_FILE */
+ /** Constant {@code NO_SKEL_FILE} */
public static ErrorMessages NO_SKEL_FILE = new ErrorMessages("NO_SKEL_FILE");
- /** Constant WRONG_SKELETON */
+ /** Constant {@code WRONG_SKELETON} */
public static ErrorMessages WRONG_SKELETON = new ErrorMessages("WRONG_SKELETON");
- /** Constant OUT_OF_MEMORY */
+ /** Constant {@code OUT_OF_MEMORY} */
public static ErrorMessages OUT_OF_MEMORY = new ErrorMessages("OUT_OF_MEMORY");
- /** Constant QUIL_INITTHROW */
+ /** Constant {@code QUIL_INITTHROW} */
public static ErrorMessages QUIL_INITTHROW = new ErrorMessages("QUIL_INITTHROW");
- /** Constant QUIL_EOFTHROW */
+ /** Constant {@code QUIL_EOFTHROW} */
public static ErrorMessages QUIL_EOFTHROW = new ErrorMessages("QUIL_EOFTHROW");
- /** Constant QUIL_YYLEXTHROW */
+ /** Constant {@code QUIL_YYLEXTHROW} */
public static ErrorMessages QUIL_YYLEXTHROW = new ErrorMessages("QUIL_YYLEXTHROW");
- /** Constant ZERO_STATES */
+ /** Constant {@code ZERO_STATES} */
public static ErrorMessages ZERO_STATES = new ErrorMessages("ZERO_STATES");
- /** Constant NO_BUFFER_SIZE */
+ /** Constant {@code NO_BUFFER_SIZE} */
public static ErrorMessages NO_BUFFER_SIZE = new ErrorMessages("NO_BUFFER_SIZE");
- /** Constant NOT_READABLE */
+ /** Constant {@code NOT_READABLE} */
public static ErrorMessages NOT_READABLE = new ErrorMessages("NOT_READABLE");
- /** Constant FILE_CYCLE */
+ /** Constant {@code FILE_CYCLE} */
public static ErrorMessages FILE_CYCLE = new ErrorMessages("FILE_CYCLE");
- /** Constant FILE_WRITE */
+ /** Constant {@code FILE_WRITE} */
public static ErrorMessages FILE_WRITE = new ErrorMessages("FILE_WRITE");
- /** Constant QUIL_SCANERROR */
+ /** Constant {@code QUIL_SCANERROR} */
public static ErrorMessages QUIL_SCANERROR = new ErrorMessages("QUIL_SCANERROR");
- /** Constant NEVER_MATCH */
+ /** Constant {@code NEVER_MATCH} */
public static ErrorMessages NEVER_MATCH = new ErrorMessages("NEVER_MATCH");
- /** Constant QUIL_THROW */
+ /** Constant {@code QUIL_THROW} */
public static ErrorMessages QUIL_THROW = new ErrorMessages("QUIL_THROW");
- /** Constant EOL_IN_CHARCLASS */
+ /** Constant {@code EOL_IN_CHARCLASS} */
public static ErrorMessages EOL_IN_CHARCLASS = new ErrorMessages("EOL_IN_CHARCLASS");
- /** Constant QUIL_CUPSYM */
+ /** Constant {@code QUIL_CUPSYM} */
public static ErrorMessages QUIL_CUPSYM = new ErrorMessages("QUIL_CUPSYM");
- /** Constant CUPSYM_AFTER_CUP */
+ /** Constant {@code CUPSYM_AFTER_CUP} */
public static ErrorMessages CUPSYM_AFTER_CUP = new ErrorMessages("CUPSYM_AFTER_CUP");
- /** Constant ALREADY_RUNNING */
+ /** Constant {@code ALREADY_RUNNING} */
public static ErrorMessages ALREADY_RUNNING = new ErrorMessages("ALREADY_RUNNING");
- /** Constant CANNOT_READ_SKEL */
+ /** Constant {@code CANNOT_READ_SKEL} */
public static ErrorMessages CANNOT_READ_SKEL = new ErrorMessages("CANNOT_READ_SKEL");
- /** Constant READING_SKEL */
+ /** Constant {@code READING_SKEL} */
public static ErrorMessages READING_SKEL = new ErrorMessages("READING_SKEL");
- /** Constant SKEL_IO_ERROR */
+ /** Constant {@code SKEL_IO_ERROR} */
public static ErrorMessages SKEL_IO_ERROR = new ErrorMessages("SKEL_IO_ERROR");
- /** Constant SKEL_IO_ERROR_DEFAULT */
+ /** Constant {@code SKEL_IO_ERROR_DEFAULT} */
public static ErrorMessages SKEL_IO_ERROR_DEFAULT = new ErrorMessages("SKEL_IO_ERROR_DEFAULT");
- /** Constant READING */
+ /** Constant {@code READING} */
public static ErrorMessages READING = new ErrorMessages("READING");
- /** Constant CANNOT_OPEN */
+ /** Constant {@code CANNOT_OPEN} */
public static ErrorMessages CANNOT_OPEN = new ErrorMessages("CANNOT_OPEN");
- /** Constant NFA_IS */
+ /** Constant {@code NFA_IS} */
public static ErrorMessages NFA_IS = new ErrorMessages("NFA_IS");
- /** Constant NFA_STATES */
+ /** Constant {@code NFA_STATES} */
public static ErrorMessages NFA_STATES = new ErrorMessages("NFA_STATES");
- /** Constant DFA_TOOK */
+ /** Constant {@code DFA_TOOK} */
public static ErrorMessages DFA_TOOK = new ErrorMessages("DFA_TOOK");
- /** Constant DFA_IS */
+ /** Constant {@code DFA_IS} */
public static ErrorMessages DFA_IS = new ErrorMessages("DFA_IS");
- /** Constant MIN_TOOK */
+ /** Constant {@code MIN_TOOK} */
public static ErrorMessages MIN_TOOK = new ErrorMessages("MIN_TOOK");
- /** Constant MIN_DFA_IS */
+ /** Constant {@code MIN_DFA_IS} */
public static ErrorMessages MIN_DFA_IS = new ErrorMessages("MIN_DFA_IS");
- /** Constant WRITE_TOOK */
+ /** Constant {@code WRITE_TOOK} */
public static ErrorMessages WRITE_TOOK = new ErrorMessages("WRITE_TOOK");
- /** Constant TOTAL_TIME */
+ /** Constant {@code TOTAL_TIME} */
public static ErrorMessages TOTAL_TIME = new ErrorMessages("TOTAL_TIME");
- /** Constant IO_ERROR */
+ /** Constant {@code IO_ERROR} */
public static ErrorMessages IO_ERROR = new ErrorMessages("IO_ERROR");
- /** Constant THIS_IS_JFLEX */
+ /** Constant {@code THIS_IS_JFLEX} */
public static ErrorMessages THIS_IS_JFLEX = new ErrorMessages("THIS_IS_JFLEX");
- /** Constant UNKNOWN_COMMANDLINE */
+ /** Constant {@code UNKNOWN_COMMANDLINE} */
public static ErrorMessages UNKNOWN_COMMANDLINE = new ErrorMessages("UNKNOWN_COMMANDLINE");
- /** Constant MACRO_CYCLE */
+ /** Constant {@code MACRO_CYCLE} */
public static ErrorMessages MACRO_CYCLE = new ErrorMessages("MACRO_CYCLE");
- /** Constant MACRO_DEF_MISSING */
+ /** Constant {@code MACRO_DEF_MISSING} */
public static ErrorMessages MACRO_DEF_MISSING = new ErrorMessages("MACRO_DEF_MISSING");
- /** Constant PARSING_TOOK */
+ /** Constant {@code PARSING_TOOK} */
public static ErrorMessages PARSING_TOOK = new ErrorMessages("PARSING_TOOK");
- /** Constant NFA_TOOK */
+ /** Constant {@code NFA_TOOK} */
public static ErrorMessages NFA_TOOK = new ErrorMessages("NFA_TOOK");
- /** Constant LOOKAHEAD_NEEDS_ACTION */
+ /** Constant {@code LOOKAHEAD_NEEDS_ACTION} */
public static ErrorMessages LOOKAHEAD_NEEDS_ACTION = new ErrorMessages("LOOKAHEAD_NEEDS_ACTION");
- /** Constant EMPTY_MATCH */
+ /** Constant {@code EMPTY_MATCH} */
public static ErrorMessages EMPTY_MATCH = new ErrorMessages("EMPTY_MATCH");
- /** Constant EMPTY_MATCH_LOOK */
+ /** Constant {@code EMPTY_MATCH_LOOK} */
public static ErrorMessages EMPTY_MATCH_LOOK = new ErrorMessages("EMPTY_MATCH_LOOK");
- /** Constant CTOR_ARG */
+ /** Constant {@code CTOR_ARG} */
public static ErrorMessages CTOR_ARG = new ErrorMessages("CTOR_ARG");
- /** Constant CTOR_DEBUG */
+ /** Constant {@code CTOR_DEBUG} */
public static ErrorMessages CTOR_DEBUG = new ErrorMessages("CTOR_DEBUG");
- /** Constant INT_AND_TYPE */
+ /** Constant {@code INT_AND_TYPE} */
public static ErrorMessages INT_AND_TYPE = new ErrorMessages("INT_AND_TYPE");
- /** Constant UNSUPPORTED_UNICODE_VERSION */
+ /** Constant {@code UNSUPPORTED_UNICODE_VERSION} */
public static ErrorMessages UNSUPPORTED_UNICODE_VERSION =
new ErrorMessages("UNSUPPORTED_UNICODE_VERSION");
- /** Constant UNSUPPORTED_UNICODE_VERSION_SUPPORTED_ARE */
+ /** Constant {@code UNSUPPORTED_UNICODE_VERSION_SUPPORTED_ARE} */
public static ErrorMessages UNSUPPORTED_UNICODE_VERSION_SUPPORTED_ARE =
new ErrorMessages("UNSUPPORTED_UNICODE_VERSION_SUPPORTED_ARE");
- /** Constant INVALID_UNICODE_PROPERTY */
+ /** Constant {@code INVALID_UNICODE_PROPERTY} */
public static ErrorMessages INVALID_UNICODE_PROPERTY =
new ErrorMessages("INVALID_UNICODE_PROPERTY");
- /** Constant DOT_BAR_NEWLINE_DOES_NOT_MATCH_ALL_CHARS */
+ /** Constant {@code DOT_BAR_NEWLINE_DOES_NOT_MATCH_ALL_CHARS} */
public static ErrorMessages DOT_BAR_NEWLINE_DOES_NOT_MATCH_ALL_CHARS =
new ErrorMessages("DOT_BAR_NEWLINE_DOES_NOT_MATCH_ALL_CHARS");
- /** Constant PROPS_ARG_REQUIRES_UNICODE_VERSION */
+ /** Constant {@code PROPS_ARG_REQUIRES_UNICODE_VERSION} */
public static ErrorMessages PROPS_ARG_REQUIRES_UNICODE_VERSION =
new ErrorMessages("PROPS_ARG_REQUIRES_UNICODE_VERSION");
- /** Constant IMPOSSIBLE_CHARCLASS_RANGE */
+ /** Constant {@code IMPOSSIBLE_CHARCLASS_RANGE} */
public static ErrorMessages IMPOSSIBLE_CHARCLASS_RANGE =
new ErrorMessages("IMPOSSIBLE_CHARCLASS_RANGE");
- /** Constant CODEPOINT_OUT_OF_RANGE */
+ /** Constant {@code CODEPOINT_OUT_OF_RANGE} */
public static ErrorMessages CODEPOINT_OUT_OF_RANGE = new ErrorMessages("CODEPOINT_OUT_OF_RANGE");
- /** Constant NO_ENCODING */
+ /** Constant {@code NO_ENCODING} */
public static ErrorMessages NO_ENCODING = new ErrorMessages("NO_ENCODING");
- /** Constant CHARSET_NOT_SUPPORTED */
+ /** Constant {@code CHARSET_NOT_SUPPORTED} */
public static ErrorMessages CHARSET_NOT_SUPPORTED = new ErrorMessages("CHARSET_NOT_SUPPORTED");
}
diff --git a/jflex/src/main/java/jflex/IntCharSet.java b/jflex/src/main/java/jflex/IntCharSet.java
index 313fa690d..ff99c6f7b 100644
--- a/jflex/src/main/java/jflex/IntCharSet.java
+++ b/jflex/src/main/java/jflex/IntCharSet.java
@@ -11,45 +11,35 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import jflex.unicode.UnicodeProperties;
/**
- * CharSet implemented with intervals
- *
- *
[fixme: optimizations possible]
+ * CharSet implemented with intervals.
*
* @author Gerwin Klein
+ * @author Régis Décamps
* @version JFlex 1.7.1-SNAPSHOT
*/
+// FIXME: optimizations possible
public final class IntCharSet {
private static final boolean DEBUG = false;
/* invariant: all intervals are disjoint, ordered */
- private List intervals;
+ private List intervals = new ArrayList<>();
private int pos;
- /** Constructor for IntCharSet. */
- public IntCharSet() {
- this.intervals = new ArrayList<>();
- }
+ /** Creates an empty char set. */
+ public IntCharSet() {}
- /**
- * Constructor for IntCharSet.
- *
- * @param c a int.
- */
+ /** Creates a char set that contains only the given character. */
public IntCharSet(int c) {
this(new Interval(c, c));
}
- /**
- * Constructor for IntCharSet.
- *
- * @param interval a {@link jflex.Interval} object.
- */
+ /** Creates a charset that contains only one interval. */
public IntCharSet(Interval interval) {
- this();
intervals.add(interval);
}
@@ -216,10 +206,24 @@ public boolean contains(int singleChar) {
*
*
o instanceof Interval
*/
+ @Override
public boolean equals(Object o) {
+ if (!(o instanceof IntCharSet)) {
+ return false;
+ }
IntCharSet set = (IntCharSet) o;
- return intervals.equals(set.intervals);
+ return Objects.equals(intervals, set.intervals);
+ }
+
+ @Override
+ public int hashCode() {
+ int h = 1;
+ for (Interval interval : intervals) {
+ h *= 1000003;
+ h ^= interval.hashCode();
+ }
+ return h;
}
private int min(int a, int b) {
diff --git a/jflex/src/main/java/jflex/Interval.java b/jflex/src/main/java/jflex/Interval.java
index 652d6b82c..cb8861811 100644
--- a/jflex/src/main/java/jflex/Interval.java
+++ b/jflex/src/main/java/jflex/Interval.java
@@ -13,15 +13,18 @@
* An interval of characters with basic operations.
*
* @author Gerwin Klein
+ * @author Régis Décamps
* @version JFlex 1.7.1-SNAPSHOT
*/
public final class Interval {
- /* start and end of the interval */
- public int start, end;
+ /** Start of the interval. */
+ public int start;
+ /** End of the interval. */
+ public int end;
/**
- * Construct a new interval from start to end.
+ * Construct a new interval from {@code start
to end}.
*
* @param start first character the interval should contain
* @param end last character the interval should contain
@@ -31,28 +34,23 @@ public Interval(int start, int end) {
this.end = end;
}
- /**
- * Copy constructor.
- *
- * @param other a {@link jflex.Interval} object.
- */
public Interval(Interval other) {
this.start = other.start;
this.end = other.end;
}
/**
- * Return true iff point is contained in this interval.
+ * Returns {@code true} iff {@code point} is contained in this interval.
*
* @param point the character to check
- * @return whether the codepoint is contained in the interval.
+ * @return whether the code point is contained in the interval.
*/
public boolean contains(int point) {
return start <= point && end >= point;
}
/**
- * Return true iff this interval completely contains the other one.
+ * Return {@code true} iff this interval completely contains the other one.
*
* @param other the other interval
* @return whether this interval completely contains the other one.
@@ -61,11 +59,8 @@ public boolean contains(Interval other) {
return this.start <= other.start && this.end >= other.end;
}
- /**
- * {@inheritDoc}
- *
- *
Return true if o is an interval with the same borders.
- */
+ /** Returns {@code true} if {@code o} is an interval with the same borders. */
+ @Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Interval)) return false;
@@ -74,6 +69,16 @@ public boolean equals(Object o) {
return other.start == this.start && other.end == this.end;
}
+ @Override
+ public int hashCode() {
+ int h = 1;
+ h *= 1000003;
+ h ^= start;
+ h *= 1000003;
+ h ^= end;
+ return h;
+ }
+
/**
* Set a new last character
*
@@ -99,15 +104,15 @@ public void setStart(int start) {
*/
private static boolean isPrintable(int c) {
// fixme: should make unicode test here
- return c > 31 && c < 127;
+ return 31 < c && c < 127;
}
/**
- * Get a String representation of this interval.
+ * Returns a String representation of this interval.
*
- * @return a string "[start-end]" or "[start]" (if there is only one
- * character in the interval) where start and end are either a
- * number (the character code) or something of the from 'a'.
+ * @return a string "{@code [start-end]}" or "{@code [start]}" (if there is only one character in
+ * the interval) where {@code start} and {@code end} are either a number (the character code)
+ * or something of the from {@code 'a'}.
*/
public String toString() {
StringBuilder result = new StringBuilder("[");
diff --git a/jflex/src/main/java/jflex/LexGenerator.java b/jflex/src/main/java/jflex/LexGenerator.java
new file mode 100644
index 000000000..6d5eeb4f8
--- /dev/null
+++ b/jflex/src/main/java/jflex/LexGenerator.java
@@ -0,0 +1,132 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * JFlex 1.7.1-SNAPSHOT *
+ * Copyright (C) 1998-2018 Gerwin Klein *
+ * All rights reserved. *
+ * *
+ * License: BSD *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+package jflex;
+
+import static jflex.Options.encoding;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+/**
+ * This is the generator of JFlex, controlling the scanner generation process.
+ *
+ * @author Gerwin Klein
+ * @author Régis Décamps
+ * @version JFlex 1.7.1-SNAPSHOT
+ */
+public class LexGenerator {
+
+ /** JFlex version */
+ public static final String VERSION = "1.7.1-SNAPSHOT"; // $NON-NLS-1$
+
+ /**
+ * Generates a scanner for the specified input file.
+ *
+ * @param inputFile a file containing a lexical specification to generate a scanner for.
+ * @return the file name of the generated Java sources.
+ */
+ public static String generate(File inputFile) {
+
+ Out.resetCounters();
+
+ Timer totalTime = new Timer();
+ Timer time = new Timer();
+
+ LexScan scanner = null;
+ LexParse parser = null;
+ Reader inputReader = null;
+
+ totalTime.start();
+
+ try {
+ Out.println(ErrorMessages.READING, inputFile.toString());
+ inputReader =
+ new InputStreamReader(Files.newInputStream(Paths.get(inputFile.toString())), encoding);
+ scanner = new LexScan(inputReader);
+ scanner.setFile(inputFile);
+ parser = new LexParse(scanner);
+ } catch (IOException e) {
+ Out.error(ErrorMessages.CANNOT_OPEN, inputFile.toString());
+ throw new GeneratorException();
+ }
+
+ try {
+ NFA nfa = (NFA) parser.parse().value;
+
+ Out.checkErrors();
+
+ if (Options.dump) Out.dump(ErrorMessages.get(ErrorMessages.NFA_IS) + Out.NL + nfa + Out.NL);
+
+ if (Options.dot) nfa.writeDot(Emitter.normalize("nfa.dot", null)); // $NON-NLS-1$
+
+ Out.println(ErrorMessages.NFA_STATES, nfa.numStates);
+
+ time.start();
+ DFA dfa = nfa.getDFA();
+ time.stop();
+ Out.time(ErrorMessages.DFA_TOOK, time);
+
+ dfa.checkActions(scanner, parser);
+
+ nfa = null;
+
+ if (Options.dump) Out.dump(ErrorMessages.get(ErrorMessages.DFA_IS) + Out.NL + dfa + Out.NL);
+
+ if (Options.dot) dfa.writeDot(Emitter.normalize("dfa-big.dot", null)); // $NON-NLS-1$
+
+ Out.checkErrors();
+
+ time.start();
+ dfa.minimize();
+ time.stop();
+
+ Out.time(ErrorMessages.MIN_TOOK, time);
+
+ if (Options.dump) Out.dump(ErrorMessages.get(ErrorMessages.MIN_DFA_IS) + Out.NL + dfa);
+
+ if (Options.dot) dfa.writeDot(Emitter.normalize("dfa-min.dot", null)); // $NON-NLS-1$
+
+ time.start();
+
+ Emitter emitter = new Emitter(inputFile, parser, dfa);
+ emitter.emit();
+
+ time.stop();
+
+ Out.time(ErrorMessages.WRITE_TOOK, time);
+
+ totalTime.stop();
+
+ Out.time(ErrorMessages.TOTAL_TIME, totalTime);
+ return emitter.outputFileName;
+ } catch (ScannerException e) {
+ Out.error(e.file, e.message, e.line, e.column);
+ throw new GeneratorException();
+ } catch (MacroException e) {
+ Out.error(e.getMessage());
+ throw new GeneratorException();
+ } catch (IOException e) {
+ Out.error(ErrorMessages.IO_ERROR, e.toString());
+ throw new GeneratorException();
+ } catch (OutOfMemoryError e) {
+ Out.error(ErrorMessages.OUT_OF_MEMORY);
+ throw new GeneratorException();
+ } catch (GeneratorException e) {
+ throw new GeneratorException();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new GeneratorException();
+ }
+ }
+}
diff --git a/jflex/src/main/java/jflex/LexicalStates.java b/jflex/src/main/java/jflex/LexicalStates.java
index 1b2b3fa3f..2a268999e 100644
--- a/jflex/src/main/java/jflex/LexicalStates.java
+++ b/jflex/src/main/java/jflex/LexicalStates.java
@@ -54,8 +54,7 @@ public void insert(String name, boolean is_inclusive) {
}
/**
- * Returns the number (code) of a declared state, null if no such state has been
- * declared.
+ * Returns the number (code) of a declared state, {@code null} if no such state has been declared.
*
* @param name a {@link java.lang.String} object.
* @return a {@link java.lang.Integer} object.
diff --git a/jflex/src/main/java/jflex/Macros.java b/jflex/src/main/java/jflex/Macros.java
index 29f3f503a..dee9e467e 100644
--- a/jflex/src/main/java/jflex/Macros.java
+++ b/jflex/src/main/java/jflex/Macros.java
@@ -9,10 +9,14 @@
package jflex;
+import static jflex.ErrorMessages.MACRO_CYCLE;
+import static jflex.ErrorMessages.get;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* Symbol table and expander for macros.
@@ -41,7 +45,7 @@ public Macros() {
*
* @param name the name of the new macro
* @param definition the definition of the new macro
- * @return true, iff the macro name has not been stored before.
+ * @return {@code true}, iff the macro name has not been stored before.
*/
public boolean insert(String name, RegExp definition) {
@@ -60,7 +64,7 @@ public boolean insert(String name, RegExp definition) {
/**
* Marks a macro as used.
*
- * @return true, iff the macro name has been stored before.
+ * @return {@code true}, iff the macro name has been stored before.
* @param name a {@link java.lang.String} object.
*/
public boolean markUsed(String name) {
@@ -70,7 +74,7 @@ public boolean markUsed(String name) {
/**
* Tests if a macro has been used.
*
- * @return true, iff the macro has been used in a regular expression.
+ * @return {@code true}, iff the macro has been used in a regular expression.
* @param name a {@link java.lang.String} object.
*/
public boolean isUsed(String name) {
@@ -101,8 +105,8 @@ public List unused() {
* one, that doesn't contain any macro usages (expand() called before).
*
* @param name the name of the macro
- * @return the definition of the macro, null if no macro with the specified name has
- * been stored.
+ * @return the definition of the macro, {@code null} if no macro with the specified name has been
+ * stored.
* @see jflex.Macros#expand
*/
public RegExp getDefinition(String name) {
@@ -156,8 +160,7 @@ private RegExp expandMacro(String name, RegExp definition) throws MacroException
case sym.MACROUSE:
String usename = (String) ((RegExp1) definition).content;
- if (name.equals(usename))
- throw new MacroException(ErrorMessages.get(ErrorMessages.MACRO_CYCLE, name));
+ if (Objects.equals(name, usename)) throw new MacroException(get(MACRO_CYCLE, name));
RegExp usedef = getDefinition(usename);
diff --git a/jflex/src/main/java/jflex/Main.java b/jflex/src/main/java/jflex/Main.java
index 87a7e4479..7ea79a449 100644
--- a/jflex/src/main/java/jflex/Main.java
+++ b/jflex/src/main/java/jflex/Main.java
@@ -9,16 +9,17 @@
package jflex;
+import static jflex.ErrorMessages.NO_ENCODING;
+import static jflex.Options.setEncoding;
+import static jflex.Options.unused_warning;
+import static jflex.Out.error;
+
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
@@ -29,114 +30,17 @@
import jflex.unicode.UnicodeProperties;
/**
- * This is the main class of JFlex controlling the scanner generation process. It is responsible for
- * parsing the commandline, getting input files, starting up the GUI if necessary, etc.
+ * This is the command-line interface.
+ *
+ *
It is responsible for parsing the commandline, getting input files, starting up the GUI if
+ * necessary, etc. and invokes {@link LexGenerator} accordingly.
*
* @author Gerwin Klein
+ * @author Régis Décamps
* @version JFlex 1.7.1-SNAPSHOT
*/
public class Main {
- /** JFlex version */
- public static final String version = "1.7.1-SNAPSHOT"; // $NON-NLS-1$
-
- /**
- * Generates a scanner for the specified input file.
- *
- * @param inputFile a file containing a lexical specification to generate a scanner for.
- */
- public static void generate(File inputFile) {
-
- Out.resetCounters();
-
- Timer totalTime = new Timer();
- Timer time = new Timer();
-
- LexScan scanner = null;
- LexParse parser = null;
- Reader inputReader = null;
-
- totalTime.start();
-
- try {
- Out.println(ErrorMessages.READING, inputFile.toString());
- inputReader = new InputStreamReader(new FileInputStream(inputFile), Options.encoding);
- scanner = new LexScan(inputReader);
- scanner.setFile(inputFile);
- parser = new LexParse(scanner);
- } catch (FileNotFoundException e) {
- Out.error(ErrorMessages.CANNOT_OPEN, inputFile.toString());
- throw new GeneratorException();
- }
-
- try {
- NFA nfa = (NFA) parser.parse().value;
-
- Out.checkErrors();
-
- if (Options.dump) Out.dump(ErrorMessages.get(ErrorMessages.NFA_IS) + Out.NL + nfa + Out.NL);
-
- if (Options.dot) nfa.writeDot(Emitter.normalize("nfa.dot", null)); // $NON-NLS-1$
-
- Out.println(ErrorMessages.NFA_STATES, nfa.numStates);
-
- time.start();
- DFA dfa = nfa.getDFA();
- time.stop();
- Out.time(ErrorMessages.DFA_TOOK, time);
-
- dfa.checkActions(scanner, parser);
-
- nfa = null;
-
- if (Options.dump) Out.dump(ErrorMessages.get(ErrorMessages.DFA_IS) + Out.NL + dfa + Out.NL);
-
- if (Options.dot) dfa.writeDot(Emitter.normalize("dfa-big.dot", null)); // $NON-NLS-1$
-
- Out.checkErrors();
-
- time.start();
- dfa.minimize();
- time.stop();
-
- Out.time(ErrorMessages.MIN_TOOK, time);
-
- if (Options.dump) Out.dump(ErrorMessages.get(ErrorMessages.MIN_DFA_IS) + Out.NL + dfa);
-
- if (Options.dot) dfa.writeDot(Emitter.normalize("dfa-min.dot", null)); // $NON-NLS-1$
-
- time.start();
-
- Emitter e = new Emitter(inputFile, parser, dfa);
- e.emit();
-
- time.stop();
-
- Out.time(ErrorMessages.WRITE_TOOK, time);
-
- totalTime.stop();
-
- Out.time(ErrorMessages.TOTAL_TIME, totalTime);
- } catch (ScannerException e) {
- Out.error(e.file, e.message, e.line, e.column);
- throw new GeneratorException();
- } catch (MacroException e) {
- Out.error(e.getMessage());
- throw new GeneratorException();
- } catch (IOException e) {
- Out.error(ErrorMessages.IO_ERROR, e.toString());
- throw new GeneratorException();
- } catch (OutOfMemoryError e) {
- Out.error(ErrorMessages.OUT_OF_MEMORY);
- throw new GeneratorException();
- } catch (GeneratorException e) {
- throw new GeneratorException();
- } catch (Exception e) {
- e.printStackTrace();
- throw new GeneratorException();
- }
- }
-
/**
* parseOptions.
*
@@ -144,12 +48,13 @@ public static void generate(File inputFile) {
* @return a {@link java.util.List} object.
* @throws jflex.SilentExit if any.
*/
- public static List parseOptions(String argv[]) throws SilentExit {
+ private static List parseOptions(String argv[]) throws SilentExit {
List files = new ArrayList<>();
for (int i = 0; i < argv.length; i++) {
- if (argv[i].equals("-d") || argv[i].equals("--outdir")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "-d")
+ || Objects.equals(argv[i], "--outdir")) { // $NON-NLS-1$ //$NON-NLS-2$
if (++i >= argv.length) {
Out.error(ErrorMessages.NO_DIRECTORY);
throw new GeneratorException();
@@ -158,7 +63,8 @@ public static List parseOptions(String argv[]) throws SilentExit {
continue;
}
- if (argv[i].equals("--skel") || argv[i].equals("-skel")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--skel")
+ || Objects.equals(argv[i], "-skel")) { // $NON-NLS-1$ //$NON-NLS-2$
if (++i >= argv.length) {
Out.error(ErrorMessages.NO_SKEL_FILE);
throw new GeneratorException();
@@ -168,104 +74,113 @@ public static List parseOptions(String argv[]) throws SilentExit {
continue;
}
- if (argv[i].equals("--encoding")) {
+ if (Objects.equals(argv[i], "--encoding")) {
if (++i >= argv.length) {
- Out.error(ErrorMessages.NO_ENCODING);
+ error(NO_ENCODING);
throw new GeneratorException();
}
- Options.setEncoding(argv[i]);
+ setEncoding(argv[i]);
continue;
}
- if (argv[i].equals("-jlex") || argv[i].equals("--jlex")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "-jlex")
+ || Objects.equals(argv[i], "--jlex")) { // $NON-NLS-1$ //$NON-NLS-2$
Options.jlex = true;
continue;
}
- if (argv[i].equals("-v")
- || argv[i].equals("--verbose")
- || argv[i].equals("-verbose")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (Objects.equals(argv[i], "-v")
+ || Objects.equals(argv[i], "--verbose")
+ || Objects.equals(argv[i], "-verbose")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Options.verbose = true;
Options.progress = true;
Options.unused_warning = true;
continue;
}
- if (argv[i].equals("-q")
- || argv[i].equals("--quiet")
- || argv[i].equals("-quiet")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (Objects.equals(argv[i], "-q")
+ || Objects.equals(argv[i], "--quiet")
+ || Objects.equals(argv[i], "-quiet")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Options.verbose = false;
Options.progress = false;
Options.unused_warning = false;
continue;
}
- if (argv[i].equals("--warn-unused")) { // $NON-NLS-1$
- Options.unused_warning = true;
+ if (Objects.equals(argv[i], "--warn-unused")) { // $NON-NLS-1$
+ unused_warning = true;
continue;
}
- if (argv[i].equals("--no-warn-unused")) { // $NON-NLS-1$
- Options.unused_warning = false;
+ if (Objects.equals(argv[i], "--no-warn-unused")) { // $NON-NLS-1$
+ unused_warning = false;
continue;
}
- if (argv[i].equals("--dump") || argv[i].equals("-dump")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--dump")
+ || Objects.equals(argv[i], "-dump")) { // $NON-NLS-1$ //$NON-NLS-2$
Options.dump = true;
continue;
}
- if (argv[i].equals("--time") || argv[i].equals("-time")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--time")
+ || Objects.equals(argv[i], "-time")) { // $NON-NLS-1$ //$NON-NLS-2$
Options.time = true;
continue;
}
- if (argv[i].equals("--version") || argv[i].equals("-version")) { // $NON-NLS-1$ //$NON-NLS-2$
- Out.println(ErrorMessages.THIS_IS_JFLEX, version);
+ if (Objects.equals(argv[i], "--version")
+ || Objects.equals(argv[i], "-version")) { // $NON-NLS-1$ //$NON-NLS-2$
+ Out.println(ErrorMessages.THIS_IS_JFLEX, LexGenerator.VERSION);
throw new SilentExit(0);
}
- if (argv[i].equals("--dot") || argv[i].equals("-dot")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--dot")
+ || Objects.equals(argv[i], "-dot")) { // $NON-NLS-1$ //$NON-NLS-2$
Options.dot = true;
continue;
}
- if (argv[i].equals("--help")
- || argv[i].equals("-h")
- || argv[i].equals("/h")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (Objects.equals(argv[i], "--help")
+ || Objects.equals(argv[i], "-h")
+ || Objects.equals(argv[i], "/h")) { // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
printUsage();
throw new SilentExit(0);
}
- if (argv[i].equals("--info") || argv[i].equals("-info")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--info")
+ || Objects.equals(argv[i], "-info")) { // $NON-NLS-1$ //$NON-NLS-2$
Out.printSystemInfo();
throw new SilentExit(0);
}
- if (argv[i].equals("--nomin") || argv[i].equals("-nomin")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--nomin")
+ || Objects.equals(argv[i], "-nomin")) { // $NON-NLS-1$ //$NON-NLS-2$
Options.no_minimize = true;
continue;
}
- if (argv[i].equals("--pack") || argv[i].equals("-pack")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--pack")
+ || Objects.equals(argv[i], "-pack")) { // $NON-NLS-1$ //$NON-NLS-2$
/* no-op - pack is the only generation method */
continue;
}
- if (argv[i].equals("--nobak") || argv[i].equals("-nobak")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--nobak")
+ || Objects.equals(argv[i], "-nobak")) { // $NON-NLS-1$ //$NON-NLS-2$
Options.no_backup = true;
continue;
}
- if (argv[i].equals("--legacydot")
- || argv[i].equals("-legacydot")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--legacydot")
+ || Objects.equals(argv[i], "-legacydot")) { // $NON-NLS-1$ //$NON-NLS-2$
Options.legacy_dot = true;
continue;
}
- if (argv[i].equals("--uniprops")
- || argv[i].equals("-uniprops")) { // $NON-NLS-1$ //$NON-NLS-2$
+ if (Objects.equals(argv[i], "--uniprops")
+ || Objects.equals(argv[i], "-uniprops")) { // $NON-NLS-1$ //$NON-NLS-2$
if (++i >= argv.length) {
Out.error(
ErrorMessages.PROPS_ARG_REQUIRES_UNICODE_VERSION, UnicodeProperties.UNICODE_VERSIONS);
@@ -333,7 +248,7 @@ private static void printUnicodePropertyValuesAndAliases(String unicodeVersion)
for (String value : propertyValues) {
propertyValuesToAliases.put(value, new TreeSet());
}
- for (int i = 0; i < propertyValueAliases.length; i += 2) {
+ for (int i = 0; i < propertyValueAliases.length - 1; i += 2) {
String alias = propertyValueAliases[i];
String value = propertyValueAliases[i + 1];
SortedSet aliases = propertyValuesToAliases.get(value);
@@ -357,7 +272,7 @@ private static void printUnicodePropertyValuesAndAliases(String unicodeVersion)
}
/** Prints the cli usage on stdout. */
- public static void printUsage() {
+ private static void printUsage() {
Out.println(""); // $NON-NLS-1$
Out.println("Usage: jflex ");
Out.println("");
@@ -384,7 +299,7 @@ public static void printUsage() {
Out.println("--help");
Out.println("-h print this message");
Out.println("");
- Out.println(ErrorMessages.THIS_IS_JFLEX, version);
+ Out.println(ErrorMessages.THIS_IS_JFLEX, LexGenerator.VERSION);
Out.println("Have a nice day!");
}
@@ -398,15 +313,17 @@ public static void generate(String argv[]) throws SilentExit {
List files = parseOptions(argv);
if (files.size() > 0) {
- for (File file : files) generate(file);
+ for (File file : files) {
+ LexGenerator.generate(file);
+ }
} else {
new MainFrame();
}
}
/**
- * Starts the generation process with the files in argv or pops up a window to choose
- * a file, when argv doesn't have any file entries.
+ * Starts the generation process with the files in {@code argv} or pops up a window to choose a
+ * file, when {@code argv} doesn't have any file entries.
*
* @param argv the commandline.
*/
@@ -420,4 +337,7 @@ public static void main(String argv[]) {
System.exit(e.exitCode());
}
}
+
+ // Only CLI, not meant for instanciation.
+ private Main() {}
}
diff --git a/jflex/src/main/java/jflex/NFA.java b/jflex/src/main/java/jflex/NFA.java
index 02e114e5a..30f51ad41 100644
--- a/jflex/src/main/java/jflex/NFA.java
+++ b/jflex/src/main/java/jflex/NFA.java
@@ -16,6 +16,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* Non-deterministic finite automata representation in JFlex.
@@ -312,7 +313,7 @@ public void addEpsilonTransition(int start, int dest) {
}
/**
- * Returns true, iff the specified set of states contains a final state.
+ * Returns {@code true}, iff the specified set of states contains a final state.
*
* @param set the set of states that is tested for final states.
*/
@@ -325,7 +326,7 @@ private boolean containsFinal(StateSet set) {
}
/**
- * Returns true, iff the specified set of states contains a pushback-state.
+ * Returns {@code true}, iff the specified set of states contains a pushback-state.
*
* @param set the set of states that is tested for pushback-states. private boolean
* containsPushback(StateSet set) { states.reset(set);
@@ -412,12 +413,12 @@ private void epsilonFill() {
}
/**
- * Calculates the set of states that can be reached from another set of states start
- * with an specified input character input
+ * Calculates the set of states that can be reached from another set of states {@code start} with
+ * an specified input character {@code input}
*
* @param start the set of states to start from
* @param input the input character for which to search the next states
- * @return the set of states that are reached from start via input
+ * @return the set of states that are reached from {@code start
via input}
*/
private StateSet DFAEdge(StateSet start, int input) {
// Out.debug(String.format("Calculating DFAEdge for state set "+start+" and input U+04X"),
@@ -574,7 +575,7 @@ public String toString() {
if (isFinal[i]) {
result.append("[FINAL");
String l = action[i].lookString();
- if (!l.equals("")) {
+ if (!Objects.equals(l, "")) {
result.append(", ");
result.append(l);
}
diff --git a/jflex/src/main/java/jflex/Options.java b/jflex/src/main/java/jflex/Options.java
index 369008242..5635267c1 100644
--- a/jflex/src/main/java/jflex/Options.java
+++ b/jflex/src/main/java/jflex/Options.java
@@ -25,6 +25,12 @@ public class Options {
/** output directory */
private static File directory;
+ /**
+ * The root source directory.
+ *
+ *
In a maven project, this is the directory that contains {@code src} and {@code target}.
+ */
+ private static File rootDirectory;
/** strict JLex compatibility */
public static boolean jlex;
/** don't run minimization algorithm if this is true */
@@ -91,6 +97,18 @@ public static void setDir(File d) {
directory = d;
}
+ /**
+ * Returns the root directory that contains source code. This is the java working (from system
+ * property {@code user.dir}) by default.
+ */
+ public static File getRootDirectory() {
+ return rootDirectory;
+ }
+
+ public static void setRootDirectory(File rootDir) {
+ rootDirectory = rootDir;
+ }
+
/** Sets encoding for input files, and check availability of encoding on this JVM. */
public static void setEncoding(String encodingName) {
if (Charset.isSupported(encodingName)) {
@@ -104,6 +122,8 @@ public static void setEncoding(String encodingName) {
/** Sets all options back to default values. */
public static void setDefaults() {
directory = null;
+ // System.getProperty("user.dir"), the directory where java was run from.
+ rootDirectory = new File("");
jlex = false;
no_minimize = false;
no_backup = false;
diff --git a/jflex/src/main/java/jflex/Out.java b/jflex/src/main/java/jflex/Out.java
index b786cc2d7..be6a69b8c 100644
--- a/jflex/src/main/java/jflex/Out.java
+++ b/jflex/src/main/java/jflex/Out.java
@@ -46,7 +46,7 @@ public final class Out {
private static StdOutWriter out = new StdOutWriter();
/**
- * Switches to GUI mode if text is not null
+ * Switches to GUI mode if {@code text
is not null}
*
* @param text the message TextArea of the JFlex GUI
*/
@@ -135,8 +135,8 @@ public static void print(String message) {
/**
* Dump debug information to System.out
*
- *
Use like this if (Out.DEBUG) Out.debug(message) to save performance during
- * normal operation (when DEBUG is turned off).
+ *
Use like this {@code if (Out.DEBUG) Out.debug(message)} to save performance during normal
+ * operation (when DEBUG is turned off).
*
* @param message a {@link java.lang.String} object.
*/
@@ -403,7 +403,7 @@ public static void printSystemInfo() {
err("OS version: " + System.getProperty("os.version"));
err("Encoding: " + System.getProperty("file.encoding"));
err("Unicode versions: " + UnicodeProperties.UNICODE_VERSIONS);
- err("JFlex version: " + Main.version);
+ err("JFlex version: " + LexGenerator.VERSION);
}
/**
diff --git a/jflex/src/main/java/jflex/PackEmitter.java b/jflex/src/main/java/jflex/PackEmitter.java
index 438ac389e..95e2b37e2 100644
--- a/jflex/src/main/java/jflex/PackEmitter.java
+++ b/jflex/src/main/java/jflex/PackEmitter.java
@@ -12,13 +12,13 @@
import java.util.Locale;
/**
- * Encodes int arrays as strings.
+ * Encodes {@code int} arrays as strings.
*
*
Also splits up strings when longer than 64K in UTF8 encoding. Subclasses emit unpacking code.
*
- *
Usage protocol: p.emitInit();
- * for each data: p.emitData(data);
- * p.emitUnpack();
+ *
Usage protocol: {@code p.emitInit();}
+ * {@code for each data: p.emitData(data);}
+ * {@code p.emitUnpack();}
*
* @author Gerwin Klein
* @version JFlex 1.7.1-SNAPSHOT
@@ -64,7 +64,7 @@ public PackEmitter(String name) {
/**
* Convert array name into all uppercase internal scanner constant name.
*
- * @return name as a internal constant name.
+ * @return {@code name} as a internal constant name.
* @see PackEmitter#name
*/
protected String constName() {
@@ -156,7 +156,7 @@ protected void nl() {
}
/**
- * Append a unicode/octal escaped character to out buffer.
+ * Append a unicode/octal escaped character to {@code out} buffer.
*
* @param c the character to append
*/
diff --git a/jflex/src/main/java/jflex/RegExp.java b/jflex/src/main/java/jflex/RegExp.java
index b64acaec9..649c781a1 100644
--- a/jflex/src/main/java/jflex/RegExp.java
+++ b/jflex/src/main/java/jflex/RegExp.java
@@ -248,9 +248,9 @@ public final RegExp resolveTilde(Macros macros) {
}
/**
- * Returns a regexp that matches any character: [^]
+ * Returns a regexp that matches any character: {@code [^]}
*
- * @return the regexp for [^]
+ * @return the regexp for {@code [^]}
*/
public RegExp anyChar() {
// FIXME: there is some code duplication here with the parser
diff --git a/jflex/src/main/java/jflex/RegExps.java b/jflex/src/main/java/jflex/RegExps.java
index d74b2cd48..9288d92a3 100644
--- a/jflex/src/main/java/jflex/RegExps.java
+++ b/jflex/src/main/java/jflex/RegExps.java
@@ -168,7 +168,7 @@ public boolean isEOF(int num) {
}
/**
- * Getter for the field states.
+ * Getter for the field {@code states}.
*
* @param num a int.
* @return a {@link java.util.List} object.
diff --git a/jflex/src/main/java/jflex/Skeleton.java b/jflex/src/main/java/jflex/Skeleton.java
index 04875f39d..866f3e618 100644
--- a/jflex/src/main/java/jflex/Skeleton.java
+++ b/jflex/src/main/java/jflex/Skeleton.java
@@ -8,13 +8,16 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jflex;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
@@ -25,7 +28,7 @@
* portion of generated code (produced in class Emitter) between every two parts of skeleton code.
*
*
There is a static part (the skeleton code) and state based iterator part to this class. The
- * iterator part is used to emit consecutive skeleton sections to some PrintWriter.
+ * iterator part is used to emit consecutive skeleton sections to some {@code PrintWriter}.
*
* @see jflex.Emitter
* @author Gerwin Klein
@@ -99,8 +102,8 @@ public static void readSkelFile(File skeletonFile) {
Out.println(ErrorMessages.READING_SKEL, skeletonFile.toString());
- try {
- BufferedReader reader = new BufferedReader(new FileReader(skeletonFile));
+ try (BufferedReader reader =
+ Files.newBufferedReader(Paths.get(skeletonFile.toString()), UTF_8)) {
readSkel(reader);
} catch (IOException e) {
Out.error(ErrorMessages.SKEL_IO_ERROR);
@@ -186,8 +189,7 @@ public static void readDefault() {
throw new GeneratorException();
}
- try {
- InputStreamReader reader = new InputStreamReader(url.openStream());
+ try (InputStreamReader reader = new InputStreamReader(url.openStream())) {
readSkel(new BufferedReader(reader));
} catch (IOException e) {
Out.error(ErrorMessages.SKEL_IO_ERROR_DEFAULT);
diff --git a/jflex/src/main/java/jflex/StateSet.java b/jflex/src/main/java/jflex/StateSet.java
index 700b6fa83..cdac34c9e 100644
--- a/jflex/src/main/java/jflex/StateSet.java
+++ b/jflex/src/main/java/jflex/StateSet.java
@@ -20,7 +20,7 @@ public final class StateSet {
private final boolean DEBUG = false;
- /** Constant EMPTY */
+ /** Constant {@code EMPTY} */
public static final StateSet EMPTY = new StateSet();
static final int BITS = 6;
@@ -250,6 +250,9 @@ public boolean containsSet(StateSet set) {
/** {@inheritDoc} */
public boolean equals(Object b) {
+ if (!(b instanceof StateSet)) {
+ return false;
+ }
int i = 0;
int l1, l2;
diff --git a/jflex/src/main/java/jflex/StdOutWriter.java b/jflex/src/main/java/jflex/StdOutWriter.java
index 32b39f581..274fb6baa 100644
--- a/jflex/src/main/java/jflex/StdOutWriter.java
+++ b/jflex/src/main/java/jflex/StdOutWriter.java
@@ -25,7 +25,7 @@ public final class StdOutWriter extends PrintWriter {
private TextArea text;
/**
- * approximation of the current column in the text area for auto wrapping at wrap
+ * approximation of the current column in the text area for auto wrapping at {@code wrap}
* characters
*/
private int col;
diff --git a/jflex/src/main/java/jflex/anttask/JFlexTask.java b/jflex/src/main/java/jflex/anttask/JFlexTask.java
index 979514cbb..8b70bc4b7 100644
--- a/jflex/src/main/java/jflex/anttask/JFlexTask.java
+++ b/jflex/src/main/java/jflex/anttask/JFlexTask.java
@@ -16,7 +16,7 @@
import java.io.LineNumberReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import jflex.Main;
+import jflex.LexGenerator;
import jflex.Options;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
@@ -69,7 +69,7 @@ public void execute() throws BuildException {
File destFile = new File(outputDir, className + ".java");
if (inputFile.lastModified() > destFile.lastModified()) {
- Main.generate(inputFile);
+ LexGenerator.generate(inputFile);
if (!Options.verbose) System.out.println("Generated: " + destFile.getName());
}
} catch (IOException e1) {
@@ -160,7 +160,7 @@ public String getPackage() {
}
/**
- * Getter for the field className.
+ * Getter for the field {@code className}.
*
* @return class name of input file
* @see #findPackageAndClass()
diff --git a/jflex/src/main/java/jflex/gui/GeneratorThread.java b/jflex/src/main/java/jflex/gui/GeneratorThread.java
index 119df4815..40e1e9376 100644
--- a/jflex/src/main/java/jflex/gui/GeneratorThread.java
+++ b/jflex/src/main/java/jflex/gui/GeneratorThread.java
@@ -10,9 +10,10 @@
package jflex.gui;
import java.io.File;
+import java.util.Objects;
import jflex.ErrorMessages;
import jflex.GeneratorException;
-import jflex.Main;
+import jflex.LexGenerator;
import jflex.Options;
import jflex.Out;
@@ -58,10 +59,10 @@ public void run() {
running = true;
setPriority(MIN_PRIORITY);
try {
- if (!outputDir.equals("")) {
+ if (!Objects.equals(outputDir, "")) {
Options.setDir(outputDir);
}
- Main.generate(new File(inputFile));
+ LexGenerator.generate(new File(inputFile));
Out.statistics();
parent.generationFinished(true);
} catch (GeneratorException e) {
diff --git a/jflex/src/main/java/jflex/gui/Handles.java b/jflex/src/main/java/jflex/gui/Handles.java
index 1a4755278..0969036ba 100644
--- a/jflex/src/main/java/jflex/gui/Handles.java
+++ b/jflex/src/main/java/jflex/gui/Handles.java
@@ -17,33 +17,33 @@
*/
public interface Handles {
- /** Constant FILL=0 */
+ /** Constant {@code FILL=0} */
int FILL = 0;
- /** Constant TOP=1 */
+ /** Constant {@code TOP=1} */
int TOP = 1;
- /** Constant TOP_LEFT=TOP */
+ /** Constant {@code TOP_LEFT=TOP} */
int TOP_LEFT = TOP;
- /** Constant TOP_CENTER=2 */
+ /** Constant {@code TOP_CENTER=2} */
int TOP_CENTER = 2;
- /** Constant TOP_RIGHT=3 */
+ /** Constant {@code TOP_RIGHT=3} */
int TOP_RIGHT = 3;
- /** Constant CENTER_LEFT=4 */
+ /** Constant {@code CENTER_LEFT=4} */
int CENTER_LEFT = 4;
- /** Constant CENTER=5 */
+ /** Constant {@code CENTER=5} */
int CENTER = 5;
- /** Constant CENTER_CENTER=CENTER */
+ /** Constant {@code CENTER_CENTER=CENTER} */
int CENTER_CENTER = CENTER;
- /** Constant CENTER_RIGHT=6 */
+ /** Constant {@code CENTER_RIGHT=6} */
int CENTER_RIGHT = 6;
- /** Constant BOTTOM=7 */
+ /** Constant {@code BOTTOM=7} */
int BOTTOM = 7;
- /** Constant BOTTOM_LEFT=BOTTOM */
+ /** Constant {@code BOTTOM_LEFT=BOTTOM} */
int BOTTOM_LEFT = BOTTOM;
- /** Constant BOTTOM_CENTER=8 */
+ /** Constant {@code BOTTOM_CENTER=8} */
int BOTTOM_CENTER = 8;
- /** Constant BOTTOM_RIGHT=9 */
+ /** Constant {@code BOTTOM_RIGHT=9} */
int BOTTOM_RIGHT = 9;
}
diff --git a/jflex/src/main/java/jflex/gui/MainFrame.java b/jflex/src/main/java/jflex/gui/MainFrame.java
index 7dd12986d..9ec5181d4 100644
--- a/jflex/src/main/java/jflex/gui/MainFrame.java
+++ b/jflex/src/main/java/jflex/gui/MainFrame.java
@@ -17,7 +17,7 @@
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
-import jflex.Main;
+import jflex.LexGenerator;
import jflex.Out;
/**
@@ -53,7 +53,7 @@ public final class MainFrame extends Frame implements Handles {
/** Constructor for MainFrame. */
public MainFrame() {
- super("JFlex " + Main.version);
+ super("JFlex " + LexGenerator.VERSION);
buildContent();
addWindowListener(
diff --git a/jflex/src/main/java/jflex/io/FileUtil.java b/jflex/src/main/java/jflex/io/FileUtil.java
new file mode 100644
index 000000000..7390bd591
--- /dev/null
+++ b/jflex/src/main/java/jflex/io/FileUtil.java
@@ -0,0 +1,31 @@
+package jflex.io;
+
+import java.io.File;
+import java.io.IOException;
+
+public class FileUtil {
+
+ /** Returns the path of {@code file} relative to {@code rootDirectory}. */
+ public static String getRelativePath(File rootDirectory, File file) {
+ try {
+ String rootDir = rootDirectory.getCanonicalPath() + File.separator;
+ String f = file.getCanonicalPath();
+ if (f.startsWith(rootDir)) {
+ return f.substring(rootDir.length());
+ }
+ } catch (IOException e) {
+ // fall back to file.getPath()
+ }
+ return file.getPath();
+ }
+
+ /**
+ * Replaces the {@code \} by a {@code /} in the path, because backslash is used as an escape
+ * sequence in Java (e.g. {@code \u1234} is a unicode character.
+ */
+ public static String slashify(String path) {
+ return path.replace('\\', '/');
+ }
+
+ private FileUtil() {} // utility class
+}
diff --git a/jflex/src/main/java/jflex/unicode/UnicodeProperties.java b/jflex/src/main/java/jflex/unicode/UnicodeProperties.java
index 29e104103..07ca5a9bf 100644
--- a/jflex/src/main/java/jflex/unicode/UnicodeProperties.java
+++ b/jflex/src/main/java/jflex/unicode/UnicodeProperties.java
@@ -12,6 +12,7 @@
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -41,11 +42,10 @@
* downloaded from unicode.org.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class UnicodeProperties {
- /** Constant UNICODE_VERSIONS="1.1, 1.1.5, 2, 2.0, 2.0.14, 2.1, 2.1.9,"{trunked} */
+ /** Constant {@code UNICODE_VERSIONS="1.1, 1.1.5, 2, 2.0, 2.0.14, 2.1, 2.1.9,"{trunked}} */
public static final String UNICODE_VERSIONS =
"1.1, 1.1.5, 2, 2.0, 2.0.14, 2.1, 2.1.9, 3, 3.0, 3.0.1, 3.1, 3.1.0, 3.2, 3.2.0, 4, 4.0, 4.0.1, 4.1, 4.1.0, 5, 5.0, 5.0.0, 5.1, 5.1.0, 5.2, 5.2.0, 6, 6.0, 6.0.0, 6.1, 6.1.0, 6.2, 6.2.0, 6.3, 6.3.0, 7, 7.0, 7.0.0, 8, 8.0, 8.0.0, 9, 9.0, 9.0.0";
@@ -159,7 +159,7 @@ private void initCaselessMatches() {
*/
private void init(String version) throws UnsupportedUnicodeVersionException {
- if (version.equals("1.1") || version.equals("1.1.5")) {
+ if (Objects.equals(version, "1.1") || Objects.equals(version, "1.1.5")) {
bind(
Unicode_1_1.propertyValues,
Unicode_1_1.intervals,
@@ -167,7 +167,9 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_1_1.maximumCodePoint,
Unicode_1_1.caselessMatchPartitions,
Unicode_1_1.caselessMatchPartitionSize);
- } else if (version.equals("2") || version.equals("2.0") || version.equals("2.0.14")) {
+ } else if (Objects.equals(version, "2")
+ || Objects.equals(version, "2.0")
+ || Objects.equals(version, "2.0.14")) {
bind(
Unicode_2_0.propertyValues,
Unicode_2_0.intervals,
@@ -175,7 +177,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_2_0.maximumCodePoint,
Unicode_2_0.caselessMatchPartitions,
Unicode_2_0.caselessMatchPartitionSize);
- } else if (version.equals("2.1") || version.equals("2.1.9")) {
+ } else if (Objects.equals(version, "2.1") || Objects.equals(version, "2.1.9")) {
bind(
Unicode_2_1.propertyValues,
Unicode_2_1.intervals,
@@ -183,7 +185,9 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_2_1.maximumCodePoint,
Unicode_2_1.caselessMatchPartitions,
Unicode_2_1.caselessMatchPartitionSize);
- } else if (version.equals("3") || version.equals("3.0") || version.equals("3.0.1")) {
+ } else if (Objects.equals(version, "3")
+ || Objects.equals(version, "3.0")
+ || Objects.equals(version, "3.0.1")) {
bind(
Unicode_3_0.propertyValues,
Unicode_3_0.intervals,
@@ -191,7 +195,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_3_0.maximumCodePoint,
Unicode_3_0.caselessMatchPartitions,
Unicode_3_0.caselessMatchPartitionSize);
- } else if (version.equals("3.1") || version.equals("3.1.0")) {
+ } else if (Objects.equals(version, "3.1") || Objects.equals(version, "3.1.0")) {
bind(
Unicode_3_1.propertyValues,
Unicode_3_1.intervals,
@@ -199,7 +203,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_3_1.maximumCodePoint,
Unicode_3_1.caselessMatchPartitions,
Unicode_3_1.caselessMatchPartitionSize);
- } else if (version.equals("3.2") || version.equals("3.2.0")) {
+ } else if (Objects.equals(version, "3.2") || Objects.equals(version, "3.2.0")) {
bind(
Unicode_3_2.propertyValues,
Unicode_3_2.intervals,
@@ -207,7 +211,9 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_3_2.maximumCodePoint,
Unicode_3_2.caselessMatchPartitions,
Unicode_3_2.caselessMatchPartitionSize);
- } else if (version.equals("4") || version.equals("4.0") || version.equals("4.0.1")) {
+ } else if (Objects.equals(version, "4")
+ || Objects.equals(version, "4.0")
+ || Objects.equals(version, "4.0.1")) {
bind(
Unicode_4_0.propertyValues,
Unicode_4_0.intervals,
@@ -215,7 +221,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_4_0.maximumCodePoint,
Unicode_4_0.caselessMatchPartitions,
Unicode_4_0.caselessMatchPartitionSize);
- } else if (version.equals("4.1") || version.equals("4.1.0")) {
+ } else if (Objects.equals(version, "4.1") || Objects.equals(version, "4.1.0")) {
bind(
Unicode_4_1.propertyValues,
Unicode_4_1.intervals,
@@ -223,7 +229,9 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_4_1.maximumCodePoint,
Unicode_4_1.caselessMatchPartitions,
Unicode_4_1.caselessMatchPartitionSize);
- } else if (version.equals("5") || version.equals("5.0") || version.equals("5.0.0")) {
+ } else if (Objects.equals(version, "5")
+ || Objects.equals(version, "5.0")
+ || Objects.equals(version, "5.0.0")) {
bind(
Unicode_5_0.propertyValues,
Unicode_5_0.intervals,
@@ -231,7 +239,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_5_0.maximumCodePoint,
Unicode_5_0.caselessMatchPartitions,
Unicode_5_0.caselessMatchPartitionSize);
- } else if (version.equals("5.1") || version.equals("5.1.0")) {
+ } else if (Objects.equals(version, "5.1") || Objects.equals(version, "5.1.0")) {
bind(
Unicode_5_1.propertyValues,
Unicode_5_1.intervals,
@@ -239,7 +247,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_5_1.maximumCodePoint,
Unicode_5_1.caselessMatchPartitions,
Unicode_5_1.caselessMatchPartitionSize);
- } else if (version.equals("5.2") || version.equals("5.2.0")) {
+ } else if (Objects.equals(version, "5.2") || Objects.equals(version, "5.2.0")) {
bind(
Unicode_5_2.propertyValues,
Unicode_5_2.intervals,
@@ -247,7 +255,9 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_5_2.maximumCodePoint,
Unicode_5_2.caselessMatchPartitions,
Unicode_5_2.caselessMatchPartitionSize);
- } else if (version.equals("6") || version.equals("6.0") || version.equals("6.0.0")) {
+ } else if (Objects.equals(version, "6")
+ || Objects.equals(version, "6.0")
+ || Objects.equals(version, "6.0.0")) {
bind(
Unicode_6_0.propertyValues,
Unicode_6_0.intervals,
@@ -255,7 +265,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_6_0.maximumCodePoint,
Unicode_6_0.caselessMatchPartitions,
Unicode_6_0.caselessMatchPartitionSize);
- } else if (version.equals("6.1") || version.equals("6.1.0")) {
+ } else if (Objects.equals(version, "6.1") || Objects.equals(version, "6.1.0")) {
bind(
Unicode_6_1.propertyValues,
Unicode_6_1.intervals,
@@ -263,7 +273,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_6_1.maximumCodePoint,
Unicode_6_1.caselessMatchPartitions,
Unicode_6_1.caselessMatchPartitionSize);
- } else if (version.equals("6.2") || version.equals("6.2.0")) {
+ } else if (Objects.equals(version, "6.2") || Objects.equals(version, "6.2.0")) {
bind(
Unicode_6_2.propertyValues,
Unicode_6_2.intervals,
@@ -271,7 +281,7 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_6_2.maximumCodePoint,
Unicode_6_2.caselessMatchPartitions,
Unicode_6_2.caselessMatchPartitionSize);
- } else if (version.equals("6.3") || version.equals("6.3.0")) {
+ } else if (Objects.equals(version, "6.3") || Objects.equals(version, "6.3.0")) {
bind(
Unicode_6_3.propertyValues,
Unicode_6_3.intervals,
@@ -279,7 +289,9 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_6_3.maximumCodePoint,
Unicode_6_3.caselessMatchPartitions,
Unicode_6_3.caselessMatchPartitionSize);
- } else if (version.equals("7") || version.equals("7.0") || version.equals("7.0.0")) {
+ } else if (Objects.equals(version, "7")
+ || Objects.equals(version, "7.0")
+ || Objects.equals(version, "7.0.0")) {
bind(
Unicode_7_0.propertyValues,
Unicode_7_0.intervals,
@@ -287,7 +299,9 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_7_0.maximumCodePoint,
Unicode_7_0.caselessMatchPartitions,
Unicode_7_0.caselessMatchPartitionSize);
- } else if (version.equals("8") || version.equals("8.0") || version.equals("8.0.0")) {
+ } else if (Objects.equals(version, "8")
+ || Objects.equals(version, "8.0")
+ || Objects.equals(version, "8.0.0")) {
bind(
Unicode_8_0.propertyValues,
Unicode_8_0.intervals,
@@ -295,7 +309,9 @@ private void init(String version) throws UnsupportedUnicodeVersionException {
Unicode_8_0.maximumCodePoint,
Unicode_8_0.caselessMatchPartitions,
Unicode_8_0.caselessMatchPartitionSize);
- } else if (version.equals("9") || version.equals("9.0") || version.equals("9.0.0")) {
+ } else if (Objects.equals(version, "9")
+ || Objects.equals(version, "9.0")
+ || Objects.equals(version, "9.0.0")) {
bind(
Unicode_9_0.propertyValues,
Unicode_9_0.intervals,
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_1_1.java b/jflex/src/main/java/jflex/unicode/data/Unicode_1_1.java
index 34d4b462f..b557c22ca 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_1_1.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_1_1.java
@@ -4,12 +4,11 @@
* Unicode_1_1 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_1_1 {
- /** Constant maximumCodePoint=0xffff */
+ /** Constant {@code maximumCodePoint=0xffff} */
public static final int maximumCodePoint = 0xffff;
- /** Constant propertyValues="{alnum, assigned, blank, cc, cn,graph, "{trunked} */
+ /** Constant {@code propertyValues="{alnum, assigned, blank, cc, cn,graph, "{trunked}} */
public static final String[] propertyValues = {
"alnum", "assigned", "blank", "cc", "cn",
"graph", "ll", "lm", "lo", "lu",
@@ -18,7 +17,7 @@ public class Unicode_1_1 {
"sm", "so", "xdigit", "zl", "zp",
"zs"
};
- /** Constant intervals="{// Unicode 1.1 property value: {alnum}"{trunked} */
+ /** Constant {@code intervals="{// Unicode 1.1 property value: {alnum}"{trunked}} */
public static final String[] intervals = {
// Unicode 1.1 property value: {alnum}
"\u0030\u0039"
@@ -2611,10 +2610,10 @@ public class Unicode_1_1 {
// Unicode 1.1 property value: {zs}
"\u0020\u0020" + "\u00a0\u00a0" + "\u2000\u200b" + "\u3000\u3000" + "\ufeff\ufeff"
};
- /** Constant propertyValueAliases="{}" */
+ /** Constant {@code propertyValueAliases="{}"} */
public static final String[] propertyValueAliases = {};
- /** Constant caselessMatchPartitionSize=3 */
+ /** Constant {@code caselessMatchPartitionSize=3} */
public static final int caselessMatchPartitionSize = 3;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\u0042\u0062\000\u0043\"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_2_0.java b/jflex/src/main/java/jflex/unicode/data/Unicode_2_0.java
index 0500621fc..34469ed7a 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_2_0.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_2_0.java
@@ -4,12 +4,11 @@
* Unicode_2_0 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_2_0 {
- /** Constant maximumCodePoint=0xffff */
+ /** Constant {@code maximumCodePoint=0xffff} */
public static final int maximumCodePoint = 0xffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=unassigned, alnu"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=unassigned, alnu"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=unassigned", "alnum", "alphabetic",
"assigned", "bidi=arabicdigit", "bidi=blockseparator", "bidi=commonseparator",
@@ -56,7 +55,7 @@ public class Unicode_2_0 {
"whitespace", "xdigit", "zerowidth", "zl", "zp",
"zs"
};
- /** Constant intervals="{// Unicode 2.0 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 2.0 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 2.0 property value: {age=1.1}
"\000\u01f5"
@@ -5916,10 +5915,10 @@ public class Unicode_2_0 {
// Unicode 2.0 property value: {zs}
"\u0020\u0020" + "\u00a0\u00a0" + "\u2000\u200b" + "\u3000\u3000"
};
- /** Constant propertyValueAliases="{}" */
+ /** Constant {@code propertyValueAliases="{}"} */
public static final String[] propertyValueAliases = {};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_2_1.java b/jflex/src/main/java/jflex/unicode/data/Unicode_2_1.java
index 3bfff5f5e..72fec44fe 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_2_1.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_2_1.java
@@ -4,12 +4,11 @@
* Unicode_2_1 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_2_1 {
- /** Constant maximumCodePoint=0xffff */
+ /** Constant {@code maximumCodePoint=0xffff} */
public static final int maximumCodePoint = 0xffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=2.1, age=unassig"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=2.1, age=unassig"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=unassigned", "alnum",
"alphabetic", "assigned", "bidi=arabicdigit", "bidi=blockseparator", "bidi=commonseparator",
@@ -54,7 +53,7 @@ public class Unicode_2_1 {
"space", "terminalpunctuation", "unassignedcodevalue", "whitespace", "xdigit",
"zerowidth", "zl", "zp", "zs"
};
- /** Constant intervals="{// Unicode 2.1 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 2.1 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 2.1 property value: {age=1.1}
"\000\u01f5"
@@ -6401,10 +6400,10 @@ public class Unicode_2_1 {
// Unicode 2.1 property value: {zs}
"\u0020\u0020" + "\u00a0\u00a0" + "\u2000\u200b" + "\u3000\u3000"
};
- /** Constant propertyValueAliases="{}" */
+ /** Constant {@code propertyValueAliases="{}"} */
public static final String[] propertyValueAliases = {};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_3_0.java b/jflex/src/main/java/jflex/unicode/data/Unicode_3_0.java
index ebc121d1a..394cf6b32 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_3_0.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_3_0.java
@@ -4,12 +4,11 @@
* Unicode_3_0 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_3_0 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=unassigned",
"alnum", "alphabetic", "assigned", "bidi=arabicdigit", "bidi=arabicrighttoleft",
@@ -71,7 +70,7 @@ public class Unicode_3_0 {
"whitespace", "xdigit", "zerowidth", "zl", "zp",
"zs"
};
- /** Constant intervals="{// Unicode 3.0 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 3.0 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 3.0 property value: {age=1.1}
"\000\u01f5"
@@ -9871,10 +9870,10 @@ public class Unicode_3_0 {
+ "\u202f\u202f"
+ "\u3000\u3000"
};
- /** Constant propertyValueAliases="{}" */
+ /** Constant {@code propertyValueAliases="{}"} */
public static final String[] propertyValueAliases = {};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_3_1.java b/jflex/src/main/java/jflex/unicode/data/Unicode_3_1.java
index d7d2a3544..02152a971 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_3_1.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_3_1.java
@@ -4,12 +4,11 @@
* Unicode_3_1 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_3_1 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=3.1",
"age=unassigned", "alnum", "alphabetic", "arabic", "armenian",
@@ -74,7 +73,7 @@ public class Unicode_3_1 {
"uppercase", "whitespace", "xdigit", "xidcontinue", "xidstart",
"yi", "zl", "zp", "zs"
};
- /** Constant intervals="{// Unicode 3.1 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 3.1 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 3.1 property value: {age=1.1}
"\000\u01f5"
@@ -11092,10 +11091,10 @@ public class Unicode_3_1 {
+ "\u202f\u202f"
+ "\u3000\u3000"
};
- /** Constant propertyValueAliases="{}" */
+ /** Constant {@code propertyValueAliases="{}"} */
public static final String[] propertyValueAliases = {};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_3_2.java b/jflex/src/main/java/jflex/unicode/data/Unicode_3_2.java
index ec3a92274..7eaffd92c 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_3_2.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_3_2.java
@@ -4,12 +4,11 @@
* Unicode_3_2 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_3_2 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=3.1",
"age=3.2", "age=unassigned", "alnum", "alphabetic", "arabic",
@@ -94,7 +93,7 @@ public class Unicode_3_2 {
"xidcontinue", "xidstart", "yi", "zl", "zp",
"zs"
};
- /** Constant intervals="{// Unicode 3.2 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 3.2 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 3.2 property value: {age=1.1}
"\000\u01f5"
@@ -12391,7 +12390,7 @@ public class Unicode_3_2 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}
+ * Constant {@code propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}}
*/
public static final String[] propertyValueAliases = {
"ahex", "asciihexdigit", "alpha", "alphabetic",
@@ -12658,7 +12657,7 @@ public class Unicode_3_2 {
"xids", "xidstart", "yiii", "yi",
"zyyy", "common"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_4_0.java b/jflex/src/main/java/jflex/unicode/data/Unicode_4_0.java
index 157dbdf8c..c2b198e79 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_4_0.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_4_0.java
@@ -4,12 +4,11 @@
* Unicode_4_0 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_4_0 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=3.1",
"age=3.2", "age=4.0", "age=unassigned", "alnum", "alphabetic",
@@ -102,7 +101,7 @@ public class Unicode_4_0 {
"xidcontinue", "xidstart", "yi", "zl", "zp",
"zs"
};
- /** Constant intervals="{// Unicode 4.0 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 4.0 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 4.0 property value: {age=1.1}
"\000\u01f5"
@@ -13289,7 +13288,7 @@ public class Unicode_4_0 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}
+ * Constant {@code propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}}
*/
public static final String[] propertyValueAliases = {
"ahex", "asciihexdigit", "alpha", "alphabetic",
@@ -13673,7 +13672,7 @@ public class Unicode_4_0 {
"xids", "xidstart", "yiii", "yi",
"zyyy", "common"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_4_1.java b/jflex/src/main/java/jflex/unicode/data/Unicode_4_1.java
index a734c7bb6..d6fdeda07 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_4_1.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_4_1.java
@@ -4,12 +4,11 @@
* Unicode_4_1 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_4_1 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=3.1",
"age=3.2", "age=4.0", "age=4.1", "age=unassigned", "alnum",
@@ -125,7 +124,7 @@ public class Unicode_4_1 {
"xidcontinue", "xidstart", "yi", "zl", "zp",
"zs"
};
- /** Constant intervals="{// Unicode 4.1 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 4.1 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 4.1 property value: {age=1.1}
"\000\u01f5"
@@ -19268,7 +19267,7 @@ public class Unicode_4_1 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}
+ * Constant {@code propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}}
*/
public static final String[] propertyValueAliases = {
"ahex", "asciihexdigit", "alpha", "alphabetic",
@@ -19732,7 +19731,7 @@ public class Unicode_4_1 {
"xids", "xidstart", "xpeo", "oldpersian",
"yiii", "yi", "zyyy", "common"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_5_0.java b/jflex/src/main/java/jflex/unicode/data/Unicode_5_0.java
index ff672efb8..596236226 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_5_0.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_5_0.java
@@ -4,12 +4,11 @@
* Unicode_5_0 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_5_0 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues */
+ /** Constant {@code propertyValues} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=3.1",
"age=3.2", "age=4.0", "age=4.1", "age=5.0", "age=unassigned",
@@ -125,7 +124,7 @@ public class Unicode_5_0 {
"xdigit", "xidcontinue", "xidstart", "yi", "zl",
"zp", "zs"
};
- /** Constant intervals="{// Unicode 5.0 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 5.0 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 5.0 property value: {age=1.1}
"\000\u01f5"
@@ -20311,7 +20310,7 @@ public class Unicode_5_0 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}
+ * Constant {@code propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}}
*/
public static final String[] propertyValueAliases = {
"ahex", "asciihexdigit", "alpha", "alphabetic",
@@ -20795,7 +20794,7 @@ public class Unicode_5_0 {
"yiii", "yi", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_5_1.java b/jflex/src/main/java/jflex/unicode/data/Unicode_5_1.java
index debb22ada..410233e4c 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_5_1.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_5_1.java
@@ -4,12 +4,11 @@
* Unicode_5_1 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_5_1 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues */
+ /** Constant {@code propertyValues} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=3.1",
"age=3.2", "age=4.0", "age=4.1", "age=5.0", "age=5.1",
@@ -140,7 +139,7 @@ public class Unicode_5_1 {
"xdigit", "xidcontinue", "xidstart", "yi", "zl",
"zp", "zs"
};
- /** Constant intervals="{// Unicode 5.1 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 5.1 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 5.1 property value: {age=1.1}
"\000\u01f5"
@@ -22707,7 +22706,7 @@ public class Unicode_5_1 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}
+ * Constant {@code propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}}
*/
public static final String[] propertyValueAliases = {
"ahex", "asciihexdigit", "alpha", "alphabetic",
@@ -23253,7 +23252,7 @@ public class Unicode_5_1 {
"yiii", "yi", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_5_2.java b/jflex/src/main/java/jflex/unicode/data/Unicode_5_2.java
index 95db0b8e4..e1593543d 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_5_2.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_5_2.java
@@ -4,12 +4,11 @@
* Unicode_5_2 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_5_2 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=3.1",
"age=3.2", "age=4.0", "age=4.1", "age=5.0", "age=5.1",
@@ -153,7 +152,7 @@ public class Unicode_5_2 {
"xdigit", "xidcontinue", "xidstart", "yi", "zl",
"zp", "zs"
};
- /** Constant intervals="{// Unicode 5.2 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 5.2 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 5.2 property value: {age=1.1}
"\000\u01f5"
@@ -27250,7 +27249,7 @@ public class Unicode_5_2 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}
+ * Constant {@code propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}}
*/
public static final String[] propertyValueAliases = {
"ahex", "asciihexdigit", "alpha", "alphabetic",
@@ -27854,7 +27853,7 @@ public class Unicode_5_2 {
"zinh", "inherited", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_6_0.java b/jflex/src/main/java/jflex/unicode/data/Unicode_6_0.java
index e2fc241d6..98340bdcb 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_6_0.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_6_0.java
@@ -4,12 +4,11 @@
* Unicode_6_0 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_6_0 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked} */
+ /** Constant {@code propertyValues="{age=1.1, age=2.0, age=2.1, age=3.0, ag"{trunked}} */
public static final String[] propertyValues = {
"age=1.1", "age=2.0", "age=2.1", "age=3.0", "age=3.1",
"age=3.2", "age=4.0", "age=4.1", "age=5.0", "age=5.1",
@@ -199,7 +198,7 @@ public class Unicode_6_0 {
"wordbreak=numeric", "wordbreak=other", "xdigit", "xidcontinue", "xidstart",
"yi", "zl", "zp", "zs"
};
- /** Constant intervals="{// Unicode 6.0 property value: {age=1."{trunked} */
+ /** Constant {@code intervals="{// Unicode 6.0 property value: {age=1."{trunked}} */
public static final String[] intervals = {
// Unicode 6.0 property value: {age=1.1}
"\000\u01f5"
@@ -29657,7 +29656,7 @@ public class Unicode_6_0 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}
+ * Constant {@code propertyValueAliases="{ahex, asciihexdigit, alpha, alphabetic"{trunked}}
*/
public static final String[] propertyValueAliases = {
"ahex", "asciihexdigit", "alpha", "alphabetic",
@@ -30370,7 +30369,7 @@ public class Unicode_6_0 {
"zinh", "inherited", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_6_1.java b/jflex/src/main/java/jflex/unicode/data/Unicode_6_1.java
index da0367d37..2c72cf6dd 100755
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_6_1.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_6_1.java
@@ -4,12 +4,11 @@
* Unicode_6_1 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_6_1 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked} */
+ /** Constant {@code propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked}} */
public static final String[] propertyValues = {
"age=unassigned", "age=v11", "age=v20", "age=v21", "age=v30",
"age=v31", "age=v32", "age=v40", "age=v41", "age=v50",
@@ -207,7 +206,7 @@ public class Unicode_6_1 {
"xidcontinue", "xidstart", "yi", "zl", "zp",
"zs"
};
- /** Constant intervals="{// Unicode 6.1 property value: {age=un"{trunked} */
+ /** Constant {@code intervals="{// Unicode 6.1 property value: {age=un"{trunked}} */
public static final String[] intervals = {
// Unicode 6.1 property value: {age=unassigned}
"\u0378\u0379"
@@ -31618,7 +31617,7 @@ public class Unicode_6_1 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}
+ * Constant {@code propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}}
*/
public static final String[] propertyValueAliases = {
"age=1.1", "age=v11", "age=2.0", "age=v20",
@@ -32648,7 +32647,7 @@ public class Unicode_6_1 {
"zinh", "inherited", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_6_2.java b/jflex/src/main/java/jflex/unicode/data/Unicode_6_2.java
index 12fad7a8a..30d8cf007 100755
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_6_2.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_6_2.java
@@ -4,12 +4,11 @@
* Unicode_6_2 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_6_2 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked} */
+ /** Constant {@code propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked}} */
public static final String[] propertyValues = {
"age=unassigned", "age=v11", "age=v20", "age=v21", "age=v30",
"age=v31", "age=v32", "age=v40", "age=v41", "age=v50",
@@ -206,7 +205,7 @@ public class Unicode_6_2 {
"wordbreak=numeric", "wordbreak=other", "wordbreak=regionalindicator", "xdigit", "xidcontinue",
"xidstart", "yi", "zl", "zp", "zs"
};
- /** Constant intervals="{// Unicode 6.2 property value: {age=un"{trunked} */
+ /** Constant {@code intervals="{// Unicode 6.2 property value: {age=un"{trunked}} */
public static final String[] intervals = {
// Unicode 6.2 property value: {age=unassigned}
"\u0378\u0379"
@@ -32223,7 +32222,7 @@ public class Unicode_6_2 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}
+ * Constant {@code propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}}
*/
public static final String[] propertyValueAliases = {
"age=1.1", "age=v11", "age=2.0", "age=v20",
@@ -33257,7 +33256,7 @@ public class Unicode_6_2 {
"zinh", "inherited", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_6_3.java b/jflex/src/main/java/jflex/unicode/data/Unicode_6_3.java
index bad8224b9..e6c5d89b6 100755
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_6_3.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_6_3.java
@@ -4,12 +4,11 @@
* Unicode_6_3 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_6_3 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked} */
+ /** Constant {@code propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked}} */
public static final String[] propertyValues = {
"age=unassigned", "age=v11", "age=v20", "age=v21", "age=v30",
"age=v31", "age=v32", "age=v40", "age=v41", "age=v50",
@@ -210,7 +209,7 @@ public class Unicode_6_3 {
"wordbreak=regionalindicator", "wordbreak=singlequote", "xdigit", "xidcontinue", "xidstart",
"yi", "zl", "zp", "zs"
};
- /** Constant intervals="{// Unicode 6.3 property value: {age=un"{trunked} */
+ /** Constant {@code intervals="{// Unicode 6.3 property value: {age=un"{trunked}} */
public static final String[] intervals = {
// Unicode 6.3 property value: {age=unassigned}
"\u0378\u0379"
@@ -32808,7 +32807,7 @@ public class Unicode_6_3 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}
+ * Constant {@code propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}}
*/
public static final String[] propertyValueAliases = {
"age=1.1", "age=v11", "age=2.0", "age=v20",
@@ -33848,7 +33847,7 @@ public class Unicode_6_3 {
"zinh", "inherited", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_7_0.java b/jflex/src/main/java/jflex/unicode/data/Unicode_7_0.java
index 243226625..64db0c5e0 100755
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_7_0.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_7_0.java
@@ -4,12 +4,11 @@
* Unicode_7_0 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_7_0 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked} */
+ /** Constant {@code propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked}} */
public static final String[] propertyValues = {
"age=unassigned", "age=v11", "age=v20", "age=v21", "age=v30",
"age=v31", "age=v32", "age=v40", "age=v41", "age=v50",
@@ -238,7 +237,7 @@ public class Unicode_7_0 {
"wordbreak=singlequote", "xdigit", "xidcontinue", "xidstart", "yi",
"zl", "zp", "zs"
};
- /** Constant intervals="{// Unicode 7.0 property value: {age=un"{trunked} */
+ /** Constant {@code intervals="{// Unicode 7.0 property value: {age=un"{trunked}} */
public static final String[] intervals = {
// Unicode 7.0 property value: {age=unassigned}
"\u0378\u0379"
@@ -35636,7 +35635,7 @@ public class Unicode_7_0 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}
+ * Constant {@code propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}}
*/
public static final String[] propertyValueAliases = {
"age=1.1", "age=v11", "age=2.0", "age=v20",
@@ -36806,7 +36805,7 @@ public class Unicode_7_0 {
"zinh", "inherited", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_8_0.java b/jflex/src/main/java/jflex/unicode/data/Unicode_8_0.java
index b2664d113..f84dddf1b 100755
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_8_0.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_8_0.java
@@ -4,12 +4,11 @@
* Unicode_8_0 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_8_0 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked} */
+ /** Constant {@code propertyValues="{age=unassigned, age=v11, age=v20, age="{trunked}} */
public static final String[] propertyValues = {
"age=unassigned", "age=v11", "age=v20", "age=v21", "age=v30",
"age=v31", "age=v32", "age=v40", "age=v41", "age=v50",
@@ -244,7 +243,7 @@ public class Unicode_8_0 {
"xidcontinue", "xidstart", "yi", "zl", "zp",
"zs"
};
- /** Constant intervals="{// Unicode 8.0 property value: {age=un"{trunked} */
+ /** Constant {@code intervals="{// Unicode 8.0 property value: {age=un"{trunked}} */
public static final String[] intervals = {
// Unicode 8.0 property value: {age=unassigned}
"\u0378\u0379"
@@ -36890,7 +36889,7 @@ public class Unicode_8_0 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}
+ * Constant {@code propertyValueAliases="{age=1.1, age=v11, age=2.0, age=v20,age"{trunked}}
*/
public static final String[] propertyValueAliases = {
"age=1.1", "age=v11", "age=2.0", "age=v20",
@@ -38100,7 +38099,7 @@ public class Unicode_8_0 {
"zinh", "inherited", "zyyy", "common",
"zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/src/main/java/jflex/unicode/data/Unicode_9_0.java b/jflex/src/main/java/jflex/unicode/data/Unicode_9_0.java
index a837a1213..f226fe406 100644
--- a/jflex/src/main/java/jflex/unicode/data/Unicode_9_0.java
+++ b/jflex/src/main/java/jflex/unicode/data/Unicode_9_0.java
@@ -4,12 +4,11 @@
* Unicode_9_0 class.
*
* @author JFlex contributors.
- * @version $Id: $Id
*/
public class Unicode_9_0 {
- /** Constant maximumCodePoint=0x10ffff */
+ /** Constant {@code maximumCodePoint=0x10ffff} */
public static final int maximumCodePoint = 0x10ffff;
- /** Constant propertyValues="{adlam, age=unassigned, age=v11, age=v2"{trunked} */
+ /** Constant {@code propertyValues="{adlam, age=unassigned, age=v11, age=v2"{trunked}} */
public static final String[] propertyValues = {
"adlam", "age=unassigned", "age=v11", "age=v20", "age=v21",
"age=v30", "age=v31", "age=v32", "age=v40", "age=v41",
@@ -263,7 +262,7 @@ public class Unicode_9_0 {
"xidcontinue",
"xidstart", "yi", "zl", "zp", "zs"
};
- /** Constant intervals="{// Unicode 9.0 property value: {adlam}"{trunked} */
+ /** Constant {@code intervals="{// Unicode 9.0 property value: {adlam}"{trunked}} */
public static final String[] intervals = {
// Unicode 9.0 property value: {adlam}
"\ud83a\udd00\ud83a\udd4a" + "\ud83a\udd50\ud83a\udd59" + "\ud83a\udd5e\ud83a\udd5f",
@@ -38521,7 +38520,7 @@ public class Unicode_9_0 {
+ "\u3000\u3000"
};
/**
- * Constant propertyValueAliases="{adlm, adlam, age=1.1, age=v11,age=2.0,"{trunked}
+ * Constant {@code propertyValueAliases="{adlm, adlam, age=1.1, age=v11,age=2.0,"{trunked}}
*/
public static final String[] propertyValueAliases = {
"adlm", "adlam", "age=1.1", "age=v11",
@@ -39790,7 +39789,7 @@ public class Unicode_9_0 {
"yiii", "yi", "zinh", "inherited",
"zyyy", "common", "zzzz", "unknown"
};
- /** Constant caselessMatchPartitionSize=4 */
+ /** Constant {@code caselessMatchPartitionSize=4} */
public static final int caselessMatchPartitionSize = 4;
/**
* Constant caselessMatchPartitions="\u0041\u0061\000\000\u0042\u0062\000\00"{trunked}
diff --git a/jflex/COPYRIGHT b/jflex/src/main/resources/LICENSE_JFLEX
similarity index 62%
rename from jflex/COPYRIGHT
rename to jflex/src/main/resources/LICENSE_JFLEX
index b43a64eeb..8f3b927ff 100644
--- a/jflex/COPYRIGHT
+++ b/jflex/src/main/resources/LICENSE_JFLEX
@@ -1,21 +1,21 @@
JFlex - Copying, Warranty & License
+===================================
-JFlex is free software, since version 1.5 published under the terms of a
-BSD-style license.
+JFlex is free software, since version 1.5 published under the terms of this
+3-clause BSD-style license.
There is absolutely NO WARRANTY for JFlex, its code and its documentation.
-Copyright (c) Gerwin Klein, Steve Rowe, Régis Décamps.
+Copyright (c) Gerwin Klein, Steve Rowe, Régis Decamps.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- * Neither the names of the authors nor the names of JFlex contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the names of the authors nor the names of JFlex contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/jflex/src/main/resources/jflex/skeleton.default b/jflex/src/main/resources/jflex/skeleton.default
index 9e08fbb0c..11a9d6891 100644
--- a/jflex/src/main/resources/jflex/skeleton.default
+++ b/jflex/src/main/resources/jflex/skeleton.default
@@ -1,19 +1,24 @@
- /** This character denotes the end of file */
+ /** This character denotes the end of file. */
public static final int YYEOF = -1;
- /** initial size of the lookahead buffer */
+ /** Initial size of the lookahead buffer. */
--- private static final int ZZ_BUFFERSIZE = ...;
- /** lexical states */
+ // Lexical states.
--- lexical states, charmap
- /* error codes */
+ /** Error code for "Unknown internal scanner error". */
private static final int ZZ_UNKNOWN_ERROR = 0;
+ /** Error code for "could not match input". */
private static final int ZZ_NO_MATCH = 1;
+ /** Error code for "pushback value was too large". */
private static final int ZZ_PUSHBACK_2BIG = 2;
- /* error messages for the codes above */
+ /**
+ * Error messages for {@link #ZZ_UNKNOWN_ERROR}, {@link #ZZ_NO_MATCH}, and
+ * {@link #ZZ_PUSHBACK_2BIG} respectively.
+ */
private static final String ZZ_ERROR_MSG[] = {
"Unknown internal scanner error",
"Error: could not match input",
@@ -21,60 +26,56 @@
};
--- isFinal list
- /** the input device */
+ /** Input device. */
private java.io.Reader zzReader;
- /** the current state of the DFA */
+ /** Current state of the DFA. */
private int zzState;
- /** the current lexical state */
+ /** Current lexical state. */
private int zzLexicalState = YYINITIAL;
- /** this buffer contains the current text to be matched and is
- the source of the yytext() string */
+ /**
+ * This buffer contains the current text to be matched and is the source of the {@link #yytext()}
+ * string.
+ */
private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
- /** the textposition at the last accepting state */
+ /** Text position at the last accepting state. */
private int zzMarkedPos;
- /** the current text position in the buffer */
+ /** Current text position in the buffer. */
private int zzCurrentPos;
- /** startRead marks the beginning of the yytext() string in the buffer */
+ /** Marks the beginning of the {@link #yytext()} string in the buffer. */
private int zzStartRead;
- /** endRead marks the last character in the buffer, that has been read
- from input */
+ /** Marks the last character in the buffer, that has been read from input. */
private int zzEndRead;
- /** number of newlines encountered up to the start of the matched text */
+ /** Number of newlines encountered up to the start of the matched text. */
private int yyline;
- /** the number of characters up to the start of the matched text */
+ /** Number of characters up to the start of the matched text. */
private int yychar;
- /**
- * the number of characters from the last newline up to the start of the
- * matched text
- */
+ /** Number of characters from the last newline up to the start of the matched text. */
private int yycolumn;
- /**
- * zzAtBOL == true iff the scanner is currently at the beginning of a line
- */
+ /** Whether the scanner is currently at the beginning of a line. */
private boolean zzAtBOL = true;
- /** zzAtEOF == true iff the scanner is at the EOF */
+ /** Whether the scanner is at the end of line. */
private boolean zzAtEOF;
- /** denotes if the user-EOF-code has already been executed */
+ /** Whether the user-EOF-code has already been executed. */
private boolean zzEOFDone;
-
- /**
- * The number of occupied positions in zzBuffer beyond zzEndRead.
- * When a lead/high surrogate has been read from the input stream
- * into the final zzBuffer position, this will have a value of 1;
- * otherwise, it will have a value of 0.
+
+ /**
+ * The number of occupied positions in {@link #zzBuffer} beyond {@link #zzEndRead}.
+ *
+ *
When a lead/high surrogate has been read from the input stream into the final
+ * {@link #zzBuffer} position, this will have a value of 1; otherwise, it will have a value of 0.
*/
private int zzFinalHighSurrogate = 0;
@@ -86,9 +87,8 @@
/**
* Refills the input buffer.
*
- * @return false, iff there was new input.
- *
- * @exception java.io.IOException if any I/O-Error occurs
+ * @return {@code false} iff there was new input.
+ * @exception java.io.IOException if any I/O-Error occurs
*/
private boolean zzRefill() throws java.io.IOException {
@@ -98,19 +98,19 @@
zzFinalHighSurrogate = 0;
System.arraycopy(zzBuffer, zzStartRead,
zzBuffer, 0,
- zzEndRead-zzStartRead);
+ zzEndRead - zzStartRead);
/* translate stored positions */
- zzEndRead-= zzStartRead;
- zzCurrentPos-= zzStartRead;
- zzMarkedPos-= zzStartRead;
+ zzEndRead -= zzStartRead;
+ zzCurrentPos -= zzStartRead;
+ zzMarkedPos -= zzStartRead;
zzStartRead = 0;
}
/* is the buffer big enough? */
if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) {
/* if not: blow it up */
- char newBuffer[] = new char[zzBuffer.length*2];
+ char newBuffer[] = new char[zzBuffer.length * 2];
System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
zzBuffer = newBuffer;
zzEndRead += zzFinalHighSurrogate;
@@ -123,13 +123,14 @@
/* not supposed to occur according to specification of java.io.Reader */
if (numRead == 0) {
- throw new java.io.IOException("Reader returned 0 characters. See JFlex examples for workaround.");
+ throw new java.io.IOException(
+ "Reader returned 0 characters. See JFlex examples/zero-reader for a workaround.");
}
if (numRead > 0) {
zzEndRead += numRead;
- /* If numRead == requested, we might have requested to few chars to
- encode a full Unicode character. We assume that a Reader would
- otherwise never return half characters. */
+ // If numRead == requested, we might have requested to few chars to encode a full Unicode
+ // character.
+ // We assume that a Reader would otherwise never return half characters.
if (numRead == requested) {
if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
--zzEndRead;
@@ -149,38 +150,40 @@
* Closes the input stream.
*/
public final void yyclose() throws java.io.IOException {
- zzAtEOF = true; /* indicate end of file */
- zzEndRead = zzStartRead; /* invalidate buffer */
+ zzAtEOF = true; // indicate end of file
+ zzEndRead = zzStartRead; // invalidate buffer
- if (zzReader != null)
+ if (zzReader != null) {
zzReader.close();
+ }
}
/**
* Resets the scanner to read from a new input stream.
- * Does not close the old reader.
*
- * All internal variables are reset, the old input stream
- * cannot be reused (internal buffer is discarded and lost).
- * Lexical state is set to ZZ_INITIAL.
+ *
Does not close the old reader.
*
- * Internal scan buffer is resized down to its initial length, if it has grown.
+ *
All internal variables are reset, the old input stream cannot be reused (internal
+ * buffer is discarded and lost). Lexical state is set to {@code ZZ_INITIAL}.
*
- * @param reader the new input stream
+ *
Internal scan buffer is resized down to its initial length, if it has grown.
+ *
+ * @param reader The new input stream.
*/
public final void yyreset(java.io.Reader reader) {
zzReader = reader;
- zzAtBOL = true;
- zzAtEOF = false;
+ zzAtBOL = true;
+ zzAtEOF = false;
zzEOFDone = false;
zzEndRead = zzStartRead = 0;
zzCurrentPos = zzMarkedPos = 0;
zzFinalHighSurrogate = 0;
yyline = yychar = yycolumn = 0;
zzLexicalState = YYINITIAL;
- if (zzBuffer.length > ZZ_BUFFERSIZE)
+ if (zzBuffer.length > ZZ_BUFFERSIZE) {
zzBuffer = new char[ZZ_BUFFERSIZE];
+ }
}
@@ -193,7 +196,7 @@
/**
- * Enters a new lexical state
+ * Enters a new lexical state.
*
* @param newState the new lexical state
*/
@@ -206,23 +209,21 @@
* Returns the text matched by the current regular expression.
*/
public final String yytext() {
- return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
+ return new String(zzBuffer, zzStartRead, zzMarkedPos-zzStartRead);
}
/**
- * Returns the character at position pos from the
- * matched text.
+ * Returns the character at the given position from the matched text.
*
- * It is equivalent to yytext().charAt(pos), but faster
+ *
It is equivalent to {@code yytext().charAt(pos)}, but faster.
*
- * @param pos the position of the character to fetch.
- * A value from 0 to yylength()-1.
+ * @param position the position of the character to fetch. A value from 0 to {@code yylength()-1}.
*
- * @return the character at position pos
+ * @return the character at {@code position}.
*/
- public final char yycharat(int pos) {
- return zzBuffer[zzStartRead+pos];
+ public final char yycharat(int position) {
+ return zzBuffer[zzStartRead + position];
}
@@ -235,25 +236,24 @@
/**
- * Reports an error that occured while scanning.
+ * Reports an error that occurred while scanning.
*
- * In a wellformed scanner (no or only correct usage of
- * yypushback(int) and a match-all fallback rule) this method
- * will only be called with things that "Can't Possibly Happen".
- * If this method is called, something is seriously wrong
- * (e.g. a JFlex bug producing a faulty scanner etc.).
+ *
In a well-formed scanner (no or only correct usage of {@code yypushback(int)} and a
+ * match-all fallback rule) this method will only be called with things that
+ * "Can't Possibly Happen".
*
- * Usual syntax/scanner level error handling should be done
- * in error fallback rules.
+ *
If this method is called, something is seriously wrong (e.g. a JFlex bug producing a faulty
+ * scanner etc.).
*
- * @param errorCode the code of the errormessage to display
+ *
Usual syntax/scanner level error handling should be done in error fallback rules.
+ *
+ * @param errorCode the code of the error message to display.
*/
--- zzScanError declaration
String message;
try {
message = ZZ_ERROR_MSG[errorCode];
- }
- catch (ArrayIndexOutOfBoundsException e) {
+ } catch (ArrayIndexOutOfBoundsException e) {
message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
}
@@ -264,10 +264,10 @@
/**
* Pushes the specified amount of characters back into the input stream.
*
- * They will be read again by then next call of the scanning method
+ *
They will be read again by then next call of the scanning method.
*
- * @param number the number of characters to be read again.
- * This number must not be greater than yylength()!
+ * @param number the number of characters to be read again. This number must not be greater than
+ * {@link #yylength()}.
*/
--- yypushback decl (contains zzScanError exception)
if ( number > yylength() )
@@ -278,12 +278,14 @@
--- zzDoEOF
+
+
/**
- * Resumes scanning until the next regular expression is matched,
- * the end of input is encountered or an I/O-Error occurs.
+ * Resumes scanning until the next regular expression is matched, the end of input is encountered
+ * or an I/O-Error occurs.
*
- * @return the next token
- * @exception java.io.IOException if any I/O-Error occurs
+ * @return the next token.
+ * @exception java.io.IOException if any I/O-Error occurs.
*/
--- yylex declaration
int zzInput;
@@ -293,8 +295,8 @@
int zzCurrentPosL;
int zzMarkedPosL;
int zzEndReadL = zzEndRead;
- char [] zzBufferL = zzBuffer;
- char [] zzCMapL = ZZ_CMAP;
+ char[] zzBufferL = zzBuffer;
+ char[] zzCMapL = ZZ_CMAP;
--- local declarations
diff --git a/jflex/src/test/java/jflex/CharClassesTest.java b/jflex/src/test/java/jflex/CharClassesTest.java
index dcca5140b..fd3808ed8 100644
--- a/jflex/src/test/java/jflex/CharClassesTest.java
+++ b/jflex/src/test/java/jflex/CharClassesTest.java
@@ -88,7 +88,7 @@ public void testCaseless() {
try {
unicodeProperties = new UnicodeProperties("4.0");
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported default Unicode version: " + e, false);
+ fail("Unsupported default Unicode version: " + e);
return;
}
diff --git a/jflex/src/test/java/jflex/IntCharSetTest.java b/jflex/src/test/java/jflex/IntCharSetTest.java
index f637939be..c508d6804 100644
--- a/jflex/src/test/java/jflex/IntCharSetTest.java
+++ b/jflex/src/test/java/jflex/IntCharSetTest.java
@@ -1,5 +1,6 @@
package jflex;
+import java.util.Objects;
import junit.framework.TestCase;
public class IntCharSetTest extends TestCase {
@@ -18,6 +19,7 @@ public void testAddIntCharSet() {
IntCharSet original_a = a.copy();
IntCharSet b = new IntCharSet(new Interval((char) 0, (char) 4));
a.add(b);
- assertTrue(original_a + " + " + b + " should be " + b + " instead of " + a, a.equals(b));
+ assertTrue(
+ original_a + " + " + b + " should be " + b + " instead of " + a, Objects.equals(a, b));
}
}
diff --git a/jflex/src/test/java/jflex/RegExpTests.java b/jflex/src/test/java/jflex/RegExpTests.java
index de21edc09..2cf93e196 100644
--- a/jflex/src/test/java/jflex/RegExpTests.java
+++ b/jflex/src/test/java/jflex/RegExpTests.java
@@ -9,6 +9,8 @@
package jflex;
+import static jflex.RegExp.revString;
+
import junit.framework.TestCase;
/**
@@ -29,7 +31,7 @@ public RegExpTests(String name) {
}
public void testrevString() {
- assertTrue(RegExp.revString("blah").equals("halb"));
+ assertEquals("halb", revString("blah"));
}
public void testCharClass() {
diff --git a/jflex/src/test/java/jflex/UnicodePropertiesTest.java b/jflex/src/test/java/jflex/UnicodePropertiesTest.java
index 20edf4930..6980ac1b6 100644
--- a/jflex/src/test/java/jflex/UnicodePropertiesTest.java
+++ b/jflex/src/test/java/jflex/UnicodePropertiesTest.java
@@ -9,6 +9,7 @@
package jflex;
+import java.util.Objects;
import jflex.unicode.UnicodeProperties;
import junit.framework.TestCase;
@@ -44,7 +45,7 @@ public void testSupportedVersions() {
"intervals for 'Lu' property value should have an interval",
intervals.numIntervals() > 0);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '" + version + "' should be supported: " + e, false);
+ fail("Unsupported version '" + version + "' should be supported: " + e);
}
}
}
@@ -52,10 +53,9 @@ public void testSupportedVersions() {
public void testUnsupportedVersion() {
try {
new UnicodeProperties("1.0");
- assertTrue(
+ fail(
"new UnicodeProperties(\"1.0\") should trigger an"
- + " UnsupportedUnicodeVersionException, but it did not.",
- false);
+ + " UnsupportedUnicodeVersionException, but it did not.");
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
// Drop the exception - it is expected.
}
@@ -75,7 +75,7 @@ public void testDefaultVersion() {
"intervals for 'Lu' property value should have an interval",
intervals.numIntervals() > 0);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Default version is unsupported: " + e, false);
+ fail("Default version is unsupported: " + e);
}
}
@@ -93,7 +93,7 @@ public void testDefaultVersionAliases() {
assertTrue("Empty interval set returned for \\p{Lo}", set_1.containsElements());
assertTrue(
"\\p{General Category : Other Letter} and \\p{Lo} should" + " return the same thing.",
- set_1.equals(set_2));
+ Objects.equals(set_1, set_2));
set_1 = properties.getIntCharSet(" Script:Tibetan ");
assertNotNull("Null interval set returned for \\p{ Script:Tibetan }", set_1);
@@ -103,9 +103,9 @@ public void testDefaultVersionAliases() {
assertTrue("Empty interval set returned for \\p{-_T i b t_-}", set_1.containsElements());
assertTrue(
"\\p{ Script:Tibetan } and \\p{-_T i b t_-} should" + " return the same thing.",
- set_1.equals(set_2));
+ Objects.equals(set_1, set_2));
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Default version is unsupported: " + e, false);
+ fail("Default version is unsupported: " + e);
}
}
@@ -126,7 +126,7 @@ public void testCaselessMatches_1_1() {
+ caselessMatches.numIntervals(),
caselessMatches.numIntervals() == 2);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '1.1' should be supported: " + e, false);
+ fail("Unsupported version '1.1' should be supported: " + e);
}
}
@@ -135,7 +135,7 @@ public void testCaselessMatches_2_0() {
UnicodeProperties properties = new UnicodeProperties("2.0");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '2.0' should be supported: " + e, false);
+ fail("Unsupported version '2.0' should be supported: " + e);
}
}
@@ -173,7 +173,7 @@ public void testCaselessMatches_2_1() {
UnicodeProperties properties = new UnicodeProperties("2.1");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '2.1' should be supported: " + e, false);
+ fail("Unsupported version '2.1' should be supported: " + e);
}
}
@@ -182,7 +182,7 @@ public void testCaselessMatches_3_0() {
UnicodeProperties properties = new UnicodeProperties("3.0");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '3.0' should be supported: " + e, false);
+ fail("Unsupported version '3.0' should be supported: " + e);
}
}
@@ -191,7 +191,7 @@ public void testCaselessMatches_3_1() {
UnicodeProperties properties = new UnicodeProperties("3.1");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '3.1' should be supported: " + e, false);
+ fail("Unsupported version '3.1' should be supported: " + e);
}
}
@@ -200,7 +200,7 @@ public void testCaselessMatches_3_2() {
UnicodeProperties properties = new UnicodeProperties("3.2");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '3.2' should be supported: " + e, false);
+ fail("Unsupported version '3.2' should be supported: " + e);
}
}
@@ -209,7 +209,7 @@ public void testCaselessMatches_4_0() {
UnicodeProperties properties = new UnicodeProperties("4.0");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '4.0' should be supported: " + e, false);
+ fail("Unsupported version '4.0' should be supported: " + e);
}
}
@@ -218,7 +218,7 @@ public void testCaselessMatches_4_1() {
UnicodeProperties properties = new UnicodeProperties("4.1");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '4.1' should be supported: " + e, false);
+ fail("Unsupported version '4.1' should be supported: " + e);
}
}
@@ -227,7 +227,7 @@ public void testCaselessMatches_5_0() {
UnicodeProperties properties = new UnicodeProperties("5.0");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '5.0' should be supported: " + e, false);
+ fail("Unsupported version '5.0' should be supported: " + e);
}
}
@@ -241,7 +241,7 @@ public void testSingleLetterProperties_5_0() {
assertNotNull("Null interval set for \\p{Symbol}", set_2);
assertTrue("Empty interval set for \\p{Symbol}", set_2.containsElements());
- assertTrue("\\p{S} is not the same as \\p{Symbol}", set_1.equals(set_2));
+ assertTrue("\\p{S} is not the same as \\p{Symbol}", Objects.equals(set_1, set_2));
// 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;;
assertTrue("\\p{S} does not contain \\u0024 '\u0024' (\\p{Sc})", set_1.contains('\u0024'));
@@ -255,7 +255,7 @@ public void testSingleLetterProperties_5_0() {
assertTrue("\\p{S} does not contain \\uFF04 (\\p{Sc}", set_1.contains('\uFF04'));
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Version '5.0' not supported: " + e, false);
+ fail("Version '5.0' not supported: " + e);
}
}
@@ -264,7 +264,7 @@ public void testCaselessMatches_5_1() {
UnicodeProperties properties = new UnicodeProperties("5.1");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '5.1' should be supported: " + e, false);
+ fail("Unsupported version '5.1' should be supported: " + e);
}
}
@@ -278,7 +278,7 @@ public void testSingleLetterProperties_5_1() {
assertNotNull("Null interval set for \\p{Symbol}", set_2);
assertTrue("Empty interval set for \\p{Symbol}", set_2.containsElements());
- assertTrue("\\p{S} is not the same as \\p{Symbol}", set_1.equals(set_2));
+ assertTrue("\\p{S} is not the same as \\p{Symbol}", Objects.equals(set_1, set_2));
// 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;;
assertTrue("\\p{S} does not contain \\u0024 '\u0024' (\\p{Sc})", set_1.contains('\u0024'));
@@ -292,7 +292,7 @@ public void testSingleLetterProperties_5_1() {
assertTrue("\\p{S} does not contain \\uFF04 (\\p{Sc}", set_1.contains('\uFF04'));
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Version '5.1' not supported: " + e, false);
+ fail("Version '5.1' not supported: " + e);
}
}
@@ -301,7 +301,7 @@ public void testCaselessMatches_5_2() {
UnicodeProperties properties = new UnicodeProperties("5.2");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '5.2' should be supported: " + e, false);
+ fail("Unsupported version '5.2' should be supported: " + e);
}
}
@@ -315,7 +315,7 @@ public void testSingleLetterProperties_5_2() {
assertNotNull("Null interval set for \\p{Symbol}", set_2);
assertTrue("Empty interval set for \\p{Symbol}", set_2.containsElements());
- assertTrue("\\p{S} is not the same as \\p{Symbol}", set_1.equals(set_2));
+ assertTrue("\\p{S} is not the same as \\p{Symbol}", Objects.equals(set_1, set_2));
// 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;;
assertTrue("\\p{S} does not contain \\u0024 '\u0024' (\\p{Sc})", set_1.contains('\u0024'));
@@ -329,7 +329,7 @@ public void testSingleLetterProperties_5_2() {
assertTrue("\\p{S} does not contain \\uFF04 (\\p{Sc}", set_1.contains('\uFF04'));
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Version '5.2' not supported: " + e, false);
+ fail("Version '5.2' not supported: " + e);
}
}
@@ -338,7 +338,7 @@ public void testCaselessMatches_6_0() {
UnicodeProperties properties = new UnicodeProperties("6.0");
checkCaseless_i_matches(properties);
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Unsupported version '6.0' should be supported: " + e, false);
+ fail("Unsupported version '6.0' should be supported: " + e);
}
}
@@ -352,7 +352,7 @@ public void testSingleLetterProperties_6_0() {
assertNotNull("Null interval set for \\p{Symbol}", set_2);
assertTrue("Empty interval set for \\p{Symbol}", set_2.containsElements());
- assertTrue("\\p{S} is not the same as \\p{Symbol}", set_1.equals(set_2));
+ assertTrue("\\p{S} is not the same as \\p{Symbol}", Objects.equals(set_1, set_2));
// 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;;
assertTrue("\\p{S} does not contain \\u0024 '\u0024' (\\p{Sc})", set_1.contains('\u0024'));
@@ -366,7 +366,7 @@ public void testSingleLetterProperties_6_0() {
assertTrue("\\p{S} does not contain \\uFF04 (\\p{Sc}", set_1.contains('\uFF04'));
} catch (UnicodeProperties.UnsupportedUnicodeVersionException e) {
- assertTrue("Version '6.0' not supported: " + e, false);
+ fail("Version '6.0' not supported: " + e);
}
}
}
diff --git a/jflex/src/test/java/jflex/io/FileUtilTest.java b/jflex/src/test/java/jflex/io/FileUtilTest.java
new file mode 100644
index 000000000..f6bfb1bff
--- /dev/null
+++ b/jflex/src/test/java/jflex/io/FileUtilTest.java
@@ -0,0 +1,36 @@
+package jflex.io;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import junit.framework.TestCase;
+import org.junit.Test;
+
+public class FileUtilTest extends TestCase {
+
+ @Test
+ public void test_getRelativePath_fileInDir() {
+ File dir = new File("/a/b/c");
+ File f = new File("/a/b/c/d/foo.bar");
+ assertEquals("d/foo.bar", FileUtil.getRelativePath(dir, f));
+ }
+
+ @Test
+ public void test_getRelativePath_fileNotInDir() {
+ File dir = new File("/a/b/c");
+ File f = new File("/d/e/f/foo.bar");
+ assertEquals("/d/e/f/foo.bar", FileUtil.getRelativePath(dir, f));
+ }
+
+ @Test
+ public void test_getRelativePath_sameStart() {
+ File dir = new File("/a/b/c");
+ File f = new File("/a/b/c.txt");
+ assertEquals("/a/b/c.txt", FileUtil.getRelativePath(dir, f));
+ }
+
+ @Test
+ public void test_slashify() {
+ assertEquals("C:/u0022.txt", FileUtil.slashify("C:\\u0022.txt"));
+ }
+}
diff --git a/mvn-deploy.sh b/mvn-deploy.sh
index 9bbd1e9c8..1379c83f4 100755
--- a/mvn-deploy.sh
+++ b/mvn-deploy.sh
@@ -21,7 +21,7 @@ set -e
# Abort if the checkout is not clean
printf "Clean checkout? "
-stat_results=`git status -s`
+stat_results=$(git status -s)
if [ ! -z "$stat_results" ] ; then
printf "NO!\n\n${stat_results}\nAborting.\n"
exit 1
diff --git a/mvnw b/mvnw
index e96ccd5fb..5551fde8e 100755
--- a/mvnw
+++ b/mvnw
@@ -200,6 +200,65 @@ if [ -z "$BASE_DIR" ]; then
exit 1;
fi
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ wget "$jarUrl" -O "$wrapperJarPath"
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ curl -o "$wrapperJarPath" "$jarUrl"
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
diff --git a/mvnw.cmd b/mvnw.cmd
index 6a6eec39b..48363fa60 100755
--- a/mvnw.cmd
+++ b/mvnw.cmd
@@ -1,145 +1,161 @@
-@REM ----------------------------------------------------------------------------
-@REM Licensed to the Apache Software Foundation (ASF) under one
-@REM or more contributor license agreements. See the NOTICE file
-@REM distributed with this work for additional information
-@REM regarding copyright ownership. The ASF licenses this file
-@REM to you under the Apache License, Version 2.0 (the
-@REM "License"); you may not use this file except in compliance
-@REM with the License. You may obtain a copy of the License at
-@REM
-@REM http://www.apache.org/licenses/LICENSE-2.0
-@REM
-@REM Unless required by applicable law or agreed to in writing,
-@REM software distributed under the License is distributed on an
-@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-@REM KIND, either express or implied. See the License for the
-@REM specific language governing permissions and limitations
-@REM under the License.
-@REM ----------------------------------------------------------------------------
-
-@REM ----------------------------------------------------------------------------
-@REM Maven2 Start Up Batch script
-@REM
-@REM Required ENV vars:
-@REM JAVA_HOME - location of a JDK home dir
-@REM
-@REM Optional ENV vars
-@REM M2_HOME - location of maven2's installed home dir
-@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
-@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
-@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
-@REM e.g. to debug Maven itself, use
-@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
-@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
-@REM ----------------------------------------------------------------------------
-
-@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
-@echo off
-@REM set title of command window
-title %0
-@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
-@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
-
-@REM set %HOME% to equivalent of $HOME
-if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
-
-@REM Execute a user defined script before this one
-if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
-@REM check for pre script, once with legacy .bat ending and once with .cmd ending
-if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
-if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
-:skipRcPre
-
-@setlocal
-
-set ERROR_CODE=0
-
-@REM To isolate internal variables from possible post scripts, we use another setlocal
-@setlocal
-
-@REM ==== START VALIDATION ====
-if not "%JAVA_HOME%" == "" goto OkJHome
-
-echo.
-echo Error: JAVA_HOME not found in your environment. >&2
-echo Please set the JAVA_HOME variable in your environment to match the >&2
-echo location of your Java installation. >&2
-echo.
-goto error
-
-:OkJHome
-if exist "%JAVA_HOME%\bin\java.exe" goto init
-
-echo.
-echo Error: JAVA_HOME is set to an invalid directory. >&2
-echo JAVA_HOME = "%JAVA_HOME%" >&2
-echo Please set the JAVA_HOME variable in your environment to match the >&2
-echo location of your Java installation. >&2
-echo.
-goto error
-
-@REM ==== END VALIDATION ====
-
-:init
-
-@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
-@REM Fallback to current working directory if not found.
-
-set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
-IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
-
-set EXEC_DIR=%CD%
-set WDIR=%EXEC_DIR%
-:findBaseDir
-IF EXIST "%WDIR%"\.mvn goto baseDirFound
-cd ..
-IF "%WDIR%"=="%CD%" goto baseDirNotFound
-set WDIR=%CD%
-goto findBaseDir
-
-:baseDirFound
-set MAVEN_PROJECTBASEDIR=%WDIR%
-cd "%EXEC_DIR%"
-goto endDetectBaseDir
-
-:baseDirNotFound
-set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
-cd "%EXEC_DIR%"
-
-:endDetectBaseDir
-
-IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
-
-@setlocal EnableExtensions EnableDelayedExpansion
-for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
-@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
-
-:endReadAdditionalConfig
-
-SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
-
-set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
-set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
-
-%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
-if ERRORLEVEL 1 goto error
-goto end
-
-:error
-set ERROR_CODE=1
-
-:end
-@endlocal & set ERROR_CODE=%ERROR_CODE%
-
-if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
-@REM check for post script, once with legacy .bat ending and once with .cmd ending
-if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
-if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
-:skipRcPost
-
-@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
-if "%MAVEN_BATCH_PAUSE%" == "on" pause
-
-if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
-
-exit /B %ERROR_CODE%
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
+FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ echo Found %WRAPPER_JAR%
+) else (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
+ echo Finished downloading %WRAPPER_JAR%
+)
+@REM End of extension
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
index 86cda27f0..1568fb9ed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,7 @@
jflexjflex-maven-plugintestsuite
+ report-module
@@ -103,15 +104,21 @@
+
+ com.google.code.findbugs
+ jsr305
+ 3.0.2
+ com.google.guavaguava
+
20.0com.google.truthtruth
- 0.36
+ 0.42commons-io
@@ -131,7 +138,7 @@
org.apache.antant
- 1.9.7
+ 1.10.5org.apache.maven
@@ -151,7 +158,7 @@
org.apache.maven.plugin-toolsmaven-plugin-annotations
- 3.5
+ 3.5.2org.apache.maven.plugin-testing
@@ -166,7 +173,7 @@
org.mockitomockito-core
- 2.11.0
+ 2.23.0test
@@ -175,6 +182,11 @@
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.2
+ de.jflexcup-maven-plugin
@@ -183,7 +195,7 @@
com.coveofmt-maven-plugin
- 2.2.0
+ 2.5.0maven-compiler-plugin
@@ -274,16 +286,18 @@
maven-surefire-plugin2.20.1
-
- org.codehaus.mojo
- findbugs-maven-plugin
- 3.0.5
-
+
+ maven-compiler-plugin
+
+ 1.7
+ 1.7
+
+ maven-site-plugin
@@ -302,6 +316,24 @@
true
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+
+ prepare-agent
+
+
+
+ generate-code-coverage-report
+ test
+
+ report
+
+
+
+
@@ -316,8 +348,6 @@
indexsummaryplugins
- dependencies
- plugins
@@ -329,20 +359,6 @@
true
-
- org.codehaus.mojo
- findbugs-maven-plugin
-
- true
- Normal
- Default
- target/findbugs
- FindDeadLocalStores,UnreadFields
- de.jflex.*
- true
- true
-
-
@@ -431,8 +447,8 @@
javac-with-errorpronetrue
- 7
- 7
+ 1.7
+ 1.7
diff --git a/report-module/README.md b/report-module/README.md
new file mode 100644
index 000000000..679e79822
--- /dev/null
+++ b/report-module/README.md
@@ -0,0 +1,12 @@
+# Maven reports
+
+This module aggregates reports from other modules.
+
+The reason for this module is that:
+
+- the Maven parent is executed first
+- the reports are created in every module
+- Maven doesn't run the reporting again on the parent.
+
+In particular, this is used to aggregated code coverage of java tests.
+
diff --git a/report-module/pom.xml b/report-module/pom.xml
new file mode 100644
index 000000000..8e875516d
--- /dev/null
+++ b/report-module/pom.xml
@@ -0,0 +1,95 @@
+
+
+ 4.0.0
+
+ de.jflex
+ jflex-parent
+ 1.7.1-SNAPSHOT
+ ../pom.xml
+
+ report-module
+ jar
+ Report aggregator for JFlex Modules
+
+ Aggregates code quality reports for JFlex.
+ The reason it's a separate maven module is because the parent is built first,
+ hence its aggregated reports.
+ Ideally, maven would run a second pass on the parent when it's also an aggregator,
+ but that's not what maven does.
+
+ 2018
+
+
+ regisd
+ Régis Décamps
+
+ developer
+
+ +1
+
+
+
+
+ benjamin.bentmann@udo.edu
+ Benjamin Bentmann
+
+ reviewer
+
+
+
+ support_0384@newplanetsoftware.com
+ John Lindal
+
+ reviewer
+
+
+
+
+
+ de.jflex
+ jflex
+ ${project.version}
+
+
+ de.jflex
+ jflex-maven-plugin
+ ${project.version}
+
+
+ de.jflex
+ cup-maven-plugin
+ 1.0
+
+
+ de.jflex
+ jflex-unicode-maven-plugin
+ ${project.version}
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ jacoco-initialize
+
+ prepare-agent
+
+
+
+ report
+ test
+
+ report-aggregate
+
+
+
+
+
+
+
diff --git a/scripts/README.md b/scripts/README.md
new file mode 100644
index 000000000..0d2feb9e2
--- /dev/null
+++ b/scripts/README.md
@@ -0,0 +1,4 @@
+# CI scripts
+
+Various scripts used by the Continuous Integration; and Travis in particular.
+
diff --git a/scripts/ant-build.sh b/scripts/ant-build.sh
deleted file mode 100755
index 7722ea2e6..000000000
--- a/scripts/ant-build.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-# Build with ant
-
-CWD="$PWD"
-BASEDIR="$(cd "$(dirname "$0")" && pwd -P)"/..
-# Provides the logi function
-source "$BASEDIR"/scripts/logger.sh
-# fail on error
-set -e
-
-logi "Compile with ant"
-cd "$BASEDIR"/jflex; ant gettools build test; cd ..
-
-cd "$CWD"
diff --git a/scripts/bazel.sh b/scripts/bazel.sh
new file mode 100755
index 000000000..eeade1798
--- /dev/null
+++ b/scripts/bazel.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Run bazel on examples
+
+CWD="$PWD"
+BASEDIR="$(cd "$(dirname "$0")" && pwd -P)"/..
+# Provides the logi function
+source "$BASEDIR"/scripts/logger.sh
+# fail on error
+set -e
+
+if [[ $TRAVIS ]]; then
+ BAZEL="bazel --bazelrc=$TRAVIS_BUILD_DIR/.travis.bazelrc --output_user_root=${HOME}/__bazel_travis_root__ --output_base=${HOME}/__bazel_output_base__"
+else
+ BAZEL='bazel'
+fi
+
+logi "Start Bazel"
+logi "==========="
+$BAZEL info
+
+logi "Build everything"
+logi "================"
+$BAZEL build //...
+
+logi "Test everything"
+logi "==============="
+$BAZEL test //...
+
+
+if [[ -n "$CI" ]]; then
+ logi "Shutdown"
+ logi "========"
+ $BAZEL shutdown
+else
+ logi "Done"
+fi
+logi "Done ✅"
+cd "$CWD"
diff --git a/scripts/deploy-source-code.sh b/scripts/deploy-source-code.sh
index 1f65dabea..7cfee0a7f 100755
--- a/scripts/deploy-source-code.sh
+++ b/scripts/deploy-source-code.sh
@@ -35,9 +35,11 @@ update_source() {
logi "Download deps and Compile"
./compile.sh
- logi "Add license files"
- cp ../LICENSE.md .
- cp ../cup/LICENSE LICENSE_CUP
+ logi "Checking licenses"
+ [[ -f LICENSE_CUP ]] || loge "Missing LICENSE_CUP for CUP"
+ [[ -f LICENSE_JFLEX ]] || loge "Missing LICENSE_JFLEX for JFlex"
+ [[ $(head -1 LICENSE_JFLEX | cut -f 1 -d " ") == "JFlex" ]] || loge "JFlex license has bad content"
+
logi "Update git sources"
git add --all
@@ -45,7 +47,10 @@ update_source() {
git status
# Don't commit if the diff is empty.
# git commit fails if the commit is empty, which makes Travis build fail.
- git diff-index --quiet HEAD || git commit -a -m "Update from $version\n\nInitial $gitlog"
+ git diff-index --quiet HEAD || \
+ git commit -a \
+ -m "Update from $version" \
+ -m "Initial $gitlog"
cd ..
}
@@ -72,3 +77,5 @@ if [[ -z "$CI" ]]; then
else
git_push
fi
+
+cd "$CWD"
diff --git a/scripts/logger.sh b/scripts/logger.sh
index 7ba154902..5ac52e41c 100755
--- a/scripts/logger.sh
+++ b/scripts/logger.sh
@@ -15,3 +15,11 @@ function logi {
echo $*
fi
}
+function loge {
+ if [[ $COLOR_CAPABILITY ]]; then
+ printf "${RED}${*}${NC}\n"
+ else
+ echo "[ERROR] ${*}"
+ fi
+ exit 1
+}
diff --git a/scripts/mk-release.sh b/scripts/mk-release.sh
index 77021a82d..9e299067f 100755
--- a/scripts/mk-release.sh
+++ b/scripts/mk-release.sh
@@ -3,9 +3,6 @@
# fail on error
set -e
-# a hack for enabling ant builds outside the repo until we figure out something better
-CUP_URL="https://raw.githubusercontent.com/jflex-de/jflex/05632859c94c348dee7d243e4a36bd656c132e96/cup/cup/java-cup-11b.jar"
-
VERSION="1.7.1-SNAPSHOT"
JFLEX_JAR="jflex-full-$VERSION.jar"
@@ -16,7 +13,7 @@ GPG=gpg
KEY=84A70085
printf "Clean checkout? "
-stat_results=`git status -s`
+stat_results=$(git status -s)
if [ ! -z "$stat_results" ] ; then
printf "NO!\n\n${stat_results}\nAborting.\n"
exit 1
@@ -44,9 +41,6 @@ echo "------[ Packaging jflex ]"
cp ../../pom.xml parent.xml
perl -pi -e "s|../pom.xml|parent.xml|" pom.xml
-# hack for ant build outside repo
-perl -pi -e "s|||" build.xml
-
# build things
"$MVN" package
diff --git a/scripts/mvn-install-fastbuild.sh b/scripts/mvn-install-fastbuild.sh
new file mode 100755
index 000000000..ec05f41de
--- /dev/null
+++ b/scripts/mvn-install-fastbuild.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+EXTRA_PROJECTS=$1
+
+BASEDIR="$(cd "$(dirname "$0")" && pwd -P)"/..
+# Provides the logi function
+source "$BASEDIR"/scripts/logger.sh
+MVN="$BASEDIR"/mvnw
+
+QUIET=""
+if [[ "$TRAVIS" ]]; then
+ # Quiet mode shows errors only.
+ QUIET="--quiet"
+fi
+
+# TODO(regisd) Define the list of packages via the profile
+logi "Build and install JFlex only (-P fastbuild)"
+cd "$BASEDIR"
+"$MVN" ${QUIET} -Pfastbuild -pl .,cup,cup/cup,cup/cup_runtime,cup-maven-plugin,jflex install
+
+if [[ -n "$EXTRA_PROJECTS" ]]; then
+ "$MVN" ${QUIET} -Pfastbuild -pl "$EXTRA_PROJECTS" install
+fi
+
+cd "$CWD"
+
diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh
index fe45e0723..d1ae4051d 100755
--- a/scripts/run-tests.sh
+++ b/scripts/run-tests.sh
@@ -4,22 +4,21 @@ CWD="$PWD"
BASEDIR="$(cd "$(dirname "$0")" && pwd -P)"/..
# Provides the logi function
source "$BASEDIR"/scripts/logger.sh
-# Maven executable
-MVN="$BASEDIR"/mvnw
# fail on error
set -e
-echo '============================== JAVA VERSION =============================='
-java -version
-javac -version
-echo '============================================================================'
+if [[ $TRAVIS ]]; then
+ loge "This script is only for manual invocation"
+ exit 1
+fi
# Clean environment
-if [[ ! $TRAVIS ]]; then
- "$BASEDIR"/scripts/clean.sh
-fi
+"$BASEDIR"/scripts/clean.sh
# Travis then runs _in parallel_ (but we do it in sequence)
+if [[ -z "$TEST_SUITE" || "$TEST_SUITE" == "java-format" ]]; then
+ "$BASEDIR"/scripts/test-java-format.sh
+fi
if [[ -z "$TEST_SUITE" || "$TEST_SUITE" == "unit" ]]; then
"$BASEDIR"/scripts/test-unit.sh
fi
@@ -28,6 +27,10 @@ if [[ -z "$TEST_SUITE" || "$TEST_SUITE" == "regression" ]]; then
fi
if [[ -z "$TEST_SUITE" || "$TEST_SUITE" == "ant" ]]; then
"$BASEDIR"/scripts/ant-build.sh
+ "$BASEDIR"/scripts/test-examples.sh
+fi
+if [[ -z "$TEST_SUITE" || "$TEST_SUITE" == "bazel" ]]; then
+ "$BASEDIR"/scripts/bazel.sh
fi
logi "Success"
diff --git a/scripts/send-code-coverage.sh b/scripts/send-code-coverage.sh
new file mode 100755
index 000000000..cb17ca4d9
--- /dev/null
+++ b/scripts/send-code-coverage.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+mkdir -p tools
+
+if [[ -z "${CODACY_PROJECT_TOKEN}" ]]; then
+ echo "Missing \$CODACY_PROJECT_TOKEN"
+ exit 1
+fi
+if [[ "${TRAVIS_PULL_REQUEST_SLUG}:${TRAVIS_BRANCH}" = ":master" ]]; then
+ # https://app.codacy.com/project/regisd/jflex/dashboard
+ curl -C - -L https://github.com/codacy/codacy-coverage-reporter/releases/download/4.0.3/codacy-coverage-reporter-4.0.3-assembly.jar -o tools/codacy-coverage-reporter.jar
+ echo "Sending code coverage report fo Codacy"
+ java -jar tools/codacy-coverage-reporter.jar report -l Java -r report-module/target/site/jacoco-aggregate/jacoco.xml
+else
+ echo "Only Travis merging in main branch sends code coverage reports"
+fi
diff --git a/scripts/test-examples.sh b/scripts/test-examples.sh
new file mode 100755
index 000000000..f4260b042
--- /dev/null
+++ b/scripts/test-examples.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+# Run unit tests
+
+CWD="$PWD"
+BASEDIR="$(cd "$(dirname "$0")" && pwd -P)"/..
+# Provides the logi function
+source "$BASEDIR"/scripts/logger.sh
+# Maven executable
+MVN="$BASEDIR"/mvnw
+# Exit with error in case of error (see #242)
+set -e
+
+logi "Compile, test and install all"
+logi "============================="
+"$BASEDIR"/scripts/mvn-install-fastbuild.sh jflex-maven-plugin
+
+logi "Run jflex examples with ant"
+logi "==========================="
+# Some tests invoke /bin/jflex which expects the jar in /lib
+cp "$BASEDIR"/jflex/target/jflex-full-*.jar "$BASEDIR"/jflex/lib
+
+cd "$BASEDIR"/jflex/examples
+
+logi "Example: byaccj"
+cd byaccj
+# Maven not supported
+# ant not supported
+# don't assume byacc/j is installed, just run lexer
+make Yylex.java
+cd ..
+
+logi "Example: cup-interpreter"
+cd cup-interpreter
+"$MVN" test
+ant test
+make test
+cd ..
+
+logi "Example: cup-java"
+cd cup-java
+"$MVN" test
+ant test
+make test
+cd ..
+
+logi "Example: cup-lcalc"
+cd cup-lcalc
+"$MVN" test
+# ant test
+# make test
+cd ..
+
+logi "Example: simple"
+cd simple
+"$MVN" test
+ant test
+# make test
+cd ..
+
+logi "Example: standalone"
+cd standalone
+"$MVN" test
+# ant test
+# make test
+cd ..
+
+logi "Example: zero-reader"
+cd zero-reader
+"$MVN" test
+# ant test
+make test
+cd ..
+
+cd "$CWD"
diff --git a/scripts/test-java-format.sh b/scripts/test-java-format.sh
new file mode 100755
index 000000000..4a7d02564
--- /dev/null
+++ b/scripts/test-java-format.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# Run the java-format code style
+TOOLSDIR=buildtools
+CWD="$PWD"
+BASEDIR="$(cd "$(dirname "$0")" && pwd -P)"/..
+# Provides the logi function
+source "$BASEDIR"/scripts/logger.sh
+# fail on error
+set -e
+
+if [[ "_${TRAVIS_JDK_VERSION}" = "_openjdk7" ]]; then
+ logi "Skip google-java-format. Unsupported java version."
+ exit
+fi
+
+function gjf() {
+ directory=$1
+ logi "Checking $directory"
+ java -jar $TOOLSDIR/google-java-format.jar --dry-run --set-exit-if-changed $(find $directory -name '*.java')
+}
+
+logi "Download google-java-format"
+logi "==========================="
+echo "TRAVIS_JDK_VERSION=$TRAVIS_JDK_VERSION"
+mkdir -p $TOOLSDIR
+curl -C - -L https://github.com/google/google-java-format/releases/download/google-java-format-1.6/google-java-format-1.6-all-deps.jar -o $TOOLSDIR/google-java-format.jar
+
+logi "Check java format"
+logi "================="
+java -jar $TOOLSDIR/google-java-format.jar --version
+gjf cup-maven-plugin
+gjf jflex
+gjf jflex-maven-plugin
+gjf jflex-unicode-maven-plugin
+gjf testsuite/jflex-testsuite-maven-plugin
+cd "$CWD"
diff --git a/scripts/test-regression.sh b/scripts/test-regression.sh
index a94d64b7c..abb6d86a6 100755
--- a/scripts/test-regression.sh
+++ b/scripts/test-regression.sh
@@ -10,17 +10,8 @@ MVN="$BASEDIR"/mvnw
# fail on error
set -e
-if [[ $TRAVIS ]]; then
- logi "Compile and install all (no tests)"
- # Travis has "`install: true` and hence jflex needs to be install in local repo
- "$MVN" install -Pfastbuild --quiet
-else
- # On local dev, ./run-tests has already installed all, so we can skip installation
- echo
-fi
-
-
logi "Run regression test cases"
+logi "========================="
# regression test suite must run in its own directory
cd "$BASEDIR"/testsuite/testcases; "$MVN" test
cd "$CWD"
diff --git a/scripts/test-unit.sh b/scripts/test-unit.sh
index 2fe3377af..cf75d109b 100755
--- a/scripts/test-unit.sh
+++ b/scripts/test-unit.sh
@@ -14,38 +14,11 @@ logi "Compile, test and install all"
logi "============================="
# NB: Installs jflex in local repo
# implies: validate, compile, test, package, verify, install
-if [[ $TRAVIS ]]; then
+if [[ "$TRAVIS" ]]; then
# Quiet mode shows errors only.
"$MVN" install --quiet
else
"$MVN" install
fi
-logi "Run jflex examples"
-logi "=================="
-# Some tests invoke /bin/jflex which expects the jar in /lib
-cp "$BASEDIR"/jflex/target/jflex-full-*.jar "$BASEDIR"/jflex/lib
-# Exit with error in case of error (see #242)
-set -x
-
-cd "$BASEDIR"/jflex/examples
-logi "Example: simple-maven"
-cd simple-maven; $MVN test; cd ..
-logi "Example: standalone-maven"
-# Note that mvn is a likely to be a different and older version of Maven.
-cd standalone-maven; $MVN test; cd ..
-logi "Example: cup-maven"
-cd cup-maven; $MVN test; cd ..
-
-logi "Example: byacc/j"
-# don't assume byacc/j is installed, just run lexer
-cd byaccj; make clean; make Yylex.java; cd ..
-logi "Example: interpreter"
-cd interpreter; make clean; make; cd ..
-logi "Example: java"
-cd java; make clean; make; cd ..
-logi "Example: zero-reader"
-cd zero-reader; make clean; make; cd ..
-set +x
-
cd "$CWD"
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 000000000..917fc0fa5
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,9 @@
+# JFlex parent sources
+
+Sources for the JFlex parent.
+
+Mostly contains shared reosources, such as
+
+- Code Checkstyle configuration
+- PMD configuration
+- Maven site configuration
diff --git a/src/main/resources/google_checks.xml b/src/main/resources/google_checks.xml
new file mode 100644
index 000000000..2ad67870f
--- /dev/null
+++ b/src/main/resources/google_checks.xml
@@ -0,0 +1,255 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/site/site.xml b/src/site/site.xml
index eb0aa8e34..feadf6414 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -11,11 +11,6 @@
-
- windows_profile
+
+ jdk_hack
-
- Windows
-
+ (,1.8]
-
- ${java.home}/../lib/tools.jar
-
-
-
- unix_profile
-
-
- Unix
-
-
-
- ${java.home}/../lib/tools.jar
-
-
-
- osx_profile
-
-
- mac
-
-
-
- ${java.home}/../lib/tools.jar
-
+
+
+ sun.jdk
+ tools
+ 1.6.0
+ system
+ ${java.home}/../lib/tools.jar
+
+
@@ -115,19 +105,6 @@
jflex${project.version}
-
-
-
-
-
-
-
- sun.jdk
- tools
- 1.5.0
- system
- ${toolsjar}
- org.apache.maven.plugin-toolsmaven-plugin-annotations
diff --git a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/CustomClassLoader.java b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/CustomClassLoader.java
index 61c848cb7..1cfffc93a 100755
--- a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/CustomClassLoader.java
+++ b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/CustomClassLoader.java
@@ -2,10 +2,11 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
@@ -36,9 +37,9 @@ public CustomClassLoader(File... files) {
}
/**
- * Break up a class path string into its items and store in pathItems.
+ * Break up a class path string into its items and store in {@code pathItems}.
*
- *
Uses system property path.separator as delimiter.
+ *
Uses system property {@code path.separator} as delimiter.
*/
private void scanPath(String classPath) {
if (classPath == null) return;
@@ -134,8 +135,7 @@ boolean isJar(String pathEntry) {
private byte[] loadFileData(String path, String fileName) {
File file = new File(path, fileName);
if (file.canRead()) {
- try {
- FileInputStream stream = new FileInputStream(file);
+ try (InputStream stream = Files.newInputStream(Paths.get(file.toString()))) {
ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
@@ -144,7 +144,7 @@ private byte[] loadFileData(String path, String fileName) {
out.close();
return out.toByteArray();
} catch (IOException e) {
- // ignore, maybe another path item succeds
+ // ignore, maybe another path item succeeds
}
}
return null;
@@ -166,7 +166,7 @@ private InputStream getFileEntry(String name, String path) {
File file = new File(path, name);
if (file.canRead()) {
try {
- return new FileInputStream(file);
+ return Files.newInputStream(Paths.get(file.toString()));
} catch (IOException e) {
return null;
}
diff --git a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/DiffStream.java b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/DiffStream.java
index 065c05026..0f7432d04 100755
--- a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/DiffStream.java
+++ b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/DiffStream.java
@@ -6,6 +6,7 @@
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
class DiffStream {
@@ -22,7 +23,7 @@ public DiffStream() {}
*/
private boolean match(String s1, String s2) {
if (s1 == null) return s2 == null;
- return s1.replace('\\', '/').equals(s2.replace('\\', '/'));
+ return Objects.equals(s1.replace('\\', '/'), s2.replace('\\', '/'));
}
public String diff(Reader input, Reader expected) {
@@ -32,7 +33,7 @@ public String diff(Reader input, Reader expected) {
/**
* Compares to streams line by line.
*
- * @return null if they are the same, a String error message otherwise
+ * @return {@code null} if they are the same, a String error message otherwise
* @param diffLines a List of Integer. The line numbers where differences are expected (and to be
* ignored)
* @param input the input stream
diff --git a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/Exec.java b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/Exec.java
index 238fac695..7429c4db5 100755
--- a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/Exec.java
+++ b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/Exec.java
@@ -1,5 +1,6 @@
package jflextest;
+import com.google.common.base.Joiner;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
@@ -44,21 +45,29 @@ private static String[] toArray(List a, List b) {
}
/**
- * Call javac on toCompile in input dir. If toCompile is null, all *.java files below dir will be
- * compiled.
+ * Call javac on javaSourceFiles in input dir. If javaSourceFiles is {@code null}, all {@code
+ * *.java} files in the directory will be compiled.
+ *
+ * @param javaSourceFiles A list of files to compile, or {@code null}
+ * @param dir Source directory.
*/
public static TestResult execJavac(
- String toCompile, File dir, String additionalJars, String encoding) {
+ List javaSourceFiles, File dir, String additionalJars, String encoding)
+ throws FileNotFoundException {
+ // javac fails if an input file doesn't exist
+ checkFilesExist(javaSourceFiles, dir);
Project p = new Project();
- Javac javac = new Javac();
Path path = new Path(p, dir.toString());
+ Javac javac = new Javac();
javac.setProject(p);
javac.setSrcdir(path);
javac.setDestdir(dir);
javac.setTarget(JAVA_VERSION);
javac.setSource(JAVA_VERSION);
javac.setSourcepath(new Path(p, "")); // Only compile explicitly specified source files
- javac.setIncludes(toCompile);
+ if (javaSourceFiles != null) {
+ javac.setIncludes(Joiner.on(' ').join(javaSourceFiles));
+ }
javac.setEncoding(encoding);
Path classPath = javac.createClasspath();
// Locate the jflex jar in the user's Maven local repository
@@ -72,8 +81,7 @@ public static TestResult execJavac(
javac.execute();
return new TestResult(out.toString(), true);
} catch (BuildException e) {
- return new TestResult(
- "Compilation with classpath " + classPath + NL + e + NL + out.toString(), false);
+ return new TestResult(e + NL + out.toString() + NL + "classpath: " + classPath, false);
} finally {
System.setErr(outSafe);
}
@@ -170,4 +178,20 @@ public static TestResult execClass(
return new TestResult(out.toString(outputFileEncoding), success);
}
+
+ /**
+ * Checks that all files exist in the given directory.
+ *
+ * @throws FileNotFoundException when a file doesn't exist.
+ */
+ private static void checkFilesExist(List files, File dir) throws FileNotFoundException {
+ if (files != null) {
+ for (String src : files) {
+ File f = new File(dir, src);
+ if (!f.isFile()) {
+ throw new FileNotFoundException(f.getPath());
+ }
+ }
+ }
+ }
}
diff --git a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/JFlexTestsuiteMojo.java b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/JFlexTestsuiteMojo.java
index e260ca32e..94926ad54 100755
--- a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/JFlexTestsuiteMojo.java
+++ b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/JFlexTestsuiteMojo.java
@@ -32,8 +32,7 @@ public class JFlexTestsuiteMojo extends AbstractMojo {
/** Path of the JFlex uber jar under test. */
@Parameter(
- defaultValue = "${project.parent.basedir}/jflex/target/jflex-full-${project.version}.jar"
- )
+ defaultValue = "${project.parent.basedir}/jflex/target/jflex-full-${project.version}.jar")
private String jflexUberJarFilename;
/** */
@@ -69,7 +68,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
success = Tester.runTests(files, jflexUberJar);
} catch (Exception e) {
- throw new MojoExecutionException("Failed to execute test suite", e);
+ throw new MojoExecutionException("Failed to execute test suite: " + e.getMessage(), e);
}
if (!success) {
throw new MojoFailureException("Test(s) failed.");
diff --git a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/TestCase.java b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/TestCase.java
index 4c1561580..bff991aff 100755
--- a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/TestCase.java
+++ b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/TestCase.java
@@ -2,16 +2,20 @@
import com.google.common.collect.ImmutableList;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
+import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
+import org.apache.maven.plugin.MojoFailureException;
public class TestCase {
@@ -21,8 +25,8 @@ public class TestCase {
/** files on which to invoke jflex */
private List jflexFiles;
- /** command line switches for javac invocation */
- private List javacExtraFiles;
+ /** command line switches for javac invocation, instead of the default {@code .java}. */
+ private List javacFiles;
/** lines with expected differences in jflex output */
private List jflexDiff;
@@ -59,6 +63,7 @@ public class TestCase {
/** get- set- methods */
void setTestName(String s) {
testName = s;
+ // TODO(regisd): The class name should depend on the flex `%class`, not on the test name.
className = testName.substring(0, 1).toUpperCase(Locale.ENGLISH) + testName.substring(1);
}
@@ -82,8 +87,8 @@ void setJflexCmdln(List v) {
jflexCmdln = v;
}
- void setJavacExtraFiles(List v) {
- javacExtraFiles = v;
+ void setJavacFiles(List v) {
+ javacFiles = v;
}
private void setInputOutput(List v) {
@@ -125,7 +130,7 @@ void init(File testDir) {
String name;
for (String file : testDir.list()) {
if (null != commonInputFile) {
- if (file.equals(testName + ".output")) {
+ if (Objects.equals(file, testName + ".output")) {
temp.add(new InputOutput((new File(testDir, testName)).toString(), true));
commonInputFile = (new File(testDir, commonInputFile)).toString();
}
@@ -148,8 +153,17 @@ void init(File testDir) {
testPath = testDir;
}
- void createScanner(File jflexUberJar) throws TestFailException {
- jflexFiles.add((new File(testPath, testName + ".flex")).getPath());
+ void createScanner(File jflexUberJar, boolean verbose)
+ throws TestFailException, MojoFailureException {
+ File lexFile = new File(testPath, testName + ".flex");
+ if (verbose) {
+ System.out.println(String.format("Open lex specification [%s]", lexFile));
+ }
+ if (!lexFile.exists()) {
+ throw new MojoFailureException(
+ "Cannot open lex definition", new FileNotFoundException(lexFile.getPath()));
+ }
+ jflexFiles.add(lexFile.getPath());
// invoke JFlex
TestResult jflexResult = Exec.execJFlex(jflexCmdln, jflexFiles);
// System.out.println(jflexResult);
@@ -189,33 +203,30 @@ void createScanner(File jflexUberJar) throws TestFailException {
}
// Compile Scanner
- StringBuilder builder = new StringBuilder();
- builder.append(new File(testPath, className + ".java").getName());
- if (null != javacExtraFiles) {
- for (String extraFile : javacExtraFiles) {
- builder.append(',').append(extraFile);
- }
- }
- String toCompile = builder.toString();
- if (Tester.verbose) {
- System.out.println("File(s) to Compile: " + toCompile);
- }
- TestResult javacResult =
- Exec.execJavac(toCompile, testPath, jflexUberJar.getAbsolutePath(), javacEncoding);
-
- // System.out.println(javacResult);
+ final List toCompile = getFilesToCompile();
if (Tester.verbose) {
- System.out.println(
- "Compilation successful: "
- + javacResult.getSuccess()
- + " [expected: "
- + !expectJavacFail
- + "]");
+ System.out.println("File(s) to compile: " + toCompile);
}
- if (javacResult.getSuccess() == expectJavacFail) {
- System.out.println("Compilation failed in " + testPath + " for " + toCompile);
- System.out.println(javacResult.getOutput());
- throw new TestFailException();
+ try {
+ TestResult javacResult =
+ Exec.execJavac(toCompile, testPath, jflexUberJar.getAbsolutePath(), javacEncoding);
+
+ // System.out.println(javacResult);
+ if (Tester.verbose) {
+ System.out.println(
+ "Compilation successful: "
+ + javacResult.getSuccess()
+ + " [expected: "
+ + !expectJavacFail
+ + "]");
+ }
+ if (javacResult.getSuccess() == expectJavacFail) {
+ throw new TestFailException(
+ "Compilation failed in " + testPath + " for " + toCompile,
+ new Exception(javacResult.getOutput()));
+ }
+ } catch (FileNotFoundException e) {
+ throw new TestFailException("javac: file not found: ", e);
}
} else {
if (!expectJFlexFail) {
@@ -247,6 +258,20 @@ void createScanner(File jflexUberJar) throws TestFailException {
}
}
+ /** Returns the list of java files to compile. */
+ private List getFilesToCompile() {
+ if (javacFiles == null) {
+ return ImmutableList.of(new File(testPath, className + ".java").getName());
+ } else {
+ ImmutableList.Builder builder = ImmutableList.builder();
+ for (String explicitJavaSrc : javacFiles) {
+ File f = new File(testPath, explicitJavaSrc);
+ builder.add(f.getName());
+ }
+ return builder.build();
+ }
+ }
+
boolean hasMoreToDo() {
// check if there's more files to run scanner main on
return !(inputOutput.isEmpty());
@@ -281,18 +306,14 @@ void runNext(File jflexUberJar) throws TestFailException, UnsupportedEncodingExc
if (expected.exists()) {
DiffStream check = new DiffStream();
String diff;
- try {
+ try (InputStreamReader expectedContent =
+ new InputStreamReader(
+ Files.newInputStream(Paths.get(expected.toString())), outputFileEncoding)) {
diff =
- check.diff(
- jflexDiff,
- new StringReader(classExecResult.getOutput()),
- new InputStreamReader(new FileInputStream(expected), outputFileEncoding));
- } catch (FileNotFoundException e) {
+ check.diff(jflexDiff, new StringReader(classExecResult.getOutput()), expectedContent);
+ } catch (IOException e) {
System.out.println("Error opening file " + expected);
throw new TestFailException();
- } catch (UnsupportedEncodingException e) {
- System.out.println("Unsupported encoding '" + outputFileEncoding + "'");
- throw new TestFailException();
}
if (diff != null) {
System.out.println("Test failed, unexpected output: " + diff);
@@ -307,7 +328,7 @@ void runNext(File jflexUberJar) throws TestFailException, UnsupportedEncodingExc
}
public String toString() {
- return "Testname: "
+ return "Test name: "
+ testName
+ "\nDescription: "
+ description
@@ -318,9 +339,7 @@ public String toString() {
+ "\n"
+ "JFlex Command line: "
+ jflexCmdln
- + (null != javacExtraFiles
- ? " Javac Extra Files: " + Arrays.toString(javacExtraFiles.toArray())
- : "")
+ + (null != javacFiles ? " Javac Files: " + Arrays.toString(javacFiles.toArray()) : "")
+ "\n"
+ "Files to run Tester on "
+ inputOutput
diff --git a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/TestFailException.java b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/TestFailException.java
index 9d539bc2a..799e23eff 100755
--- a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/TestFailException.java
+++ b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/TestFailException.java
@@ -9,4 +9,8 @@ public TestFailException() {
public TestFailException(String message) {
super(message);
}
+
+ public TestFailException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
diff --git a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/Tester.java b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/Tester.java
index d1391b0de..d3d2cf38b 100755
--- a/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/Tester.java
+++ b/testsuite/jflex-testsuite-maven-plugin/src/main/java/jflextest/Tester.java
@@ -3,9 +3,10 @@
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
public class Tester {
@@ -65,7 +66,8 @@ public boolean accept(File f, String name) {
* @param jflexUberJar The JFlex shaded jar
* @return true if all tests succeeded, false otherwise
*/
- public static boolean runTests(List tests, File jflexUberJar) {
+ public static boolean runTests(List tests, File jflexUberJar)
+ throws TestFailException, MojoExecutionException, MojoFailureException {
int successCount = 0;
int totalCount = 0;
@@ -88,7 +90,7 @@ public static boolean runTests(List tests, File jflexUberJar) {
if (verbose) System.out.println("Loaded successfully"); // - Details:\n"+currentTest);
if (currentTest.checkJavaVersion()) {
- currentTest.createScanner(jflexUberJar);
+ currentTest.createScanner(jflexUberJar, verbose);
while (currentTest.hasMoreToDo()) currentTest.runNext(jflexUberJar);
successCount++;
@@ -98,13 +100,9 @@ public static boolean runTests(List tests, File jflexUberJar) {
System.out.println("Test [" + test + "] skipped (JDK version mismatch).");
}
} catch (TestFailException e) {
- System.out.println("Test [" + test + "] failed!");
- } catch (LoadException e) {
- System.out.println("Load Error:" + e.getMessage());
- } catch (IOException e) {
- System.out.println("IO Error:" + e.getMessage());
+ throw new MojoFailureException("Test [" + test + "] failed", e);
} catch (Exception e) {
- e.printStackTrace();
+ throw new MojoExecutionException("Test [" + test.getName() + "] failed to execute", e);
}
}
diff --git a/testsuite/jflex-testsuite-maven-plugin/src/main/jflex/TestLoader.flex b/testsuite/jflex-testsuite-maven-plugin/src/main/jflex/TestLoader.flex
index 5ab21bfb1..0d89dfdae 100644
--- a/testsuite/jflex-testsuite-maven-plugin/src/main/jflex/TestLoader.flex
+++ b/testsuite/jflex-testsuite-maven-plugin/src/main/jflex/TestLoader.flex
@@ -14,7 +14,7 @@ import jflex.sym;
// %debug
-%state DESCR JFLEXCMD JAVAC_EXTRA_FILES LINELIST VERSION
+%state DESCR JFLEXCMD JAVAC_FILES LINELIST VERSION
%{
private StringBuilder buffer = new StringBuilder();
@@ -34,7 +34,7 @@ DIGIT = [0-9]
"description:" { yybegin(DESCR); }
"jflex: " { cmdLine = new ArrayList(); yybegin(JFLEXCMD); }
- "javac-extra-files: " { cmdLine = new ArrayList(); yybegin(JAVAC_EXTRA_FILES); }
+ "javac-files: " { cmdLine = new ArrayList(); yybegin(JAVAC_FILES); }
"jflex-fail:" " "+ "true" { test.setExpectJFlexFail(true); }
"jflex-fail:" " "+ "false" { test.setExpectJFlexFail(false); }
@@ -72,7 +72,7 @@ DIGIT = [0-9]
}
- {
+ {
[^ \t\r\n]+ { cmdLine.add(yytext()); }
\" ~\" { cmdLine.add(yytext().substring(1,yylength()-1));
/* quoted cmdline options */ }
@@ -83,8 +83,8 @@ DIGIT = [0-9]
{NL} { test.setJflexCmdln(cmdLine); yybegin(YYINITIAL); }
-
- {NL} { test.setJavacExtraFiles(cmdLine); yybegin(YYINITIAL); }
+
+ {NL} { test.setJavacFiles(cmdLine); yybegin(YYINITIAL); }
{
[0-9]+ { lineList.add(new Integer(yytext())); }
diff --git a/testsuite/testcases/.gitignore b/testsuite/testcases/.gitignore
deleted file mode 100644
index 337e58f45..000000000
--- a/testsuite/testcases/.gitignore
+++ /dev/null
@@ -1,64 +0,0 @@
-src/test/cases/apiprivate/Private.java
-src/test/cases/arr-return/Arr.java
-src/test/cases/bol/Bol.java
-src/test/cases/buffer/Buffer.java
-src/test/cases/caseless-jflex/Caseless.java
-src/test/cases/caseless-jlex/Caseless.java
-src/test/cases/ccl-16/Ccl.java
-src/test/cases/ccl-bug/Yylex.java
-src/test/cases/ccl-esc/Yylex.java
-src/test/cases/ccl-pre/Ccl2.java
-src/test/cases/ccl-pre/Ccl3.java
-src/test/cases/charclass/Charclass.java
-src/test/cases/count/Count.java
-src/test/cases/ctorarg/Ctorarg.java
-src/test/cases/cupsym/Cupsym.java
-src/test/cases/dot-newline/Dotnewline.java
-src/test/cases/empty-match/*.java
-src/test/cases/eof-min/Eofmin.java
-src/test/cases/eofclose/Eofclose.java
-src/test/cases/eofclose2/Eofclose2.java
-src/test/cases/eol-comment/Eolcomment.java
-src/test/cases/eol-look/Eol.java
-src/test/cases/fixed-look/Fixedlook.java
-src/test/cases/generics/Generics*.java
-src/test/cases/genlook/Genlook.java
-src/test/cases/genlook2/Genlook2.java
-src/test/cases/include/Include.java
-src/test/cases/include-in-rules/IncludeInRules.java
-src/test/cases/include2/Include2.java
-src/test/cases/initthrow-eol/Initthrow.java
-src/test/cases/java/Java.java
-src/test/cases/line-cont/Yylex.java
-src/test/cases/look/Look.java
-src/test/cases/look-macro/Lookmacro.java
-src/test/cases/macro-exp/Macro.java
-src/test/cases/manual-ex/Lexer.java
-src/test/cases/nevermatch/Never.java
-src/test/cases/simple/Simple.java
-src/test/cases/six-digit-unicode-escape/SixDigitUnicodeEscape*.java
-src/test/cases/testloader/Testloader.java
-src/test/cases/unicode-age/UnicodeAge_*.java
-src/test/cases/unicode-blocks/Unicode*.java
-src/test/cases/unicode-caseless/UnicodeCaseless*.java
-src/test/cases/unicode-codepoint-escapes/UnicodeCodePointEscapes*.java
-src/test/cases/unicode-compatibility-properties/UnicodeCompatibilityProperties*.java
-src/test/cases/unicode-derived-core-properties/UnicodeDerivedCoreProperties*.java
-src/test/cases/unicode-digit/UnicodeDecimalDigit*.java
-src/test/cases/unicode-general-category/UnicodeGeneralCategory*.java
-src/test/cases/unicode-general-category/UnicodeNotGeneralCategory*.java
-src/test/cases/unicode-grapheme-break/UnicodeGrapheme*Break*.java
-src/test/cases/unicode-letter/UnicodeLetter*.java
-src/test/cases/unicode-line-break/UnicodeLineBreak*.java
-src/test/cases/unicode-lowercase/UnicodeLowercase*.java
-src/test/cases/unicode-misc-properties/UnicodeMisc*.java
-src/test/cases/unicode-proplist/UnicodePropList*.java
-src/test/cases/unicode-scripts/Unicode*.java
-src/test/cases/unicode-sentence-break/UnicodeSentenceBreak*.java
-src/test/cases/unicode-space/UnicodeWhiteSpace*.java
-src/test/cases/unicode-uppercase/UnicodeUppercase*.java
-src/test/cases/unicode-word/UnicodeWord*.java
-src/test/cases/unicode-word-break/UnicodeWordBreak*.java
-src/test/cases/cup2private/Cup2private.java
-src/test/cases/no-unused/NoUnused.java
-src/test/cases/unused/Unused.java
diff --git a/testsuite/testcases/README.md b/testsuite/testcases/README.md
new file mode 100644
index 000000000..3b59bff6a
--- /dev/null
+++ b/testsuite/testcases/README.md
@@ -0,0 +1,8 @@
+# JFlex regression tests
+
+Run one particular test case with the `testcases` variable.
+
+Example:
+
+ ../../mvnw test -Dtestcases=apiprivate
+
diff --git a/testsuite/testcases/src/test/cases/action-pipe/.gitignore b/testsuite/testcases/src/test/cases/action-pipe/.gitignore
new file mode 100644
index 000000000..74e6d5f15
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/action-pipe/.gitignore
@@ -0,0 +1 @@
+ActionPipe.java
diff --git a/testsuite/testcases/src/test/cases/action-pipe/action-pipe.flex b/testsuite/testcases/src/test/cases/action-pipe/action-pipe.flex
new file mode 100644
index 000000000..7aa6fa2a1
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/action-pipe/action-pipe.flex
@@ -0,0 +1,25 @@
+
+%%
+
+%public
+%class ActionPipe
+
+%int
+
+LineTerminator = \r|\n|\r\n
+
+Identifier = [:jletter:][:jletterdigit:]*
+
+
+%%
+
+
+Identifier { System.out.println(yytext()); }
+
+<> |
+LineTerminator { System.out.println("⏎\n"); }
+
+
+[^] { /* no action */ }
+
+
diff --git a/testsuite/testcases/src/test/cases/action-pipe/action-pipe.output b/testsuite/testcases/src/test/cases/action-pipe/action-pipe.output
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/action-pipe/action-pipe.output
@@ -0,0 +1 @@
+
diff --git a/testsuite/testcases/src/test/cases/action-pipe/action-pipe.test b/testsuite/testcases/src/test/cases/action-pipe/action-pipe.test
new file mode 100644
index 000000000..735e7fab0
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/action-pipe/action-pipe.test
@@ -0,0 +1,7 @@
+name: action-pipe
+
+description:
+Issue #201. Pipe action doesn't compile when first.
+
+# TODO(#201) Fix the pipe action on EOF
+jflex-fail: true
diff --git a/testsuite/testcases/src/test/cases/apiprivate/.gitignore b/testsuite/testcases/src/test/cases/apiprivate/.gitignore
new file mode 100644
index 000000000..23e89acf3
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/apiprivate/.gitignore
@@ -0,0 +1 @@
+Private.java
diff --git a/testsuite/testcases/src/test/cases/apiprivate/private.test b/testsuite/testcases/src/test/cases/apiprivate/private.test
index a49a3d758..cf1d8be88 100755
--- a/testsuite/testcases/src/test/cases/apiprivate/private.test
+++ b/testsuite/testcases/src/test/cases/apiprivate/private.test
@@ -6,6 +6,7 @@ test feature request #513500 [Generate cleaner interfaces], %apiprivate option
jflex: -q
-javac-extra-files: Test.java
+# Verify that the Test class doesn't have access to the Private class,
+javac-files: Private.java Test.java
javac-fail: true
diff --git a/testsuite/testcases/src/test/cases/arr-return/.gitignore b/testsuite/testcases/src/test/cases/arr-return/.gitignore
new file mode 100644
index 000000000..364cc5a50
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/arr-return/.gitignore
@@ -0,0 +1 @@
+Arr.java
diff --git a/testsuite/testcases/src/test/cases/bol/.gitignore b/testsuite/testcases/src/test/cases/bol/.gitignore
new file mode 100644
index 000000000..0d7dc2c74
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/bol/.gitignore
@@ -0,0 +1 @@
+Bol.java
diff --git a/testsuite/testcases/src/test/cases/buffer/.gitignore b/testsuite/testcases/src/test/cases/buffer/.gitignore
new file mode 100644
index 000000000..16ad15c13
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/buffer/.gitignore
@@ -0,0 +1 @@
+Buffer.java
diff --git a/testsuite/testcases/src/test/cases/caseless-jflex/.gitignore b/testsuite/testcases/src/test/cases/caseless-jflex/.gitignore
new file mode 100644
index 000000000..641dfd2ff
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/caseless-jflex/.gitignore
@@ -0,0 +1 @@
+Caseless.java
diff --git a/testsuite/testcases/src/test/cases/caseless-jlex/.gitignore b/testsuite/testcases/src/test/cases/caseless-jlex/.gitignore
new file mode 100644
index 000000000..641dfd2ff
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/caseless-jlex/.gitignore
@@ -0,0 +1 @@
+Caseless.java
diff --git a/testsuite/testcases/src/test/cases/ccl-16/.gitignore b/testsuite/testcases/src/test/cases/ccl-16/.gitignore
new file mode 100644
index 000000000..9c8a22fb8
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/ccl-16/.gitignore
@@ -0,0 +1 @@
+Ccl.java
diff --git a/testsuite/testcases/src/test/cases/ccl-bug/.gitignore b/testsuite/testcases/src/test/cases/ccl-bug/.gitignore
new file mode 100644
index 000000000..bae521e23
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/ccl-bug/.gitignore
@@ -0,0 +1 @@
+Yylex.java
diff --git a/testsuite/testcases/src/test/cases/ccl-bug/ccl-bug.test b/testsuite/testcases/src/test/cases/ccl-bug/ccl-bug.test
index 03d8c6bf9..207e84aa2 100644
--- a/testsuite/testcases/src/test/cases/ccl-bug/ccl-bug.test
+++ b/testsuite/testcases/src/test/cases/ccl-bug/ccl-bug.test
@@ -5,3 +5,5 @@ description:
Generated Yylex.java does not compile, because of missing ","
jflex: --nobak
+
+javac-files: Yylex.java
diff --git a/testsuite/testcases/src/test/cases/ccl-esc/.gitignore b/testsuite/testcases/src/test/cases/ccl-esc/.gitignore
new file mode 100644
index 000000000..bae521e23
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/ccl-esc/.gitignore
@@ -0,0 +1 @@
+Yylex.java
diff --git a/testsuite/testcases/src/test/cases/ccl-esc/ccl.test b/testsuite/testcases/src/test/cases/ccl-esc/ccl.test
index 793ce2c77..e31191c67 100644
--- a/testsuite/testcases/src/test/cases/ccl-esc/ccl.test
+++ b/testsuite/testcases/src/test/cases/ccl-esc/ccl.test
@@ -4,3 +4,5 @@ description:
bug-test for [".."] style character escapes (#467469)
jflex: --nobak --dump
+
+javac-files: Yylex.java
diff --git a/testsuite/testcases/src/test/cases/ccl-pre/.gitignore b/testsuite/testcases/src/test/cases/ccl-pre/.gitignore
new file mode 100644
index 000000000..b8deb723e
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/ccl-pre/.gitignore
@@ -0,0 +1,2 @@
+Ccl2.java
+Ccl3.java
diff --git a/testsuite/testcases/src/test/cases/charclass/.gitignore b/testsuite/testcases/src/test/cases/charclass/.gitignore
new file mode 100644
index 000000000..1af69435a
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/charclass/.gitignore
@@ -0,0 +1 @@
+Charclass.java
diff --git a/testsuite/testcases/src/test/cases/count/.gitignore b/testsuite/testcases/src/test/cases/count/.gitignore
new file mode 100644
index 000000000..772276e5b
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/count/.gitignore
@@ -0,0 +1 @@
+Count.java
diff --git a/testsuite/testcases/src/test/cases/ctorarg/.gitignore b/testsuite/testcases/src/test/cases/ctorarg/.gitignore
new file mode 100644
index 000000000..c7aa701c1
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/ctorarg/.gitignore
@@ -0,0 +1 @@
+Ctorarg.java
diff --git a/testsuite/testcases/src/test/cases/cup2private/.gitignore b/testsuite/testcases/src/test/cases/cup2private/.gitignore
new file mode 100644
index 000000000..ac8a23e60
--- /dev/null
+++ b/testsuite/testcases/src/test/cases/cup2private/.gitignore
@@ -0,0 +1 @@
+Cup2private.java
diff --git a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/ant/CUP2AntTask.java b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/ant/CUP2AntTask.java
index e1aef6b56..01ddd2116 100644
--- a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/ant/CUP2AntTask.java
+++ b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/ant/CUP2AntTask.java
@@ -1,12 +1,5 @@
package edu.tum.cup2.ant;
-import java.io.File;
-import java.util.LinkedList;
-
-import org.apache.tools.ant.*;
-import org.apache.tools.ant.types.Path;
-import org.apache.tools.ant.taskdefs.Javac;
-
import edu.tum.cup2.generator.*;
import edu.tum.cup2.generator.exceptions.GeneratorException;
import edu.tum.cup2.generator.exceptions.ReduceReduceConflict;
@@ -21,418 +14,316 @@
import edu.tum.cup2.parser.tables.LRParsingTable;
import edu.tum.cup2.spec.CUP2Specification;
import edu.tum.cup2.spec.exceptions.IllegalSpecException;
-
+import java.io.File;
+import java.util.LinkedList;
+import java.util.Objects;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.taskdefs.Javac;
+import org.apache.tools.ant.types.Path;
/**
- * Custom CUP2 compile task for Ant.
- * The task can be used to create a parser using CUP2 with a {@link CUP2Specification}.
- * Therefore it creates the class files for the parser with
- * the help of the javac task and creates the .cup2 file (serialization of the parser)
- * using the {@link LRParserSerializer} class.
- *
- * See CUP2AntTask.txt for more information.
- *
+ * Custom CUP2 compile task for Ant. The task can be used to create a parser using CUP2 with a
+ * {@link CUP2Specification}. Therefore it creates the class files for the parser with the help of
+ * the javac task and creates the .cup2 file (serialization of the parser) using the {@link
+ * LRParserSerializer} class.
+ *
+ *
See CUP2AntTask.txt for more information.
+ *
* @author Michael Hausmann
* @author Andreas Wenger
*/
-public class CUP2AntTask
- extends Task
-{
-
- //required attributes
- private String spec = null; //specification name; e.g: edu.tum.cup2.test.SpecCalc4
- private String specdir = null; //root source directory for the specification
- private String destdir = null; //destination directory for CUP2 and the compiled spec
- private Path classpath = null;
-
- //optional attributes
- private String cup2srcdir = null; //source path of cup2
- private String algorithm = null; //generator algorithm; e.g: lr1
- private boolean verbose = false; //print a lot of status messages?
- private String parsetable = null; //where to store the parsing table?
-
- //other fields
- private CUP2Specification cup2Specification = null; //instantiated specification
-
-
- /**
- * executing the cup2 task
- */
- public void execute()
- {
- //print parameter settings
- if (this.verbose)
- this.displayValues();
-
- //check if required attribute spec is set
- if (spec == null || spec.length() == 0)
- {
- log("spec missing!", Project.MSG_ERR);
- }
- //check if required attribute specsrc is set
- else if (specdir == null || specdir.length() == 0)
- {
- log("specsrc is missing!", Project.MSG_ERR);
- }
- //check if required attribute dest is set
- else if (destdir == null || destdir.length() == 0)
- {
- log("dest is missing!", Project.MSG_ERR);
- }
- //check if required classpath is set
- else if (classpath == null)
- {
- log("classpath is missing!", Project.MSG_ERR);
- }
- else
- {
- //check optional attribute classpath
- if (classpath == null)
- log("No classpath set! Is this correct?", Project.MSG_WARN);
-
- //if optional attribute cup2src is set, compile cup2 sources
- if (cup2srcdir != null)
- {
- this.compileCup2();
- }
-
- //compiling the CUPSpecification
- compileSpec();
- if (verbose)
- log(" === Compiling Spec done ===");
-
- //instantiate CUPSpecification
- try
- {
- this.cup2Specification = this.createCUP2Specification();
- }
- catch (InstantiationException e)
- {
- log("InstantiationException when trying to create CUP2Specification");
- e.printStackTrace();
- }
- catch (IllegalSpecException e)
- {
- log("CUP2 Specification invalid : " + e);
- e.printStackTrace();
- }
- catch (ClassNotFoundException e)
- {
- log("ClassNotFoundException when trying to create CUP2Specification");
- e.printStackTrace();
- }
- catch (IllegalAccessException e)
- {
- log("IllegalAccessException when trying to create CUP2Specification");
- e.printStackTrace();
- }
-
- if (this.cup2Specification == null)
- {
- log("Error: could not create CUPSpecification", Project.MSG_ERR);
- }
- else
- {
- //Productivity and reachability is checked
- if (verbose)
- log(" === Checking productivity and reachability ===");
-
- IGrammar orgGram = this.cup2Specification.getGrammar();
- CheckedGrammar cg = new CheckedGrammar(orgGram);
- if (!cg.isReduced())
- {
- log("The grammar is not reduced!", Project.MSG_WARN);
- if (cg.hasNotProductiveNonTerminals())
- {
- log("The grammar contains not productive NonTerminals!", Project.MSG_WARN);
- LinkedList notProductiveNonTerminals = cg
- .getNotProductiveNonTerminals();
- log("Not productive are: " + notProductiveNonTerminals.toString());
-
- }
- if (cg.hasNotReachableNonTerminals())
- {
- log("The grammar contains not reachable NonTerminals!", Project.MSG_WARN);
- LinkedList notReachableNonTerminals = cg
- .getNotReachableNonTerminals();
- log("Not reachable are: " + notReachableNonTerminals.toString());
-
- }
- }
-
- //create serialization
- LRParsingTable table = null;
- try
- {
- if (verbose)
- log(" === Creating parsing table ===");
-
- //create Parsing Table
- LRGenerator, ?> generator = createGenerator(this.cup2Specification);
- table = generator.getParsingTable();
-
- LRParser parser = new LRParser(table);
- if (verbose)
- log(" === Serializing parser ===");
- serializeParser(parser);
- }
- catch (ShiftReduceConflict e)
- {
- log("Shift-Reduce-Conflict during parser generation: " + e.getMessage(),
- Project.MSG_ERR);
- }
- catch (ReduceReduceConflict e)
- {
- log("Reduc-Reduce-Conflict during parser generation: " + e.getMessage(),
- Project.MSG_ERR);
- }
- catch (GeneratorException e)
- {
- log("GeneratorException occured during parser generation: " + e.getMessage(),
- Project.MSG_ERR);
- }
- catch (IllegalSpecException e)
- {
- log("Cup2 Specification invalid : " + e);
- e.printStackTrace();
- }
-
- //print parsing table
- if (this.parsetable != null && parsetable.length() > 0)
- {
- printParsingTable(table, this.parsetable);
- }
- }
- } /*end else*/
- if (verbose)
- log(" === Cup2 Ant Task ended ===", Project.MSG_INFO);
- } /*end of execute*/
-
-
- /**
- * display all field values
- */
- private void displayValues()
- {
- log("cup2 task - attribute settings: \n ========================", Project.MSG_INFO);
- log("spec..........: " + this.spec);
- log("- source......: " + getSpecAbsolutePath());
- log("- serialized..: " + getSerializedSpecAbsolutePath());
- log("specdir.......: " + this.specdir);
- log("cup2srcdir....: " + this.cup2srcdir);
- log("classpath.....: " + this.classpath);
- log("algorithm.....: " + this.algorithm);
- log("verbose.......: " + this.verbose);
- log("parsetable....: " + this.parsetable);
- log(" ========================");
- }
-
-
- /**
- * Compiles CUP2 from its sources.
- */
- private void compileCup2()
- {
- log(" === Compiling CUP2 sources ===", Project.MSG_INFO);
-
- //set params
- Javac jcct = new Javac();
- jcct.setSourcepath(new Path(this.getProject(), cup2srcdir));
- jcct.setSrcdir(new Path(this.getProject(), cup2srcdir));
- jcct.setDestdir(new File(this.destdir));
- jcct.setClasspath(classpath);
-
- jcct.setProject(this.getProject());
-
- //compile cup2 sources
- jcct.execute();
- }
-
-
- /**
- * Compiles the CUP2Specification.
- */
- private void compileSpec()
- {
- //setting params for the compile task
- log(" === Creating parser (Specification = " + this.spec + " Directory = "
- + this.specdir + ")", Project.MSG_INFO);
- Javac jsct = new Javac(); //JavaSpecCompileTaks
- jsct.setProject(this.getProject());
- jsct.setSrcdir(new Path(this.getProject(), specdir));
- jsct.setIncludes(getSpecRelativePath());
- jsct.setClasspath(classpath);
- jsct.setDestdir(new File(destdir));
-
- //compile the spec
- jsct.execute();
- }
-
-
- /**
- * Creates a generator depending on algorithm attribute.
- */
- private LRGenerator extends Object, ? extends Object> createGenerator(
- CUP2Specification spec)
- throws GeneratorException
- {
- LRGenerator extends Object, ? extends Object> generator = null;
- if (verbose)
- log("algorithm = " + algorithm);
- if (this.algorithm == null || this.algorithm.equals("lr1"))
- {
- if (verbose)
- log("instantiating lr1 generator...");
- generator = new LR1Generator(spec);
- }
- else if (this.algorithm.equals("lr0"))
- {
- if (verbose)
- log("instantiating lr0 generator...");
- generator = new LR0Generator(spec);
- }
- else if (this.algorithm.equals("lalr1"))
- {
- if (verbose)
- log("instantiating lalr1 generator...");
- generator = new LALR1Generator(spec);
- }
- return generator;
- }
-
-
- /**
- * Instantiates the {@link CUP2Specification} with reflection.
- */
- @SuppressWarnings("unchecked") private CUP2Specification createCUP2Specification()
- throws ClassNotFoundException, IllegalAccessException, InstantiationException
- {
- Class c = (Class) Class.forName(spec);
- return (CUP2Specification) c.newInstance();
- }
-
-
- /**
- * Saves the parsing table to a file
- * (if the related specification is newer than the
- * cup2 file that is to hold the serialization)
- */
- private void serializeParser(LRParser parser)
- {
- File cup2File = new File(getSerializedSpecAbsolutePath());
- File specFile = new File(getSpecAbsolutePath());
-
- if (verbose) //if verbose = "on" ==> print files and time stamps
- {
- log("specification source file = " + getSpecAbsolutePath());
- log("Cup2 file for serialization = " + cup2File.getAbsolutePath());
- log("specification - last modified = " + specFile.lastModified());
- log("CUP2 file - last modified = " + cup2File.lastModified());
- }
-
- //check if CUP2 file is not older than spec (spec has to be newer)
- if (specFile.lastModified() > cup2File.lastModified() || !cup2File.exists())
- {
- //spec file is newer ==> serialize
-
- if (verbose && !cup2File.exists())
- log("cup2 file for serialization does not yet exist and is created...");
- else if (verbose && specFile.lastModified() > cup2File.lastModified())
- log("Spec file is newer than cup2 file... creating cup2 file");
-
- //create LRParserSerialization object
- LRParserSerialization serial = new LRParserSerialization(cup2File.getAbsolutePath());
-
- //serialize parser
- serial.saveParser(parser);
- }
- else if (verbose)
- {
- log("Specification is older than CUP2 file. No serialization.");
- }
- }
-
-
- /**
- * output the parsing table of the LRParser to a file
- * @param table: Parsing Table of an LRParser
- * @param fileName: filename for the output
- */
- private void printParsingTable(LRParsingTable table, String fileName)
- {
- if (this.verbose)
- {
- log("Printing ParsingTable to: " + fileName);
- }
- File file = new File(fileName);
- LRParsingTableDump.dumpToHTML(table, file);
- }
-
-
- private String getSpecRelativePath()
- {
- return spec.replaceAll("\\.", "/") + ".java";
- }
-
-
- private String getSpecAbsolutePath()
- {
- return specdir + "/" + getSpecRelativePath();
- }
-
-
- private String getSerializedSpecAbsolutePath()
- {
- return destdir + "/" + spec.replaceAll("\\.", "/") + ".cup2";
- }
-
-
- public void setSpec(String spec)
- {
- this.spec = spec;
- }
-
-
- public void setSpecdir(String specdir)
- {
- this.specdir = specdir;
- }
-
-
- public void setDestdir(String destdir)
- {
- this.destdir = destdir;
- }
-
-
- public void addConfiguredClasspath(Path cp)
- {
- this.classpath = cp;
- }
-
-
- public void setCup2srcdir(String cup2srcdir)
- {
- this.cup2srcdir = cup2srcdir;
- }
-
-
- public void setAlgorithm(String s)
- {
- this.algorithm = s.trim().toLowerCase();
- }
-
-
- public void setVerbose(boolean b)
- {
- this.verbose = b;
- }
-
-
- public void setParsetable(String parsetable)
- {
- this.parsetable = parsetable;
- }
-
-
+public class CUP2AntTask extends Task {
+
+ // required attributes
+ private String spec = null; // specification name; e.g: edu.tum.cup2.test.SpecCalc4
+ private String specdir = null; // root source directory for the specification
+ private String destdir = null; // destination directory for CUP2 and the compiled spec
+ private Path classpath = null;
+
+ // optional attributes
+ private String cup2srcdir = null; // source path of cup2
+ private String algorithm = null; // generator algorithm; e.g: lr1
+ private boolean verbose = false; // print a lot of status messages?
+ private String parsetable = null; // where to store the parsing table?
+
+ // other fields
+ private CUP2Specification cup2Specification = null; // instantiated specification
+
+ /** executing the cup2 task */
+ public void execute() {
+ // print parameter settings
+ if (this.verbose) this.displayValues();
+
+ // check if required attribute spec is set
+ if (spec == null || spec.length() == 0) {
+ log("spec missing!", Project.MSG_ERR);
+ }
+ // check if required attribute specsrc is set
+ else if (specdir == null || specdir.length() == 0) {
+ log("specsrc is missing!", Project.MSG_ERR);
+ }
+ // check if required attribute dest is set
+ else if (destdir == null || destdir.length() == 0) {
+ log("dest is missing!", Project.MSG_ERR);
+ }
+ // check if required classpath is set
+ else if (classpath == null) {
+ log("classpath is missing!", Project.MSG_ERR);
+ } else {
+ // check optional attribute classpath
+ if (classpath == null) log("No classpath set! Is this correct?", Project.MSG_WARN);
+
+ // if optional attribute cup2src is set, compile cup2 sources
+ if (cup2srcdir != null) {
+ this.compileCup2();
+ }
+
+ // compiling the CUPSpecification
+ compileSpec();
+ if (verbose) log(" === Compiling Spec done ===");
+
+ // instantiate CUPSpecification
+ try {
+ this.cup2Specification = this.createCUP2Specification();
+ } catch (InstantiationException e) {
+ log("InstantiationException when trying to create CUP2Specification");
+ e.printStackTrace();
+ } catch (IllegalSpecException e) {
+ log("CUP2 Specification invalid : " + e);
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ log("ClassNotFoundException when trying to create CUP2Specification");
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ log("IllegalAccessException when trying to create CUP2Specification");
+ e.printStackTrace();
+ }
+
+ if (this.cup2Specification == null) {
+ log("Error: could not create CUPSpecification", Project.MSG_ERR);
+ } else {
+ // Productivity and reachability is checked
+ if (verbose) log(" === Checking productivity and reachability ===");
+
+ IGrammar orgGram = this.cup2Specification.getGrammar();
+ CheckedGrammar cg = new CheckedGrammar(orgGram);
+ if (!cg.isReduced()) {
+ log("The grammar is not reduced!", Project.MSG_WARN);
+ if (cg.hasNotProductiveNonTerminals()) {
+ log("The grammar contains not productive NonTerminals!", Project.MSG_WARN);
+ LinkedList notProductiveNonTerminals = cg.getNotProductiveNonTerminals();
+ log("Not productive are: " + notProductiveNonTerminals.toString());
+ }
+ if (cg.hasNotReachableNonTerminals()) {
+ log("The grammar contains not reachable NonTerminals!", Project.MSG_WARN);
+ LinkedList notReachableNonTerminals = cg.getNotReachableNonTerminals();
+ log("Not reachable are: " + notReachableNonTerminals.toString());
+ }
+ }
+
+ // create serialization
+ LRParsingTable table = null;
+ try {
+ if (verbose) log(" === Creating parsing table ===");
+
+ // create Parsing Table
+ LRGenerator, ?> generator = createGenerator(this.cup2Specification);
+ table = generator.getParsingTable();
+
+ LRParser parser = new LRParser(table);
+ if (verbose) log(" === Serializing parser ===");
+ serializeParser(parser);
+ } catch (ShiftReduceConflict e) {
+ log("Shift-Reduce-Conflict during parser generation: " + e.getMessage(), Project.MSG_ERR);
+ } catch (ReduceReduceConflict e) {
+ log("Reduc-Reduce-Conflict during parser generation: " + e.getMessage(), Project.MSG_ERR);
+ } catch (GeneratorException e) {
+ log(
+ "GeneratorException occured during parser generation: " + e.getMessage(),
+ Project.MSG_ERR);
+ } catch (IllegalSpecException e) {
+ log("Cup2 Specification invalid : " + e);
+ e.printStackTrace();
+ }
+
+ // print parsing table
+ if (this.parsetable != null && parsetable.length() > 0) {
+ printParsingTable(table, this.parsetable);
+ }
+ }
+ } /*end else*/
+ if (verbose) log(" === Cup2 Ant Task ended ===", Project.MSG_INFO);
+ } /*end of execute*/
+
+ /** display all field values */
+ private void displayValues() {
+ log("cup2 task - attribute settings: \n ========================", Project.MSG_INFO);
+ log("spec..........: " + this.spec);
+ log("- source......: " + getSpecAbsolutePath());
+ log("- serialized..: " + getSerializedSpecAbsolutePath());
+ log("specdir.......: " + this.specdir);
+ log("cup2srcdir....: " + this.cup2srcdir);
+ log("classpath.....: " + this.classpath);
+ log("algorithm.....: " + this.algorithm);
+ log("verbose.......: " + this.verbose);
+ log("parsetable....: " + this.parsetable);
+ log(" ========================");
+ }
+
+ /** Compiles CUP2 from its sources. */
+ private void compileCup2() {
+ log(" === Compiling CUP2 sources ===", Project.MSG_INFO);
+
+ // set params
+ Javac jcct = new Javac();
+ jcct.setSourcepath(new Path(this.getProject(), cup2srcdir));
+ jcct.setSrcdir(new Path(this.getProject(), cup2srcdir));
+ jcct.setDestdir(new File(this.destdir));
+ jcct.setClasspath(classpath);
+
+ jcct.setProject(this.getProject());
+
+ // compile cup2 sources
+ jcct.execute();
+ }
+
+ /** Compiles the CUP2Specification. */
+ private void compileSpec() {
+ // setting params for the compile task
+ log(
+ " === Creating parser (Specification = "
+ + this.spec
+ + " Directory = "
+ + this.specdir
+ + ")",
+ Project.MSG_INFO);
+ Javac jsct = new Javac(); // JavaSpecCompileTaks
+ jsct.setProject(this.getProject());
+ jsct.setSrcdir(new Path(this.getProject(), specdir));
+ jsct.setIncludes(getSpecRelativePath());
+ jsct.setClasspath(classpath);
+ jsct.setDestdir(new File(destdir));
+
+ // compile the spec
+ jsct.execute();
+ }
+
+ /** Creates a generator depending on algorithm attribute. */
+ private LRGenerator extends Object, ? extends Object> createGenerator(CUP2Specification spec)
+ throws GeneratorException {
+ LRGenerator extends Object, ? extends Object> generator = null;
+ if (verbose) log("algorithm = " + algorithm);
+ if (this.algorithm == null || Objects.equals(this.algorithm, "lr1")) {
+ if (verbose) log("instantiating lr1 generator...");
+ generator = new LR1Generator(spec);
+ } else if (Objects.equals(this.algorithm, "lr0")) {
+ if (verbose) log("instantiating lr0 generator...");
+ generator = new LR0Generator(spec);
+ } else if (Objects.equals(this.algorithm, "lalr1")) {
+ if (verbose) log("instantiating lalr1 generator...");
+ generator = new LALR1Generator(spec);
+ }
+ return generator;
+ }
+
+ /** Instantiates the {@link CUP2Specification} with reflection. */
+ @SuppressWarnings("unchecked")
+ private CUP2Specification createCUP2Specification()
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ Class c = (Class) Class.forName(spec);
+ return (CUP2Specification) c.newInstance();
+ }
+
+ /**
+ * Saves the parsing table to a file (if the related specification is newer than the cup2 file
+ * that is to hold the serialization)
+ */
+ private void serializeParser(LRParser parser) {
+ File cup2File = new File(getSerializedSpecAbsolutePath());
+ File specFile = new File(getSpecAbsolutePath());
+
+ if (verbose) // if verbose = "on" ==> print files and time stamps
+ {
+ log("specification source file = " + getSpecAbsolutePath());
+ log("Cup2 file for serialization = " + cup2File.getAbsolutePath());
+ log("specification - last modified = " + specFile.lastModified());
+ log("CUP2 file - last modified = " + cup2File.lastModified());
+ }
+
+ // check if CUP2 file is not older than spec (spec has to be newer)
+ if (specFile.lastModified() > cup2File.lastModified() || !cup2File.exists()) {
+ // spec file is newer ==> serialize
+
+ if (verbose && !cup2File.exists())
+ log("cup2 file for serialization does not yet exist and is created...");
+ else if (verbose && specFile.lastModified() > cup2File.lastModified())
+ log("Spec file is newer than cup2 file... creating cup2 file");
+
+ // create LRParserSerialization object
+ LRParserSerialization serial = new LRParserSerialization(cup2File.getAbsolutePath());
+
+ // serialize parser
+ serial.saveParser(parser);
+ } else if (verbose) {
+ log("Specification is older than CUP2 file. No serialization.");
+ }
+ }
+
+ /**
+ * output the parsing table of the LRParser to a file
+ *
+ * @param table: Parsing Table of an LRParser
+ * @param fileName: filename for the output
+ */
+ private void printParsingTable(LRParsingTable table, String fileName) {
+ if (this.verbose) {
+ log("Printing ParsingTable to: " + fileName);
+ }
+ File file = new File(fileName);
+ LRParsingTableDump.dumpToHTML(table, file);
+ }
+
+ private String getSpecRelativePath() {
+ return spec.replaceAll("\\.", "/") + ".java";
+ }
+
+ private String getSpecAbsolutePath() {
+ return specdir + "/" + getSpecRelativePath();
+ }
+
+ private String getSerializedSpecAbsolutePath() {
+ return destdir + "/" + spec.replaceAll("\\.", "/") + ".cup2";
+ }
+
+ public void setSpec(String spec) {
+ this.spec = spec;
+ }
+
+ public void setSpecdir(String specdir) {
+ this.specdir = specdir;
+ }
+
+ public void setDestdir(String destdir) {
+ this.destdir = destdir;
+ }
+
+ public void addConfiguredClasspath(Path cp) {
+ this.classpath = cp;
+ }
+
+ public void setCup2srcdir(String cup2srcdir) {
+ this.cup2srcdir = cup2srcdir;
+ }
+
+ public void setAlgorithm(String s) {
+ this.algorithm = s.trim().toLowerCase();
+ }
+
+ public void setVerbose(boolean b) {
+ this.verbose = b;
+ }
+
+ public void setParsetable(String parsetable) {
+ this.parsetable = parsetable;
+ }
}
diff --git a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/Automaton.java b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/Automaton.java
index 4f803d371..7baf02f72 100644
--- a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/Automaton.java
+++ b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/Automaton.java
@@ -1,129 +1,100 @@
package edu.tum.cup2.generator;
+import edu.tum.cup2.generator.items.Item;
+import edu.tum.cup2.generator.states.State;
+import edu.tum.cup2.io.IAutomatonVisitor;
+import edu.tum.cup2.io.IVisitedElement;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
-import edu.tum.cup2.generator.items.Item;
-import edu.tum.cup2.generator.states.State;
-import edu.tum.cup2.io.IAutomatonVisitor;
-import edu.tum.cup2.io.IVisitedElement;
-
-
/**
- * An automaton consists of states and edges
- * connecting the states.
- *
+ * An automaton consists of states and edges connecting the states.
+ *
* @author Andreas Wenger
*/
-public class Automaton> implements IVisitedElement
-{
-
- private Set states = Collections.synchronizedSet(new HashSet());
- private Set edges = Collections.synchronizedSet(new HashSet());
- private S startState = null;
-
-
- public Automaton(S startState)
- {
- states.add(startState);
- this.startState = startState;
- }
-
-
- public Set getStates()
- {
- return states;
- }
-
-
- public Set getEdges()
- {
- return edges;
- }
-
-
- public S getStartState()
- {
- return startState;
- }
-
-
- public void visited(IAutomatonVisitor visitor)
- {
- visitor.visit(this);
- }
-
-
- /**
- * Gets all edges starting at the given state.
- * This implementation is not optimized and runs in O(n).
- */
- public LinkedList getEdgesFrom(S state)
- {
- LinkedList ret = new LinkedList();
- for (Edge edge : edges)
- {
- if (edge.getSrc().equals(state))
- ret.add(edge);
- }
- return ret;
- }
-
-
- /**
- * Gets the edge arriving in the given state.
- * This implementation is not optimized and runs in O(n).
- */
- public List getEdgeTo(State> state)
- {
- LinkedList ret = new LinkedList();
- for (Edge edge : edges)
- {
- State> dest = edge.getDest();
- if (dest != null && dest.equals(state))
- ret.add(edge);
- }
- return ret;
- }
-
-
- @SuppressWarnings("unchecked")
- @Override
- public String toString()
- {
- Comparator comp = new Comparator() {
- public int compare(Edge o1, Edge o2)
- {
- return o1.toString().compareTo(o2.toString());
- }
- };
- StringBuffer sb = new StringBuffer();
- LinkedList queue = new LinkedList();
- HashSet set = new HashSet();
- queue.add(getStartState());
- while (!queue.isEmpty())
- {
- S s = queue.poll();
- sb.append(s.toString());
- set.add(s);
- List sortedList = getEdgesFrom(s);
- Collections.sort(sortedList, comp);
- for (Edge e : sortedList)
- {
- if (set.contains(e.getDest()))
- continue;
- State> st = e.getDest();
- if (st != null)
- queue.add((S) st);
-
- }
- }
-
- return sb.toString();// +"\n"+edges.toString();
- }
-
+public class Automaton> implements IVisitedElement {
+
+ private Set states = Collections.synchronizedSet(new HashSet());
+ private Set edges = Collections.synchronizedSet(new HashSet());
+ private S startState = null;
+
+ public Automaton(S startState) {
+ states.add(startState);
+ this.startState = startState;
+ }
+
+ public Set getStates() {
+ return states;
+ }
+
+ public Set getEdges() {
+ return edges;
+ }
+
+ public S getStartState() {
+ return startState;
+ }
+
+ public void visited(IAutomatonVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ /**
+ * Gets all edges starting at the given state. This implementation is not optimized and runs in
+ * O(n).
+ */
+ public LinkedList getEdgesFrom(S state) {
+ LinkedList ret = new LinkedList();
+ for (Edge edge : edges) {
+ if (Objects.equals(edge.getSrc(), state)) ret.add(edge);
+ }
+ return ret;
+ }
+
+ /**
+ * Gets the edge arriving in the given state. This implementation is not optimized and runs in
+ * O(n).
+ */
+ public List getEdgeTo(State> state) {
+ LinkedList ret = new LinkedList();
+ for (Edge edge : edges) {
+ State> dest = edge.getDest();
+ if (dest != null && Objects.equals(dest, state)) ret.add(edge);
+ }
+ return ret;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toString() {
+ Comparator comp =
+ new Comparator() {
+ public int compare(Edge o1, Edge o2) {
+ return o1.toString().compareTo(o2.toString());
+ }
+ };
+ StringBuffer sb = new StringBuffer();
+ LinkedList queue = new LinkedList();
+ HashSet set = new HashSet();
+ queue.add(getStartState());
+ while (!queue.isEmpty()) {
+ S s = queue.poll();
+ sb.append(s.toString());
+ set.add(s);
+ List sortedList = getEdgesFrom(s);
+ Collections.sort(sortedList, comp);
+ for (Edge e : sortedList) {
+ if (set.contains(e.getDest())) continue;
+ State> st = e.getDest();
+ if (st != null) queue.add((S) st);
+ }
+ }
+
+ return sb.toString(); // +"\n"+edges.toString();
+ }
}
diff --git a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/Edge.java b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/Edge.java
index 82f288728..0a3237ec2 100644
--- a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/Edge.java
+++ b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/Edge.java
@@ -6,117 +6,86 @@
import edu.tum.cup2.grammar.Symbol;
import edu.tum.cup2.io.IAutomatonVisitor;
import edu.tum.cup2.io.IVisitedElement;
-
+import java.util.Objects;
/**
* An edge within a LR state transition diagram.
- *
- * An edge is identified by the source {@link State} and a
- * {@link Symbol}, since it is a deterministic finite automata.
- * The destination {@link State} is also saved, because the
- * edges are needed for constructing the parsing table later.
- *
- * The {@link Item} of the source {@link State} is saved too,
- * because we need the corresponding production and its position
- * for assigning semantic actions to shift operations later.
- *
+ *
+ *
An edge is identified by the source {@link State} and a {@link Symbol}, since it is a
+ * deterministic finite automata. The destination {@link State} is also saved, because the edges are
+ * needed for constructing the parsing table later.
+ *
+ *
The {@link Item} of the source {@link State} is saved too, because we need the corresponding
+ * production and its position for assigning semantic actions to shift operations later.
+ *
* @author Andreas Wenger
*/
-public final class Edge
- implements IVisitedElement
-{
+public final class Edge implements IVisitedElement {
+
+ private final State> src, dest;
+ private final Symbol symbol;
+ private final LR0Item srcItem;
+ private final int hashCache;
+
+ /** Edge which leads to another non-accepting state. */
+ public Edge(State> src, Symbol symbol, State> dest, LR0Item srcItem) {
+ this.src = src;
+ this.symbol = symbol;
+ this.dest = dest;
+ this.srcItem = srcItem;
+ this.hashCache = src.hashCode() * 100 + symbol.hashCode();
+ }
+
+ /** Edge which leads to the accepting state. */
+ public static Edge createAcceptEdge(State> src, Symbol symbol) {
+ return new Edge(src, symbol, null, null);
+ }
- private final State> src, dest;
- private final Symbol symbol;
- private final LR0Item srcItem;
- private final int hashCache;
-
-
- /**
- * Edge which leads to another non-accepting state.
- */
- public Edge(State> src, Symbol symbol, State> dest, LR0Item srcItem)
- {
- this.src = src;
- this.symbol = symbol;
- this.dest = dest;
- this.srcItem = srcItem;
- this.hashCache = src.hashCode() * 100 + symbol.hashCode();
- }
-
-
- /**
- * Edge which leads to the accepting state.
- */
- public static Edge createAcceptEdge(State> src, Symbol symbol)
- {
- return new Edge(src, symbol, null, null);
- }
-
-
- public State> getSrc()
- {
- return src;
- }
+ public State> getSrc() {
+ return src;
+ }
-
- public State> getDest()
- {
- return dest;
- }
+ public State> getDest() {
+ return dest;
+ }
-
- public Symbol getSymbol()
- {
- return symbol;
- }
-
-
- public LR0Item getSrcItem()
- {
- return srcItem;
- }
-
-
- public boolean isDestAccepting()
- {
- return dest == null;
- }
-
-
- /**
- * Returns true, if the given object is an edge and if it starts from
- * the same state using the same symbol.
- * The destination state and the source item are not checked!
- */
- @Override public boolean equals(Object obj)
- {
- if (obj instanceof Edge)
- {
- Edge e = (Edge) obj;
- return src.equals(e.src) && symbol.equals(e.symbol);
- }
- return false;
- }
-
-
- @Override public int hashCode()
- {
- return hashCache;
- }
+ public Symbol getSymbol() {
+ return symbol;
+ }
- /**
- * method to accept a visitor (also see "visitor pattern")
- */
- public void visited(IAutomatonVisitor visitor)
- {
- visitor.visit(this);
- }
+ public LR0Item getSrcItem() {
+ return srcItem;
+ }
- @Override
- public String toString() {
- return srcItem + " "+symbol;
+ public boolean isDestAccepting() {
+ return dest == null;
+ }
+
+ /**
+ * Returns true, if the given object is an edge and if it starts from the same state using the
+ * same symbol. The destination state and the source item are not checked!
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Edge) {
+ Edge e = (Edge) obj;
+ return Objects.equals(src, e.src) && Objects.equals(symbol, e.symbol);
}
-
-
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCache;
+ }
+
+ /** method to accept a visitor (also see "visitor pattern") */
+ public void visited(IAutomatonVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ return srcItem + " " + symbol;
+ }
}
diff --git a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/FirstSets.java b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/FirstSets.java
index df86e5831..db8f4af1f 100644
--- a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/FirstSets.java
+++ b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/FirstSets.java
@@ -3,131 +3,104 @@
import static edu.tum.cup2.grammar.SpecialTerminals.Epsilon;
import static edu.tum.cup2.util.CollectionTools.map;
-import java.util.Map;
-
import edu.tum.cup2.generator.terminals.EfficientTerminalSet;
import edu.tum.cup2.grammar.Grammar;
import edu.tum.cup2.grammar.NonTerminal;
import edu.tum.cup2.grammar.Production;
import edu.tum.cup2.grammar.Symbol;
import edu.tum.cup2.grammar.Terminal;
-
+import java.util.Map;
+import java.util.Objects;
/**
- * The FIRST sets of all symbols.
- * This is the set of all terminals that may appear at the beginning
+ * The FIRST sets of all symbols. This is the set of all terminals that may appear at the beginning
* of a string derived from the given symbol.
- *
+ *
* @author Andreas Wenger
*/
-public final class FirstSets
-{
-
- private final Map data;
-
-
-
- /**
- * Computes the FIRST sets of all symbols of the
- * given grammar, using the precomputed set of nullable non-terminals.
- * This algorithm is inspired by ASU99, page 230 (german edition) (rules)
- * and Appel's book, page 51 (rule 3 implementation).
- */
- public FirstSets(Grammar grammar, NullableSet nullableSet)
- {
- Map data = map();
-
- //initialize map for all symbols
- EfficientTerminalSet emptySet = new EfficientTerminalSet(grammar.getTerminals());
- for (Terminal terminal : grammar.getTerminals())
- {
- data.put(terminal, emptySet);
- }
- for (NonTerminal nonTerminal : grammar.getNonTerminals())
- {
- data.put(nonTerminal, emptySet);
- }
-
- //rule 1: if X is a terminal, then FIRST(X) = {X}
- for (Terminal terminal : grammar.getTerminals())
- {
- data.put(terminal, data.get(terminal).plus(terminal));
- }
- data.put(Epsilon, emptySet.plus(Epsilon));
-
- //rule 2: if X → ɛ is a production, add ɛ to FIRST(X)
- for (NonTerminal nullableNonTerminal : nullableSet)
- {
- data.put(nullableNonTerminal, data.get(nullableNonTerminal).plus(Epsilon));
- }
-
- //rule 3: if X is a non-terminal and X → Y1 Y2 ... Yk is
- //a production, then add a to FIRST(X), if a is in FIRST(Yi) for
- //any i and FIRST(Y1) ... FIRST(Yi-1) are all nullable. if all
- //FIRST(Y1) ... FIRST(Yk) are nullable, add ɛ to FIRST(X)
- //(Appel ignores the epsilon, but we do not, according to ASU99)
- boolean changed;
- do
- {
- changed = false;
- for (Production production : grammar.getProductions())
- {
- NonTerminal lhs = production.getLHS();
- //find first not nullable rhs symbol. up to this
- //symbol, add all FIRST-symbols of these rhs symbols to
- //the FIRST-set of the current lhs symbol
- Symbol firstNotNullableSymbol = null;
- for (Symbol symbol : production.getRHS())
- {
- if (!(symbol == Epsilon || nullableSet.contains(symbol)))
- {
- //terminal or not nullable non-terminal, stop
- firstNotNullableSymbol = symbol;
- break;
- }
- else
- {
- //epsilon or nullable non-terminal, so go on, but
- //add their FIRST values
- EfficientTerminalSet to = data.get(lhs);
- EfficientTerminalSet from = data.get(symbol);
- EfficientTerminalSet merged = to.plusAllExceptEpsilon(from);
- data.put(lhs, merged);
- changed |= (!merged.equals(to));
- }
- }
- //first not nullable symbol found? than add its FIRST values.
- //otherwise add epsilon
- if (firstNotNullableSymbol != null)
- {
- EfficientTerminalSet to = data.get(lhs);
- EfficientTerminalSet from = data.get(firstNotNullableSymbol);
- EfficientTerminalSet merged = to.plusAllExceptEpsilon(from);
- data.put(lhs, merged);
- changed |= (!merged.equals(to));
- }
- else
- {
- EfficientTerminalSet before = data.get(lhs);
- EfficientTerminalSet after = before.plus(Epsilon);
- data.put(lhs, after);
- changed |= (!before.equals(after));
- }
- }
- }
- while (changed);
-
- this.data = data;
- }
-
-
- /**
- * Gets the FIRST set for the given symbol.
- */
- public EfficientTerminalSet get(Symbol symbol)
- {
- return data.get(symbol);
- }
-
+public final class FirstSets {
+
+ private final Map data;
+
+ /**
+ * Computes the FIRST sets of all symbols of the given grammar, using the precomputed set of
+ * nullable non-terminals. This algorithm is inspired by ASU99, page 230 (german edition) (rules)
+ * and Appel's book, page 51 (rule 3 implementation).
+ */
+ public FirstSets(Grammar grammar, NullableSet nullableSet) {
+ Map data = map();
+
+ // initialize map for all symbols
+ EfficientTerminalSet emptySet = new EfficientTerminalSet(grammar.getTerminals());
+ for (Terminal terminal : grammar.getTerminals()) {
+ data.put(terminal, emptySet);
+ }
+ for (NonTerminal nonTerminal : grammar.getNonTerminals()) {
+ data.put(nonTerminal, emptySet);
+ }
+
+ // rule 1: if X is a terminal, then FIRST(X) = {X}
+ for (Terminal terminal : grammar.getTerminals()) {
+ data.put(terminal, data.get(terminal).plus(terminal));
+ }
+ data.put(Epsilon, emptySet.plus(Epsilon));
+
+ // rule 2: if X → ɛ is a production, add ɛ to FIRST(X)
+ for (NonTerminal nullableNonTerminal : nullableSet) {
+ data.put(nullableNonTerminal, data.get(nullableNonTerminal).plus(Epsilon));
+ }
+
+ // rule 3: if X is a non-terminal and X → Y1 Y2 ... Yk is
+ // a production, then add a to FIRST(X), if a is in FIRST(Yi) for
+ // any i and FIRST(Y1) ... FIRST(Yi-1) are all nullable. if all
+ // FIRST(Y1) ... FIRST(Yk) are nullable, add ɛ to FIRST(X)
+ // (Appel ignores the epsilon, but we do not, according to ASU99)
+ boolean changed;
+ do {
+ changed = false;
+ for (Production production : grammar.getProductions()) {
+ NonTerminal lhs = production.getLHS();
+ // find first not nullable rhs symbol. up to this
+ // symbol, add all FIRST-symbols of these rhs symbols to
+ // the FIRST-set of the current lhs symbol
+ Symbol firstNotNullableSymbol = null;
+ for (Symbol symbol : production.getRHS()) {
+ if (!(symbol == Epsilon || nullableSet.contains(symbol))) {
+ // terminal or not nullable non-terminal, stop
+ firstNotNullableSymbol = symbol;
+ break;
+ } else {
+ // epsilon or nullable non-terminal, so go on, but
+ // add their FIRST values
+ EfficientTerminalSet to = data.get(lhs);
+ EfficientTerminalSet from = data.get(symbol);
+ EfficientTerminalSet merged = to.plusAllExceptEpsilon(from);
+ data.put(lhs, merged);
+ changed |= (!Objects.equals(merged, to));
+ }
+ }
+ // first not nullable symbol found? than add its FIRST values.
+ // otherwise add epsilon
+ if (firstNotNullableSymbol != null) {
+ EfficientTerminalSet to = data.get(lhs);
+ EfficientTerminalSet from = data.get(firstNotNullableSymbol);
+ EfficientTerminalSet merged = to.plusAllExceptEpsilon(from);
+ data.put(lhs, merged);
+ changed |= (!Objects.equals(merged, to));
+ } else {
+ EfficientTerminalSet before = data.get(lhs);
+ EfficientTerminalSet after = before.plus(Epsilon);
+ data.put(lhs, after);
+ changed |= (!Objects.equals(before, after));
+ }
+ }
+ } while (changed);
+
+ this.data = data;
+ }
+ /** Gets the FIRST set for the given symbol. */
+ public EfficientTerminalSet get(Symbol symbol) {
+ return data.get(symbol);
+ }
}
diff --git a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/FollowSets.java b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/FollowSets.java
index 5b17cc3e3..27d81f9e7 100644
--- a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/FollowSets.java
+++ b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/FollowSets.java
@@ -1,151 +1,136 @@
package edu.tum.cup2.generator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
import edu.tum.cup2.generator.terminals.EfficientTerminalSet;
import edu.tum.cup2.grammar.Grammar;
import edu.tum.cup2.grammar.NonTerminal;
import edu.tum.cup2.grammar.Production;
import edu.tum.cup2.grammar.SpecialTerminals;
import edu.tum.cup2.grammar.Symbol;
-
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
/**
- * Computes the FOLLOW sets of all non-terminals of the given grammar, using the precomputed set of nullable
- * non-terminals and first sets. This algorithm is inspired by ASU99, page 230 (german edition) (rules).
- *
+ * Computes the FOLLOW sets of all non-terminals of the given grammar, using the precomputed set of
+ * nullable non-terminals and first sets. This algorithm is inspired by ASU99, page 230 (german
+ * edition) (rules).
+ *
* @author Gero
*/
-public class FollowSets
-{
- private final Map data;
-
-
- /**
- * @param grammar
- * @param firstSets
- */
- public FollowSets(Grammar grammar, FirstSets firstSets)
- {
- data = new HashMap();
-
- // Initialize data map
- final EfficientTerminalSet emptySet = new EfficientTerminalSet(grammar.getTerminals());
- for (NonTerminal nonTerminal : grammar.getNonTerminals())
- {
- data.put(nonTerminal, emptySet); // Viable because all modifiying operations will create new instances
- }
-
- // Rule 1: For start symbol S, add $ to FOLLOW(S)
- final NonTerminal startSymbol = grammar.getStartProduction().getLHS();
- final EfficientTerminalSet startSet = emptySet.plus(SpecialTerminals.EndOfInputStream);
- data.put(startSymbol, startSet);
-
-
- // Actual algorithm: Apply rule 2 and 3 until nothing changes anymore
- boolean changed;
- do
- {
- changed = false;
-
- for (Production production : grammar.getProductions())
- {
- // Rule 2: For a production A → αBβ, every element of FIRST(β) (w/o ɛ) is an element to FOLLOW(B)
- // Rule 3: For productions A → αB (3.1) or A → αBβ with FIRST(β) containing ɛ (3.2), every element of
- // FOLLOW(A) is also an element of FOLLOW(B)
-
-
- // ### Find B (A → αBβ / A → αB => first non-terminal in rhs) ...
- final List rhs = production.getRHS();
-
- NonTerminal nonTerminalB = null;
- Symbol nextSymbol = null;
-
- final Iterator rhsIt = rhs.iterator();
- for (; rhsIt.hasNext();)
- {
- Symbol symbol = rhsIt.next();
- if (symbol instanceof NonTerminal)
- {
- nonTerminalB = (NonTerminal) symbol;
-
- // Great, found non-terminal B! Check for β...
- if (rhsIt.hasNext())
- {
- nextSymbol = rhsIt.next();
- }
-
- break;
- }
- }
-
- if (nonTerminalB == null)
- {
- // If there's no non-terminal: continue with next production
- continue;
- }
-
-
- // ### Check for rule 2 and 3
- final boolean notLastSymbol = !(nextSymbol == null);
- final NonTerminal nonTerminalA = production.getLHS();
- final EfficientTerminalSet followB = data.get(nonTerminalB);
-
- // Differ between αBβ and αB ...
- if (notLastSymbol)
- {
- // Identified A → αBβ => Apply rule 2: Every element of FIRST(β) (w/o ɛ) is added to FOLLOW(B)
- // Important: β may be a list of Symbols! If a first set for a symbol contains ɛ, the following must be considered, to!
- final Symbol beta = nextSymbol;
- EfficientTerminalSet firstBeta = firstSets.get(beta);
-
- // Aggregate first sets if all sets before contained ɛ
- while (rhsIt.hasNext() && firstBeta.contains(SpecialTerminals.Epsilon))
- {
- Symbol symbol = rhsIt.next();
- final EfficientTerminalSet firstNextBeta = firstSets.get(symbol);
- firstBeta = firstBeta.plusAll(firstNextBeta);
- }
- EfficientTerminalSet newFollowB = followB.plusAllExceptEpsilon(firstBeta);
-
-
- // Check for condition 3.2: FIRST(β) contains ɛ
- if (firstBeta.contains(SpecialTerminals.Epsilon))
- {
- // Apply rule 3: Every element of FOLLOW(A) is also an element of FOLLOW(B)
- final EfficientTerminalSet followA = data.get(nonTerminalA);
- newFollowB = newFollowB.plusAll(followA);
- }
-
-
- // Finish: put new FOLLOW(B) into data map and check for changes
- data.put(nonTerminalB, newFollowB);
- changed |= !newFollowB.equals(followB);
- } else
- {
- // Identified A → αB => Apply rule 3: Every element of FOLLOW(A) is also an element of FOLLOW(B)
- final EfficientTerminalSet followA = data.get(nonTerminalA);
- final EfficientTerminalSet newFollowB = followB.plusAll(followA);
-
-
- // Finish: put new FOLLOW(B) into data map and check for changes
- data.put(nonTerminalB, newFollowB);
- changed |= !newFollowB.equals(followB);
- }
- }
- } while (changed);
- }
-
-
- /**
- * @param nonTerminal
- * @return Gets the FOLLOW set for the given non-terminal.
- */
- public EfficientTerminalSet get(NonTerminal nonTerminal)
- {
- return data.get(nonTerminal);
- }
+public class FollowSets {
+ private final Map data;
+
+ /**
+ * @param grammar
+ * @param firstSets
+ */
+ public FollowSets(Grammar grammar, FirstSets firstSets) {
+ data = new HashMap();
+
+ // Initialize data map
+ final EfficientTerminalSet emptySet = new EfficientTerminalSet(grammar.getTerminals());
+ for (NonTerminal nonTerminal : grammar.getNonTerminals()) {
+ data.put(
+ nonTerminal,
+ emptySet); // Viable because all modifiying operations will create new instances
+ }
+
+ // Rule 1: For start symbol S, add $ to FOLLOW(S)
+ final NonTerminal startSymbol = grammar.getStartProduction().getLHS();
+ final EfficientTerminalSet startSet = emptySet.plus(SpecialTerminals.EndOfInputStream);
+ data.put(startSymbol, startSet);
+
+ // Actual algorithm: Apply rule 2 and 3 until nothing changes anymore
+ boolean changed;
+ do {
+ changed = false;
+
+ for (Production production : grammar.getProductions()) {
+ // Rule 2: For a production A → αBβ, every element of FIRST(β) (w/o ɛ) is an element to
+ // FOLLOW(B)
+ // Rule 3: For productions A → αB (3.1) or A → αBβ with FIRST(β) containing ɛ (3.2), every
+ // element of
+ // FOLLOW(A) is also an element of FOLLOW(B)
+
+ // ### Find B (A → αBβ / A → αB => first non-terminal in rhs) ...
+ final List rhs = production.getRHS();
+
+ NonTerminal nonTerminalB = null;
+ Symbol nextSymbol = null;
+
+ final Iterator rhsIt = rhs.iterator();
+ for (; rhsIt.hasNext(); ) {
+ Symbol symbol = rhsIt.next();
+ if (symbol instanceof NonTerminal) {
+ nonTerminalB = (NonTerminal) symbol;
+
+ // Great, found non-terminal B! Check for β...
+ if (rhsIt.hasNext()) {
+ nextSymbol = rhsIt.next();
+ }
+
+ break;
+ }
+ }
+
+ if (nonTerminalB == null) {
+ // If there's no non-terminal: continue with next production
+ continue;
+ }
+
+ // ### Check for rule 2 and 3
+ final boolean notLastSymbol = !(nextSymbol == null);
+ final NonTerminal nonTerminalA = production.getLHS();
+ final EfficientTerminalSet followB = data.get(nonTerminalB);
+
+ // Differ between αBβ and αB ...
+ if (notLastSymbol) {
+ // Identified A → αBβ => Apply rule 2: Every element of FIRST(β) (w/o ɛ) is added to
+ // FOLLOW(B)
+ // Important: β may be a list of Symbols! If a first set for a symbol contains ɛ, the
+ // following must be considered, to!
+ final Symbol beta = nextSymbol;
+ EfficientTerminalSet firstBeta = firstSets.get(beta);
+
+ // Aggregate first sets if all sets before contained ɛ
+ while (rhsIt.hasNext() && firstBeta.contains(SpecialTerminals.Epsilon)) {
+ Symbol symbol = rhsIt.next();
+ final EfficientTerminalSet firstNextBeta = firstSets.get(symbol);
+ firstBeta = firstBeta.plusAll(firstNextBeta);
+ }
+ EfficientTerminalSet newFollowB = followB.plusAllExceptEpsilon(firstBeta);
+
+ // Check for condition 3.2: FIRST(β) contains ɛ
+ if (firstBeta.contains(SpecialTerminals.Epsilon)) {
+ // Apply rule 3: Every element of FOLLOW(A) is also an element of FOLLOW(B)
+ final EfficientTerminalSet followA = data.get(nonTerminalA);
+ newFollowB = newFollowB.plusAll(followA);
+ }
+
+ // Finish: put new FOLLOW(B) into data map and check for changes
+ data.put(nonTerminalB, newFollowB);
+ changed |= !Objects.equals(newFollowB, followB);
+ } else {
+ // Identified A → αB => Apply rule 3: Every element of FOLLOW(A) is also an element of
+ // FOLLOW(B)
+ final EfficientTerminalSet followA = data.get(nonTerminalA);
+ final EfficientTerminalSet newFollowB = followB.plusAll(followA);
+
+ // Finish: put new FOLLOW(B) into data map and check for changes
+ data.put(nonTerminalB, newFollowB);
+ changed |= !Objects.equals(newFollowB, followB);
+ }
+ }
+ } while (changed);
+ }
+
+ /**
+ * @param nonTerminal
+ * @return Gets the FOLLOW set for the given non-terminal.
+ */
+ public EfficientTerminalSet get(NonTerminal nonTerminal) {
+ return data.get(nonTerminal);
+ }
}
diff --git a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1AutomatonFactory.java b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1AutomatonFactory.java
index cf5f14915..2f83b8a6f 100644
--- a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1AutomatonFactory.java
+++ b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1AutomatonFactory.java
@@ -2,205 +2,184 @@
import static edu.tum.cup2.grammar.SpecialTerminals.EndOfInputStream;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Set;
-
import edu.tum.cup2.generator.exceptions.GeneratorException;
import edu.tum.cup2.generator.items.*;
import edu.tum.cup2.generator.states.*;
import edu.tum.cup2.grammar.Symbol;
-
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Objects;
+import java.util.Set;
/**
* Factory for a LALR(1) automaton.
- *
- * TIDY: remove hashsets/maps from {@link AutomatonFactory} since each
- * factory works differently... at least I think so (Andi).
- *
+ *
+ *
TIDY: remove hashsets/maps from {@link AutomatonFactory} since each factory works
+ * differently... at least I think so (Andi).
+ *
* @author Andreas Wenger
* @author Daniel Altmann
* @author Michael Hausmann
*/
-public class LALR1AutomatonFactory extends AutomatonFactory
-{
-
- private class NumberedEdge
- {
- public final Integer srcState;
- public final Integer destState; //null means: accept
- public final Symbol symbol;
- public final LR1Item srcItem;
-
- public NumberedEdge(Integer srcState, Integer destState, Symbol symbol, LR1Item srcItem)
- {
- this.srcState = srcState;
- this.destState = destState;
- this.symbol = symbol;
- this.srcItem = srcItem;
- }
-
- @Override public boolean equals(Object obj)
- {
- if (obj instanceof NumberedEdge)
- {
- NumberedEdge e = (NumberedEdge) obj;
- return srcState.equals(e.srcState) && symbol.equals(e.symbol);
- }
- return false;
- }
-
-
- @Override public int hashCode()
- {
- return srcState * 100 + symbol.hashCode();
- }
- }
-
-
- /**
- * Create an LALR(1)-Automaton.
- */
- public Automaton createAutomaton(LRGenerator generator,
- GrammarInfo grammarInfo)
- throws GeneratorException
- {
-
- this.generator = generator;
- this.grammarInfo = grammarInfo;
- initCreation();
-
- //hashmap which matches a kernel of a state to its complete state
- HashMap newDFAStates = new HashMap();
-
- //hashmap which matches an integer number to a state (and backwards). this allows merging a state
- //with a new one without changing its number, so that we don't need to update the
- //edges each time we merge statesState
- HashMap numberedStates = new HashMap();
- HashMap statesNumbered = new HashMap();
-
- //but this means also that we need to store the source and destination states
- //of the edges in this format
- HashSet numberedEdges = new HashSet();
-
- //our queue consists of numbers instead of states
- LinkedList newQueue = new LinkedList();
- LR1State state = queue.remove(0);
- numberedStates.put(0, state);
- statesNumbered.put(state, 0);
- newQueue.add(0);
-
- //to find out quickly if a state is already queued, we use an additional hashset
- HashSet queuedStateNumbers = new HashSet();
- queuedStateNumbers.add(0);
-
- //for all states, find their edges to other (possibly new) states
- while (!newQueue.isEmpty())
- //Appel says: "until E and T did not change in this iteration".
- //but: do we really need E here? I ignored it
- {
- //handle next state in queue
- Integer stateNumber = newQueue.removeFirst();
- queuedStateNumbers.remove(stateNumber);
- stateKernel = numberedStates.get(stateNumber); //get kernel of the state
-
- //debug messages
- printDebugMessages();
- state = stateKernel.closure(grammarInfo); //unpack state (from kernel to closure)
- Set shiftedSymbols = new HashSet();
- for (LR1Item item : state.getItems())
- {
-
- if (item.isShiftable())
- {
- Symbol symbol = item.getNextSymbol();
- if (symbol == EndOfInputStream)
- {
- //$-symbol: here we accept
- numberedEdges.add(new NumberedEdge(stateNumber, null, symbol, item));
- }
- else if (!shiftedSymbols.contains(symbol))
- {
- shiftedSymbols.add(symbol);
-
- //terminal or non-terminal
-
- //shift to other state
- LR1State shiftedState = (LR1State) state.goTo(symbol);
- LR0State shiftedStateKernel = shiftedState.getLR0Kernel();
- //its number is still unknown. it depends on the existence of a LR(0)-equal state
- Integer shiftedStateNumber;
-
- //we try to find out if there is already some state which has an equal
- //kernel to the shifted state
- LR1State equalStateLR0 = newDFAStates.get(shiftedStateKernel);
- boolean foundEqualState = (equalStateLR0 != null);
-
- //add the shifted state to the queue (again)?
- boolean addShiftedStateToQueue = false;
-
- if (foundEqualState)
- {
- //in case they are equal we merge the states
- LR1State mergedState = equalStateLR0.merge(shiftedState);
- shiftedStateNumber = statesNumbered.get(equalStateLR0);
-
- //if merged state is different to the old state, new information
- //was found and we have to add it to the queue again
- if (!mergedState.equals(equalStateLR0))
- {
- //replace state in hashmap. its number stays the same.
- statesNumbered.remove(equalStateLR0);
- numberedStates.put(shiftedStateNumber, mergedState);
- statesNumbered.put(mergedState, shiftedStateNumber);
- newDFAStates.put(mergedState.getLR0Kernel(), mergedState);
- addShiftedStateToQueue = true;
- }
- }
- else
- {
- //create new state with new number
- LR1State newState = shiftedState;
- shiftedStateNumber = numberedStates.size();
- newDFAStates.put(newState.getLR0Kernel(), newState);
- numberedStates.put(shiftedStateNumber, newState);
- statesNumbered.put(newState, shiftedStateNumber);
- addShiftedStateToQueue = true;
- }
-
- //add edge
- numberedEdges.add(new NumberedEdge(stateNumber, shiftedStateNumber, symbol, item));
-
- //queue shifted state if requested, but only if not already in queue
- if (addShiftedStateToQueue && !queuedStateNumbers.contains(shiftedStateNumber))
- {
- newQueue.add(shiftedStateNumber);
- queuedStateNumbers.add(shiftedStateNumber);
- }
-
- }
- }
- }
- }
-
- //fill dfaStates
- for (LR1State s : numberedStates.values())
- {
- dfaStates.add(s);
- }
-
- //fill dfaEdges
- for (NumberedEdge e : numberedEdges)
- {
- dfaEdges.add(new Edge(numberedStates.get(e.srcState), e.symbol,
- numberedStates.get(e.destState), e.srcItem.getLR0Kernel()));
- }
-
- printDebugResult();
-
- return ret;
- }
-
+public class LALR1AutomatonFactory extends AutomatonFactory {
+
+ private class NumberedEdge {
+ public final Integer srcState;
+ public final Integer destState; // null means: accept
+ public final Symbol symbol;
+ public final LR1Item srcItem;
+
+ public NumberedEdge(Integer srcState, Integer destState, Symbol symbol, LR1Item srcItem) {
+ this.srcState = srcState;
+ this.destState = destState;
+ this.symbol = symbol;
+ this.srcItem = srcItem;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof NumberedEdge) {
+ NumberedEdge e = (NumberedEdge) obj;
+ return Objects.equals(srcState, e.srcState) && Objects.equals(symbol, e.symbol);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return srcState * 100 + symbol.hashCode();
+ }
+ }
+
+ /** Create an LALR(1)-Automaton. */
+ public Automaton createAutomaton(
+ LRGenerator generator, GrammarInfo grammarInfo) throws GeneratorException {
+
+ this.generator = generator;
+ this.grammarInfo = grammarInfo;
+ initCreation();
+
+ // hashmap which matches a kernel of a state to its complete state
+ HashMap newDFAStates = new HashMap();
+
+ // hashmap which matches an integer number to a state (and backwards). this allows merging a
+ // state
+ // with a new one without changing its number, so that we don't need to update the
+ // edges each time we merge statesState
+ HashMap numberedStates = new HashMap();
+ HashMap statesNumbered = new HashMap();
+
+ // but this means also that we need to store the source and destination states
+ // of the edges in this format
+ HashSet numberedEdges = new HashSet();
+
+ // our queue consists of numbers instead of states
+ LinkedList newQueue = new LinkedList();
+ LR1State state = queue.remove(0);
+ numberedStates.put(0, state);
+ statesNumbered.put(state, 0);
+ newQueue.add(0);
+
+ // to find out quickly if a state is already queued, we use an additional hashset
+ HashSet queuedStateNumbers = new HashSet();
+ queuedStateNumbers.add(0);
+
+ // for all states, find their edges to other (possibly new) states
+ while (!newQueue.isEmpty())
+ // Appel says: "until E and T did not change in this iteration".
+ // but: do we really need E here? I ignored it
+ {
+ // handle next state in queue
+ Integer stateNumber = newQueue.removeFirst();
+ queuedStateNumbers.remove(stateNumber);
+ stateKernel = numberedStates.get(stateNumber); // get kernel of the state
+
+ // debug messages
+ printDebugMessages();
+ state = stateKernel.closure(grammarInfo); // unpack state (from kernel to closure)
+ Set shiftedSymbols = new HashSet();
+ for (LR1Item item : state.getItems()) {
+
+ if (item.isShiftable()) {
+ Symbol symbol = item.getNextSymbol();
+ if (symbol == EndOfInputStream) {
+ // $-symbol: here we accept
+ numberedEdges.add(new NumberedEdge(stateNumber, null, symbol, item));
+ } else if (!shiftedSymbols.contains(symbol)) {
+ shiftedSymbols.add(symbol);
+
+ // terminal or non-terminal
+
+ // shift to other state
+ LR1State shiftedState = (LR1State) state.goTo(symbol);
+ LR0State shiftedStateKernel = shiftedState.getLR0Kernel();
+ // its number is still unknown. it depends on the existence of a LR(0)-equal state
+ Integer shiftedStateNumber;
+
+ // we try to find out if there is already some state which has an equal
+ // kernel to the shifted state
+ LR1State equalStateLR0 = newDFAStates.get(shiftedStateKernel);
+ boolean foundEqualState = (equalStateLR0 != null);
+
+ // add the shifted state to the queue (again)?
+ boolean addShiftedStateToQueue = false;
+
+ if (foundEqualState) {
+ // in case they are equal we merge the states
+ LR1State mergedState = equalStateLR0.merge(shiftedState);
+ shiftedStateNumber = statesNumbered.get(equalStateLR0);
+
+ // if merged state is different to the old state, new information
+ // was found and we have to add it to the queue again
+ if (!Objects.equals(mergedState, equalStateLR0)) {
+ // replace state in hashmap. its number stays the same.
+ statesNumbered.remove(equalStateLR0);
+ numberedStates.put(shiftedStateNumber, mergedState);
+ statesNumbered.put(mergedState, shiftedStateNumber);
+ newDFAStates.put(mergedState.getLR0Kernel(), mergedState);
+ addShiftedStateToQueue = true;
+ }
+ } else {
+ // create new state with new number
+ LR1State newState = shiftedState;
+ shiftedStateNumber = numberedStates.size();
+ newDFAStates.put(newState.getLR0Kernel(), newState);
+ numberedStates.put(shiftedStateNumber, newState);
+ statesNumbered.put(newState, shiftedStateNumber);
+ addShiftedStateToQueue = true;
+ }
+
+ // add edge
+ numberedEdges.add(new NumberedEdge(stateNumber, shiftedStateNumber, symbol, item));
+
+ // queue shifted state if requested, but only if not already in queue
+ if (addShiftedStateToQueue && !queuedStateNumbers.contains(shiftedStateNumber)) {
+ newQueue.add(shiftedStateNumber);
+ queuedStateNumbers.add(shiftedStateNumber);
+ }
+ }
+ }
+ }
+ }
+
+ // fill dfaStates
+ for (LR1State s : numberedStates.values()) {
+ dfaStates.add(s);
+ }
+
+ // fill dfaEdges
+ for (NumberedEdge e : numberedEdges) {
+ dfaEdges.add(
+ new Edge(
+ numberedStates.get(e.srcState),
+ e.symbol,
+ numberedStates.get(e.destState),
+ e.srcItem.getLR0Kernel()));
+ }
+
+ printDebugResult();
+ return ret;
+ }
}
diff --git a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1CPAutomatonFactory.java b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1CPAutomatonFactory.java
index 07e87965b..1f087f997 100644
--- a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1CPAutomatonFactory.java
+++ b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1CPAutomatonFactory.java
@@ -6,11 +6,6 @@
import static edu.tum.cup2.util.CollectionTools.map;
import static edu.tum.cup2.util.CollectionTools.set;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import edu.tum.cup2.generator.exceptions.GeneratorException;
import edu.tum.cup2.generator.items.CPGoToLink;
import edu.tum.cup2.generator.items.LALR1CPItem;
@@ -21,232 +16,215 @@
import edu.tum.cup2.generator.terminals.EfficientTerminalSet;
import edu.tum.cup2.grammar.Symbol;
import edu.tum.cup2.util.Tuple2;
-
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
/**
- * Factory for a LALR(1) automaton, that works without side effects
- * (unlike {@link LALR1CPAutomatonFactory}).
- *
+ * Factory for a LALR(1) automaton, that works without side effects (unlike {@link
+ * LALR1CPAutomatonFactory}).
+ *
* @author Andreas Wenger
* @author Daniel Altmann
* @author Michael Hausmann
*/
-public class LALR1CPAutomatonFactory extends AutomatonFactory
-{
-
-
- /**
- * Create an LALR(1)-Automaton.
- */
- public Automaton createAutomaton(LRGenerator generator,
- GrammarInfo grammarInfo)
- throws GeneratorException
- {
-
- this.generator = generator;
- this.grammarInfo = grammarInfo;
- initCreation();
-
-// long time0 = System.currentTimeMillis();
-
- //create the start state (start production with dot at position 0 and "Placeholder" as lookahead)
- LR0Item startStateKernelItem = this.queue.remove(0).getLR0Kernel().getFirstItem();
- Set startStateItemKernel = set();
- startStateItemKernel.add(startStateKernelItem);
- Set startStateItem = set();
- startStateItem.add(new LALR1CPItem(startStateKernelItem, grammarInfo.getTerminalSet(Placeholder)));
- LALR1CPState startStateKernel = new LALR1CPState(
- startStateItem);
-
- //hashmap which matches a kernel of a state
- //to its complete (with closure) state
- Map kernel2closure = map();
-
- //collected go-to context propagation links
- //(key: source item, value contains target state *closure*)
- Map goToLinks = map();
-
- //which items belong to which state (closure)
- Map itemStates = map();
-
- //set of edges
- Set lr0Edges = set();
-
- //TODO: own function
- {
-
- //initialize queue, which consists of states
- Set queue = set();
- queue.add(startStateKernel);
- kernel2closure.put(startStateKernel, startStateKernel.closure(grammarInfo));
-
- //for all states, find their edges to other (possibly new) states
- while (!queue.isEmpty())
- //Appel says: "until E and T did not change in this iteration".
- //but: do we really need E here? I ignored it
- {
- //handle next state in queue
- LALR1CPState stateKernel = queue.iterator().next();
- queue.remove(stateKernel);
-
- //debug messages
- printDebugMessages();
-
- //first, create a LALR(1)-with-CP-Links automaton and remember the closures
- //for performance reasons
- LALR1CPState state = kernel2closure.get(stateKernel);
- Set shiftedSymbols = new HashSet();
- for (LALR1CPItem item : state.getItems())
- {
- //remember the state this item belongs to
- itemStates.put(item, state);
- //try to shift
- if (item.isShiftable())
- {
- Symbol symbol = item.getNextSymbol();
- if (symbol == EndOfInputStream)
- {
- //$-symbol: here we accept
- lr0Edges.add(createAcceptEdge(stateKernel, symbol)); //GOON: with or without closure?
- }
- else if (shiftedSymbols.add(symbol)) //shift each symbol only once
- {
- //terminal or non-terminal
-
- //shift to other state
- Tuple2> s = state.goToCP(symbol);
- LALR1CPState shiftedStateKernel = s.get1();
- List shiftedStateCPLinks = s.get2();
-
- //we try to find out if there is already some state which has an equal
- //kernel to the shifted state (LALR1CPState equals on kernel)
- LALR1CPState equalStateLALR1CP = kernel2closure.get(shiftedStateKernel);
- LALR1CPState gotoLinkTargetState = equalStateLALR1CP;
- if (equalStateLALR1CP == null)
- {
- //add new state
- LALR1CPState shiftedState = shiftedStateKernel.closure(grammarInfo);
- kernel2closure.put(shiftedStateKernel, shiftedState);
- queue.add(shiftedStateKernel);
- gotoLinkTargetState = shiftedState;
-
- }
-
- //remember CP links (cp link contains closure of target state, not only kernel)
- for (CPGoToLink link : shiftedStateCPLinks)
- {
- LALR1CPItem todoItem = link.getSource();
- if (goToLinks.containsKey(todoItem))
- throw new RuntimeException("Double gotoLink!");
- goToLinks.put(todoItem, link.withTargetState(gotoLinkTargetState));
- }
-
- //add edge
- lr0Edges.add(new Edge(stateKernel, symbol, shiftedStateKernel, item.getLR0Item()));
- }
- }
- }
- }
- }
-
- Map lookaheads = map();
- //TODO: own function
- {
- //now, since we have built the LALR(1)-CP automaton, we compute
- //all lookaheads by just following the CP links. Therefore, we just save the lookaheads
- //for each LALR1CPItem in a hashmap
-
-
- //initialize queue (consisting of kernels) with the start item kernel
- Set queue = set();
- LALR1CPState st = kernel2closure.get(startStateKernel);
- LALR1CPItem firstItem = st.getItemWithLookaheadByLR0Item(startStateKernelItem);
- queue.add(firstItem);
- lookaheads.put(firstItem, firstItem.getLookaheads());
-
- EfficientTerminalSet empty = firstItem.getLookaheads().empty();
- for (LALR1CPState sta: kernel2closure.values()){
- for (LALR1CPItem ite : sta.getItems()){
- if (ite.getPosition()==0) {
- queue.add(ite);
- lookaheads.put(ite,ite.getLookaheads());
- }
- else
- lookaheads.put(ite,empty);
- }
- }
-
- while (!queue.isEmpty())
- {
- LALR1CPItem item = queue.iterator().next();
- queue.remove(item);
- EfficientTerminalSet sourceItemLookaheads = lookaheads.get(item);
-
- //go-to-links: propagate lookaheads to all target items
- CPGoToLink gotoLink = goToLinks.get(item);
- if (gotoLink != null)
- {
- LALR1CPState targetState = gotoLink.getTargetState();
- LALR1CPItem targetItem = targetState.getItemWithLookaheadByLR0Item(gotoLink.getTargetItem());
- //add lookaheads to target item
- //if new lookaheads were found, add target item to the queue
- EfficientTerminalSet before = lookaheads.get(targetItem);
- EfficientTerminalSet after = before.plusAll(sourceItemLookaheads);
- if (!before.equals(after))
- {
- lookaheads.put(targetItem, after);
- queue.add(targetItem);
- }
- }
-
- //closure-links
- for (LR0Item closureLink : item.getClosureLinks())
- {
- LALR1CPState targetState = itemStates.get(item); //same state as current item
- LALR1CPItem targetItem = targetState.getItemWithLookaheadByLR0Item(closureLink);
- //add lookaheads to target item
- //if new lookaheads were found, add target item to the queue
- EfficientTerminalSet before = lookaheads.get(targetItem);
- EfficientTerminalSet after = before.plusAll(sourceItemLookaheads);
- after=after.plusAll(targetItem.getLookaheads());
- if (!before.equals(after))
- {
- lookaheads.put(targetItem, after);
- queue.add(targetItem);
- }
- }
-
- }
- }
-
- //create states and edges from collected information
- Map lalr1CPToLR1Map = map();
- for (LALR1CPState state : kernel2closure.keySet())
- {
- HashSet lr1Items = new HashSet();
- LALR1CPState stateWithClosure = kernel2closure.get(state);
-
- for (LR0Item strippedItem : state.getStrippedItems()){
- LALR1CPItem item = stateWithClosure.getItemWithLookaheadByLR0Item(strippedItem);
- EfficientTerminalSet terminals = lookaheads.get(item);
- lr1Items.add(new LR1Item(strippedItem, terminals));
- }
- LR1State lr1State = new LR1State(lr1Items);
- lalr1CPToLR1Map.put(state, lr1State);
- dfaStates.add(lr1State);
- }
-
- //fill dfaEdges
- for (Edge edge : lr0Edges)
- {
- this.dfaEdges.add(new Edge(lalr1CPToLR1Map.get(edge.getSrc()),
- edge.getSymbol(), lalr1CPToLR1Map.get(edge.getDest()), edge.getSrcItem()));
- }
-
- printDebugResult();
-
- return ret;
- }
-
+public class LALR1CPAutomatonFactory extends AutomatonFactory {
+
+ /** Create an LALR(1)-Automaton. */
+ public Automaton createAutomaton(
+ LRGenerator generator, GrammarInfo grammarInfo) throws GeneratorException {
+
+ this.generator = generator;
+ this.grammarInfo = grammarInfo;
+ initCreation();
+
+ // long time0 = System.currentTimeMillis();
+
+ // create the start state (start production with dot at position 0 and "Placeholder" as
+ // lookahead)
+ LR0Item startStateKernelItem = this.queue.remove(0).getLR0Kernel().getFirstItem();
+ Set startStateItemKernel = set();
+ startStateItemKernel.add(startStateKernelItem);
+ Set startStateItem = set();
+ startStateItem.add(
+ new LALR1CPItem(startStateKernelItem, grammarInfo.getTerminalSet(Placeholder)));
+ LALR1CPState startStateKernel = new LALR1CPState(startStateItem);
+
+ // hashmap which matches a kernel of a state
+ // to its complete (with closure) state
+ Map kernel2closure = map();
+
+ // collected go-to context propagation links
+ // (key: source item, value contains target state *closure*)
+ Map goToLinks = map();
+
+ // which items belong to which state (closure)
+ Map itemStates = map();
+
+ // set of edges
+ Set lr0Edges = set();
+
+ // TODO: own function
+ {
+
+ // initialize queue, which consists of states
+ Set queue = set();
+ queue.add(startStateKernel);
+ kernel2closure.put(startStateKernel, startStateKernel.closure(grammarInfo));
+
+ // for all states, find their edges to other (possibly new) states
+ while (!queue.isEmpty())
+ // Appel says: "until E and T did not change in this iteration".
+ // but: do we really need E here? I ignored it
+ {
+ // handle next state in queue
+ LALR1CPState stateKernel = queue.iterator().next();
+ queue.remove(stateKernel);
+
+ // debug messages
+ printDebugMessages();
+
+ // first, create a LALR(1)-with-CP-Links automaton and remember the closures
+ // for performance reasons
+ LALR1CPState state = kernel2closure.get(stateKernel);
+ Set shiftedSymbols = new HashSet();
+ for (LALR1CPItem item : state.getItems()) {
+ // remember the state this item belongs to
+ itemStates.put(item, state);
+ // try to shift
+ if (item.isShiftable()) {
+ Symbol symbol = item.getNextSymbol();
+ if (symbol == EndOfInputStream) {
+ // $-symbol: here we accept
+ lr0Edges.add(createAcceptEdge(stateKernel, symbol)); // GOON: with or without closure?
+ } else if (shiftedSymbols.add(symbol)) // shift each symbol only once
+ {
+ // terminal or non-terminal
+
+ // shift to other state
+ Tuple2> s = state.goToCP(symbol);
+ LALR1CPState shiftedStateKernel = s.get1();
+ List shiftedStateCPLinks = s.get2();
+
+ // we try to find out if there is already some state which has an equal
+ // kernel to the shifted state (LALR1CPState equals on kernel)
+ LALR1CPState equalStateLALR1CP = kernel2closure.get(shiftedStateKernel);
+ LALR1CPState gotoLinkTargetState = equalStateLALR1CP;
+ if (equalStateLALR1CP == null) {
+ // add new state
+ LALR1CPState shiftedState = shiftedStateKernel.closure(grammarInfo);
+ kernel2closure.put(shiftedStateKernel, shiftedState);
+ queue.add(shiftedStateKernel);
+ gotoLinkTargetState = shiftedState;
+ }
+
+ // remember CP links (cp link contains closure of target state, not only kernel)
+ for (CPGoToLink link : shiftedStateCPLinks) {
+ LALR1CPItem todoItem = link.getSource();
+ if (goToLinks.containsKey(todoItem)) throw new RuntimeException("Double gotoLink!");
+ goToLinks.put(todoItem, link.withTargetState(gotoLinkTargetState));
+ }
+
+ // add edge
+ lr0Edges.add(new Edge(stateKernel, symbol, shiftedStateKernel, item.getLR0Item()));
+ }
+ }
+ }
+ }
+ }
+
+ Map lookaheads = map();
+ // TODO: own function
+ {
+ // now, since we have built the LALR(1)-CP automaton, we compute
+ // all lookaheads by just following the CP links. Therefore, we just save the lookaheads
+ // for each LALR1CPItem in a hashmap
+
+ // initialize queue (consisting of kernels) with the start item kernel
+ Set queue = set();
+ LALR1CPState st = kernel2closure.get(startStateKernel);
+ LALR1CPItem firstItem = st.getItemWithLookaheadByLR0Item(startStateKernelItem);
+ queue.add(firstItem);
+ lookaheads.put(firstItem, firstItem.getLookaheads());
+
+ EfficientTerminalSet empty = firstItem.getLookaheads().empty();
+ for (LALR1CPState sta : kernel2closure.values()) {
+ for (LALR1CPItem ite : sta.getItems()) {
+ if (ite.getPosition() == 0) {
+ queue.add(ite);
+ lookaheads.put(ite, ite.getLookaheads());
+ } else lookaheads.put(ite, empty);
+ }
+ }
+
+ while (!queue.isEmpty()) {
+ LALR1CPItem item = queue.iterator().next();
+ queue.remove(item);
+ EfficientTerminalSet sourceItemLookaheads = lookaheads.get(item);
+
+ // go-to-links: propagate lookaheads to all target items
+ CPGoToLink gotoLink = goToLinks.get(item);
+ if (gotoLink != null) {
+ LALR1CPState targetState = gotoLink.getTargetState();
+ LALR1CPItem targetItem =
+ targetState.getItemWithLookaheadByLR0Item(gotoLink.getTargetItem());
+ // add lookaheads to target item
+ // if new lookaheads were found, add target item to the queue
+ EfficientTerminalSet before = lookaheads.get(targetItem);
+ EfficientTerminalSet after = before.plusAll(sourceItemLookaheads);
+ if (!Objects.equals(before, after)) {
+ lookaheads.put(targetItem, after);
+ queue.add(targetItem);
+ }
+ }
+
+ // closure-links
+ for (LR0Item closureLink : item.getClosureLinks()) {
+ LALR1CPState targetState = itemStates.get(item); // same state as current item
+ LALR1CPItem targetItem = targetState.getItemWithLookaheadByLR0Item(closureLink);
+ // add lookaheads to target item
+ // if new lookaheads were found, add target item to the queue
+ EfficientTerminalSet before = lookaheads.get(targetItem);
+ EfficientTerminalSet after = before.plusAll(sourceItemLookaheads);
+ after = after.plusAll(targetItem.getLookaheads());
+ if (!Objects.equals(before, after)) {
+ lookaheads.put(targetItem, after);
+ queue.add(targetItem);
+ }
+ }
+ }
+ }
+
+ // create states and edges from collected information
+ Map lalr1CPToLR1Map = map();
+ for (LALR1CPState state : kernel2closure.keySet()) {
+ HashSet lr1Items = new HashSet();
+ LALR1CPState stateWithClosure = kernel2closure.get(state);
+
+ for (LR0Item strippedItem : state.getStrippedItems()) {
+ LALR1CPItem item = stateWithClosure.getItemWithLookaheadByLR0Item(strippedItem);
+ EfficientTerminalSet terminals = lookaheads.get(item);
+ lr1Items.add(new LR1Item(strippedItem, terminals));
+ }
+ LR1State lr1State = new LR1State(lr1Items);
+ lalr1CPToLR1Map.put(state, lr1State);
+ dfaStates.add(lr1State);
+ }
+
+ // fill dfaEdges
+ for (Edge edge : lr0Edges) {
+ this.dfaEdges.add(
+ new Edge(
+ lalr1CPToLR1Map.get(edge.getSrc()),
+ edge.getSymbol(),
+ lalr1CPToLR1Map.get(edge.getDest()),
+ edge.getSrcItem()));
+ }
+
+ printDebugResult();
+ return ret;
+ }
}
diff --git a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1ParallelAutomatonFactory.java b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1ParallelAutomatonFactory.java
index 9f0d2634b..557f1b436 100755
--- a/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1ParallelAutomatonFactory.java
+++ b/testsuite/testcases/src/test/cases/cup2private/edu/tum/cup2/generator/LALR1ParallelAutomatonFactory.java
@@ -5,16 +5,6 @@
import static edu.tum.cup2.grammar.SpecialTerminals.Placeholder;
import static edu.tum.cup2.util.CollectionTools.*;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
-
import edu.tum.cup2.generator.exceptions.GeneratorException;
import edu.tum.cup2.generator.items.CPGoToLink;
import edu.tum.cup2.generator.items.LALR1CPItem;
@@ -25,376 +15,389 @@
import edu.tum.cup2.generator.terminals.EfficientTerminalSet;
import edu.tum.cup2.grammar.Symbol;
import edu.tum.cup2.util.Tuple2;
-
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
/**
- * Factory for a LALR(1) automaton, that is computed concurrently.
- * (based on {@link LALR1CPAutomatonFactory}).
- *
+ * Factory for a LALR(1) automaton, that is computed concurrently. (based on {@link
+ * LALR1CPAutomatonFactory}).
+ *
* @author Andreas Wenger
* @author Daniel Altmann
* @author Michael Hausmann
* @author Johannes Schamburger
*/
-public class LALR1ParallelAutomatonFactory extends AutomatonFactory
-{
-
- protected Map kernel2closure;
- protected Map itemStates;
- protected Set lr0Edges;
- protected Map goToLinks;
- private Map lookaheads;
-
- /**
- * Task for the first step of the efficient LALR(1) parser generation.
- * Creates the LR(0) automaton together with context propagation links.
- */
- private class WorkerTaskLALR1 extends WorkerTask {
-
- public WorkerTaskLALR1(LALR1CPState state, ThreadPoolExecutor threadPool, ReentrantLock lock) {
- super(state, threadPool, lock);
- }
-
- /**
- * Handles one state; creates new tasks by shifting.
- * @return 0 - we don't care about the return value, but the {@link Callable}
- * interface forces us to return an Integer.
- */
- public Integer call() {
-
- try {
- //handle next state in queue
-
- //debug messages
- printDebugMessages();
-
- //first, create a LALR(1)-with-CP-Links automaton and remember the closures
- //for performance reasons
- currentState = kernel2closure.get(stateKernel);
-
- Set shiftedSymbols = new HashSet();
- for (LALR1CPItem item : currentState.getItems())
- {
- //remember the state this item belongs to
- itemStates.put(item, currentState);
- //try to shift
- if (item.isShiftable())
- {
- Symbol symbol = item.getNextSymbol();
- if (symbol == EndOfInputStream)
- {
- //$-symbol: here we accept
- lr0Edges.add(createAcceptEdge(stateKernel, symbol)); //GOON: with or without closure?
- }
- else if (shiftedSymbols.add(symbol)) //shift each symbol only once
- {
- //terminal or non-terminal
-
- //shift to other state
- Tuple2> s = currentState.goToCP(symbol);
- LALR1CPState shiftedStateKernel = s.get1();
- List shiftedStateCPLinks = s.get2();
-
- //we try to find out if there is already some state which has an equal
- //kernel to the shifted state (LALR1CPState equals on kernel)
- LALR1CPState equalStateLALR1CP;
- LALR1CPState gotoLinkTargetState;
-
- //we need to synchronize here because we access kernel2closure twice;
- //there must be no interruption between the get() and the put() call
- synchronized(kernel2closure) {
- equalStateLALR1CP = kernel2closure.get(shiftedStateKernel);
- gotoLinkTargetState = equalStateLALR1CP;
- if (equalStateLALR1CP == null)
- {
- //add new state
- LALR1CPState shiftedState = shiftedStateKernel.closure(grammarInfo);
- kernel2closure.put(shiftedStateKernel, shiftedState);
- threadPool.submit(new WorkerTaskLALR1(shiftedStateKernel, threadPool, taskCountLock));
- gotoLinkTargetState = shiftedState;
- }
- }
-
- //remember CP links (cp link contains closure of target state, not only kernel)
- for (CPGoToLink link : shiftedStateCPLinks)
- {
- LALR1CPItem todoItem = link.getSource();
- if(goToLinks.put(todoItem, link.withTargetState(gotoLinkTargetState)) != null) {
- throw new RuntimeException("Double gotoLink!");
- }
- }
-
- //add edge
- lr0Edges.add(new Edge(stateKernel, symbol, shiftedStateKernel, item.getLR0Item()));
- }
- }
- }
-
- decrementTaskCount();
- } catch (Throwable e) {
- e.printStackTrace();
- }
- return 0;
-
- }
-
- }
-
- /**
- * Task for the second step of the efficient LALR(1) parser generation.
- * Propagates the lookahead symbols along the context propagation links.
- */
- private class WorkerTaskCPLinks extends WorkerTask {
-
- private LALR1CPItem currentItem;
-
- public String toString() {
- return currentItem.toString();
- }
-
- public WorkerTaskCPLinks(LALR1CPItem item, ThreadPoolExecutor threadPool, ReentrantLock lock) {
- super(null, threadPool, lock); // we don't care for the current state in this WorkerTask
- currentItem = item;
- }
-
- /**
- * Handles one state; creates new tasks by following context propagation links.
- * @return 0 - we don't care about the return value, but the {@link Callable}
- * interface forces us to return an Integer.
- */
- public Integer call() {
-
- try {
- EfficientTerminalSet sourceItemLookaheads = lookaheads.get(currentItem);
-
- //go-to-links: propagate lookaheads to all target items
- CPGoToLink gotoLink = goToLinks.get(currentItem);
- if (gotoLink != null)
- {
- LALR1CPState targetState = gotoLink.getTargetState();
- LALR1CPItem targetItem = targetState.getItemWithLookaheadByLR0Item(gotoLink.getTargetItem());
- //add lookaheads to target item
- //if new lookaheads were found, create a new WorkerTask for the target item
- synchronized(lookaheads) {
- EfficientTerminalSet before = lookaheads.get(targetItem);
- EfficientTerminalSet after = before.plusAll(sourceItemLookaheads);
- if(!before.equals(after)) {
- lookaheads.put(targetItem,after);
- threadPool.submit(new WorkerTaskCPLinks(targetItem, threadPool, taskCountLock));
- }
- }
- }
-
- //closure-links
- for (LR0Item closureLink : currentItem.getClosureLinks())
- {
- LALR1CPState targetState = itemStates.get(currentItem); //same state as current item
- LALR1CPItem targetItem = targetState.getItemWithLookaheadByLR0Item(closureLink);
- //add lookaheads to target item
- //if new lookaheads were found, create a new WorkerTask for the target item
- synchronized(lookaheads) {
- EfficientTerminalSet before = lookaheads.get(targetItem);
- EfficientTerminalSet after = before.plusAll(sourceItemLookaheads);
- after = after.plusAll(targetItem.getLookaheads());
- if(!before.equals(after)) {
- lookaheads.put(targetItem, after);
- threadPool.submit(new WorkerTaskCPLinks(targetItem, threadPool, taskCountLock));
- }
- }
- }
- } catch (Throwable e) {
- e.printStackTrace();
- }
-
- decrementTaskCount();
-
- return 0;
-
- }
- }
-
- /**
- * Create a LALR(1)-Automaton concurrently.
- * @param generator
- * @param grammarInfo
- * @param numThreads the number of threads that will be used for the creation.
- * @return the generated automaton.
- * @throws GeneratorException
- */
- public Automaton createAutomaton(LRGenerator generator,
- GrammarInfo grammarInfo, int numThreads)
- throws GeneratorException
- {
-
- this.generator = generator;
- this.grammarInfo = grammarInfo;
- this.numThreads = numThreads;
-
- initCreation();
-
- //create the start state (start production with dot at position 0 and "Placeholder" as lookahead)
- LR0Item startStateKernelItem = this.queue.remove(0).getLR0Kernel().getFirstItem();
- Set startStateItemKernel = set();
- startStateItemKernel.add(startStateKernelItem);
- Set startStateItem = set();
- startStateItem.add(new LALR1CPItem(startStateKernelItem, grammarInfo.getTerminalSet(Placeholder)));
- LALR1CPState startStateKernel = new LALR1CPState(
- startStateItem);
-
- kernel2closure = synchronizedMap();
- goToLinks = synchronizedMap();
- itemStates = synchronizedMap();
- lr0Edges = synchronizedSet();
-
- threadPool = new ThreadPoolExecutor(numThreads, numThreads, Long.MAX_VALUE, TimeUnit.NANOSECONDS, new LinkedBlockingQueue());
- taskCountLock = new ReentrantLock();
-
- shutDownThread = new Thread() {
- @Override public void run() {
- try {
- synchronized(threadPool) {
- threadPool.wait();
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- threadPool.shutdown();
- }
- };
- // we need to ensure that the shutDownThread is started before the taskCount can be decremented to 0
- shutDownThread.start();
- // we need to ensure that the shutDownThread is already waiting to be notified
- while(!(shutDownThread.getState()).equals(Thread.State.WAITING)) {
- }
-
- // add one task for state0 to the thread pool and start the thread pool
- LinkedList tasks = new LinkedList();
- kernel2closure.put(startStateKernel, startStateKernel.closure(grammarInfo));
-
- taskCountLock.lock();
- try {
- taskCount = 0;
- } finally {
- taskCountLock.unlock();
- }
- tasks.add(new WorkerTaskLALR1(startStateKernel, threadPool, taskCountLock));
- try {
- threadPool.invokeAll(tasks);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- // wait until the ThreadPool has been shut down
- try {
- shutDownThread.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- lookaheads = synchronizedMap();
-
- //now, since we have built the LALR(1)-CP automaton, we compute
- //all lookaheads by just following the CP links. Therefore, we just save the lookaheads
- //for each LALR1CPItem in a hashmap
-
- final ThreadPoolExecutor threadPoolCP = new ThreadPoolExecutor(numThreads, numThreads, Long.MAX_VALUE, TimeUnit.NANOSECONDS, new LinkedBlockingQueue());
- ReentrantLock taskCountLockCP = new ReentrantLock();
-
- // create a new thread that waits until all tasks are done
- Thread shutDownThreadCP = new Thread() {
- @Override public void run() {
- try {
- synchronized(threadPoolCP) {
- threadPoolCP.wait();
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- threadPoolCP.shutdown();
- }
- };
- shutDownThreadCP.start();
-
- // we need to ensure that the shutDownThread is already waiting to be notified
- while(!(shutDownThreadCP.getState()).equals(Thread.State.WAITING)) {
- }
-
- taskCountLockCP.lock();
- try {
- taskCount = 0;
- } finally {
- taskCountLockCP.unlock();
- }
-
- //initialize queue (consisting of kernels) with the start item kernel
- LinkedList tasksCP = new LinkedList();
-
- LALR1CPState st = kernel2closure.get(startStateKernel);
- LALR1CPItem firstItem = st.getItemWithLookaheadByLR0Item(startStateKernelItem);
- tasksCP.add(new WorkerTaskCPLinks(firstItem, threadPoolCP, taskCountLockCP));
- lookaheads.put(firstItem, firstItem.getLookaheads());
-
- EfficientTerminalSet empty = firstItem.getLookaheads().empty();
- for (LALR1CPState sta: kernel2closure.values()){
- for (LALR1CPItem ite : sta.getItems()){
- if (ite.getPosition()==0) {
- tasksCP.add(new WorkerTaskCPLinks(ite, threadPoolCP, taskCountLockCP));
- lookaheads.put(ite,ite.getLookaheads());
- }
- else
- lookaheads.put(ite,empty);
- }
- }
-
-
- try {
- threadPoolCP.invokeAll(tasksCP);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- // wait until the ThreadPool has been shut down
- try {
- shutDownThreadCP.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- //create states and edges from collected information
- Map lalr1CPToLR1Map = map();
- for (LALR1CPState state : kernel2closure.keySet())
- {
- HashSet lr1Items = new HashSet();
- LALR1CPState stateWithClosure = kernel2closure.get(state);
-
- for (LR0Item strippedItem : state.getStrippedItems()){
- LALR1CPItem item = stateWithClosure.getItemWithLookaheadByLR0Item(strippedItem);
- EfficientTerminalSet terminals = lookaheads.get(item);
- lr1Items.add(new LR1Item(strippedItem, terminals));
- }
- LR1State lr1State = new LR1State(lr1Items);
- lalr1CPToLR1Map.put(state, lr1State);
- dfaStates.add(lr1State);
- }
-
- //fill dfaEdges
- for (Edge edge : lr0Edges)
- {
- this.dfaEdges.add(new Edge(lalr1CPToLR1Map.get(edge.getSrc()),
- edge.getSymbol(), lalr1CPToLR1Map.get(edge.getDest()), edge.getSrcItem()));
- }
-
- printDebugResult();
-
- return ret;
- }
-
- @Override
- public Automaton createAutomaton(
- LRGenerator generator, GrammarInfo grammarInfo)
- throws GeneratorException {
- return createAutomaton(generator, grammarInfo, defaultNumThreads);
- }
-
+public class LALR1ParallelAutomatonFactory extends AutomatonFactory {
+
+ protected Map kernel2closure;
+ protected Map itemStates;
+ protected Set lr0Edges;
+ protected Map goToLinks;
+ private Map lookaheads;
+
+ /**
+ * Task for the first step of the efficient LALR(1) parser generation. Creates the LR(0) automaton
+ * together with context propagation links.
+ */
+ private class WorkerTaskLALR1 extends WorkerTask {
+
+ public WorkerTaskLALR1(LALR1CPState state, ThreadPoolExecutor threadPool, ReentrantLock lock) {
+ super(state, threadPool, lock);
+ }
+
+ /**
+ * Handles one state; creates new tasks by shifting.
+ *
+ * @return 0 - we don't care about the return value, but the {@link Callable} interface forces
+ * us to return an Integer.
+ */
+ public Integer call() {
+
+ try {
+ // handle next state in queue
+
+ // debug messages
+ printDebugMessages();
+
+ // first, create a LALR(1)-with-CP-Links automaton and remember the closures
+ // for performance reasons
+ currentState = kernel2closure.get(stateKernel);
+
+ Set shiftedSymbols = new HashSet();
+ for (LALR1CPItem item : currentState.getItems()) {
+ // remember the state this item belongs to
+ itemStates.put(item, currentState);
+ // try to shift
+ if (item.isShiftable()) {
+ Symbol symbol = item.getNextSymbol();
+ if (symbol == EndOfInputStream) {
+ // $-symbol: here we accept
+ lr0Edges.add(createAcceptEdge(stateKernel, symbol)); // GOON: with or without closure?
+ } else if (shiftedSymbols.add(symbol)) // shift each symbol only once
+ {
+ // terminal or non-terminal
+
+ // shift to other state
+ Tuple2> s = currentState.goToCP(symbol);
+ LALR1CPState shiftedStateKernel = s.get1();
+ List shiftedStateCPLinks = s.get2();
+
+ // we try to find out if there is already some state which has an equal
+ // kernel to the shifted state (LALR1CPState equals on kernel)
+ LALR1CPState equalStateLALR1CP;
+ LALR1CPState gotoLinkTargetState;
+
+ // we need to synchronize here because we access kernel2closure twice;
+ // there must be no interruption between the get() and the put() call
+ synchronized (kernel2closure) {
+ equalStateLALR1CP = kernel2closure.get(shiftedStateKernel);
+ gotoLinkTargetState = equalStateLALR1CP;
+ if (equalStateLALR1CP == null) {
+ // add new state
+ LALR1CPState shiftedState = shiftedStateKernel.closure(grammarInfo);
+ kernel2closure.put(shiftedStateKernel, shiftedState);
+ threadPool.submit(
+ new WorkerTaskLALR1(shiftedStateKernel, threadPool, taskCountLock));
+ gotoLinkTargetState = shiftedState;
+ }
+ }
+
+ // remember CP links (cp link contains closure of target state, not only kernel)
+ for (CPGoToLink link : shiftedStateCPLinks) {
+ LALR1CPItem todoItem = link.getSource();
+ if (goToLinks.put(todoItem, link.withTargetState(gotoLinkTargetState)) != null) {
+ throw new RuntimeException("Double gotoLink!");
+ }
+ }
+
+ // add edge
+ lr0Edges.add(new Edge(stateKernel, symbol, shiftedStateKernel, item.getLR0Item()));
+ }
+ }
+ }
+
+ decrementTaskCount();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+ }
+
+ /**
+ * Task for the second step of the efficient LALR(1) parser generation. Propagates the lookahead
+ * symbols along the context propagation links.
+ */
+ private class WorkerTaskCPLinks extends WorkerTask {
+
+ private LALR1CPItem currentItem;
+
+ public String toString() {
+ return currentItem.toString();
+ }
+
+ public WorkerTaskCPLinks(LALR1CPItem item, ThreadPoolExecutor threadPool, ReentrantLock lock) {
+ super(null, threadPool, lock); // we don't care for the current state in this WorkerTask
+ currentItem = item;
+ }
+
+ /**
+ * Handles one state; creates new tasks by following context propagation links.
+ *
+ * @return 0 - we don't care about the return value, but the {@link Callable} interface forces
+ * us to return an Integer.
+ */
+ public Integer call() {
+
+ try {
+ EfficientTerminalSet sourceItemLookaheads = lookaheads.get(currentItem);
+
+ // go-to-links: propagate lookaheads to all target items
+ CPGoToLink gotoLink = goToLinks.get(currentItem);
+ if (gotoLink != null) {
+ LALR1CPState targetState = gotoLink.getTargetState();
+ LALR1CPItem targetItem =
+ targetState.getItemWithLookaheadByLR0Item(gotoLink.getTargetItem());
+ // add lookaheads to target item
+ // if new lookaheads were found, create a new WorkerTask for the target item
+ synchronized (lookaheads) {
+ EfficientTerminalSet before = lookaheads.get(targetItem);
+ EfficientTerminalSet after = before.plusAll(sourceItemLookaheads);
+ if (!Objects.equals(before, after)) {
+ lookaheads.put(targetItem, after);
+ threadPool.submit(new WorkerTaskCPLinks(targetItem, threadPool, taskCountLock));
+ }
+ }
+ }
+
+ // closure-links
+ for (LR0Item closureLink : currentItem.getClosureLinks()) {
+ LALR1CPState targetState = itemStates.get(currentItem); // same state as current item
+ LALR1CPItem targetItem = targetState.getItemWithLookaheadByLR0Item(closureLink);
+ // add lookaheads to target item
+ // if new lookaheads were found, create a new WorkerTask for the target item
+ synchronized (lookaheads) {
+ EfficientTerminalSet before = lookaheads.get(targetItem);
+ EfficientTerminalSet after = before.plusAll(sourceItemLookaheads);
+ after = after.plusAll(targetItem.getLookaheads());
+ if (!Objects.equals(before, after)) {
+ lookaheads.put(targetItem, after);
+ threadPool.submit(new WorkerTaskCPLinks(targetItem, threadPool, taskCountLock));
+ }
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ decrementTaskCount();
+
+ return 0;
+ }
+ }
+
+ /**
+ * Create a LALR(1)-Automaton concurrently.
+ *
+ * @param generator
+ * @param grammarInfo
+ * @param numThreads the number of threads that will be used for the creation.
+ * @return the generated automaton.
+ * @throws GeneratorException
+ */
+ public Automaton createAutomaton(
+ LRGenerator generator, GrammarInfo grammarInfo, int numThreads)
+ throws GeneratorException {
+
+ this.generator = generator;
+ this.grammarInfo = grammarInfo;
+ this.numThreads = numThreads;
+
+ initCreation();
+
+ // create the start state (start production with dot at position 0 and "Placeholder" as
+ // lookahead)
+ LR0Item startStateKernelItem = this.queue.remove(0).getLR0Kernel().getFirstItem();
+ Set startStateItemKernel = set();
+ startStateItemKernel.add(startStateKernelItem);
+ Set startStateItem = set();
+ startStateItem.add(
+ new LALR1CPItem(startStateKernelItem, grammarInfo.getTerminalSet(Placeholder)));
+ LALR1CPState startStateKernel = new LALR1CPState(startStateItem);
+
+ kernel2closure = synchronizedMap();
+ goToLinks = synchronizedMap();
+ itemStates = synchronizedMap();
+ lr0Edges = synchronizedSet();
+
+ threadPool =
+ new ThreadPoolExecutor(
+ numThreads,
+ numThreads,
+ Long.MAX_VALUE,
+ TimeUnit.NANOSECONDS,
+ new LinkedBlockingQueue());
+ taskCountLock = new ReentrantLock();
+
+ shutDownThread =
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ synchronized (threadPool) {
+ threadPool.wait();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ threadPool.shutdown();
+ }
+ };
+ // we need to ensure that the shutDownThread is started before the taskCount can be decremented
+ // to 0
+ shutDownThread.start();
+ // we need to ensure that the shutDownThread is already waiting to be notified
+ while (!Objects.equals(shutDownThread.getState(), Thread.State.WAITING)) {}
+
+ // add one task for state0 to the thread pool and start the thread pool
+ LinkedList tasks = new LinkedList();
+ kernel2closure.put(startStateKernel, startStateKernel.closure(grammarInfo));
+
+ taskCountLock.lock();
+ try {
+ taskCount = 0;
+ } finally {
+ taskCountLock.unlock();
+ }
+ tasks.add(new WorkerTaskLALR1(startStateKernel, threadPool, taskCountLock));
+ try {
+ threadPool.invokeAll(tasks);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // wait until the ThreadPool has been shut down
+ try {
+ shutDownThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ lookaheads = synchronizedMap();
+
+ // now, since we have built the LALR(1)-CP automaton, we compute
+ // all lookaheads by just following the CP links. Therefore, we just save the lookaheads
+ // for each LALR1CPItem in a hashmap
+
+ final ThreadPoolExecutor threadPoolCP =
+ new ThreadPoolExecutor(
+ numThreads,
+ numThreads,
+ Long.MAX_VALUE,
+ TimeUnit.NANOSECONDS,
+ new LinkedBlockingQueue());
+ ReentrantLock taskCountLockCP = new ReentrantLock();
+
+ // create a new thread that waits until all tasks are done
+ Thread shutDownThreadCP =
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ synchronized (threadPoolCP) {
+ threadPoolCP.wait();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ threadPoolCP.shutdown();
+ }
+ };
+ shutDownThreadCP.start();
+
+ // we need to ensure that the shutDownThread is already waiting to be notified
+ while (!Objects.equals(shutDownThreadCP.getState(), Thread.State.WAITING)) {}
+
+ taskCountLockCP.lock();
+ try {
+ taskCount = 0;
+ } finally {
+ taskCountLockCP.unlock();
+ }
+
+ // initialize queue (consisting of kernels) with the start item kernel
+ LinkedList tasksCP = new LinkedList