Skip to content

Commit

Permalink
Merge pull request #14 from polystat/develop
Browse files Browse the repository at this point in the history
Latest changes
  • Loading branch information
IamMaxim authored Oct 5, 2021
2 parents 2e45f1f + 4632b38 commit 7346153
Show file tree
Hide file tree
Showing 512 changed files with 11,581 additions and 2,561 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/gradle-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ jobs:
with:
arguments: build

- uses: gradle/gradle-build-action@v1
with:
arguments: test

61 changes: 60 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,63 @@

[![Gradle Build](https://github.com/polystat/j2eo/actions/workflows/gradle-build.yml/badge.svg)](https://github.com/polystat/j2eo/actions/workflows/gradle-build.yml)

This is a translator of Java to [EOLANG](https://www.eolang.org).
This is a translator of Java to [EOLANG](https://www.eolang.org).

---

## Motivation

This project is a part of Polystat project, the goal of which is to statically analyze different languages using EOLANG,
the implementation of phi-calculus. In order to do that, the first step is to convert source language into EO. This
particular repository contains translator from Java to EO.

---

## Decisions

**Q**: Why do we implement yet another Java parser?

**A**: Publicly available parsers only support older versions of Java, while we aim to support the latest version (
currently 16). Thus, we had to create our own parser.

---

**Q**: Why do we implement EO AST?

**A**: Working with AST instead of raw strings allows utilization of Java compiler's type checking to minimize amount of
bugs in our code. It is also much easier to work with abstraction layer than with strings.

---

## Usage

> ⚠️ NOTE: for now, the entire pipeline is not available. Project is Work In Progress.
```shell
java -jar j2eo.jar <source package directory> -o <output directory>
```

---

## How does it work?

- First, the Java source code files are parsed recursively.
- Then, for each file, translator converts Java AST to EO AST.
- Then, EO AST is printed out as a source code to output directory in the same directory structure.

## NOT covered Java features list

- Type Erasure
- Subtyping
- Conversions
- Casting
- Modules
- Exceptions
- Asserts
- Throws
- ``synchronized`` blocks
- ``try``/``catch`` blocks
- ``yeild`` feature
- Threads and Locks

In general, we cover **91 feature of 112** described in the Java language specification.
17 changes: 8 additions & 9 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ repositories {
}

dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.0")
}

tasks.withType(JavaCompile::class).configureEach {
Expand Down Expand Up @@ -78,8 +78,9 @@ fun runBison() =
workingDir = File(".")
executable = "bin/win_bison.exe"
args = mutableListOf(
"-r",
"all",
"--report=states,lookaheads",
// "-r", "all",
// "--debug", "--help", "--stacktrace",
"--report-file=${reportFilePath}",
"--output=${javaParserFilePath}",
javaGrammarFilePath
Expand All @@ -90,8 +91,7 @@ fun runBison() =
workingDir = File(".")
executable = "bin/bison_mac"
args = mutableListOf(
"-r",
"all",
"-r", "all",
"--report-file=${reportFilePath}",
"--output=${javaParserFilePath}",
javaGrammarFilePath
Expand All @@ -102,8 +102,7 @@ fun runBison() =
workingDir = File(".")
executable = "bison"
args = mutableListOf(
"-r",
"all",
"-r", "all",
"--report-file=${reportFilePath}",
"--output=${javaParserFilePath}",
javaGrammarFilePath
Expand All @@ -125,7 +124,7 @@ fun generateMD5(filepath: String): String {
val buffer = ByteArray(8192)
var read = 0
do {
digest.update(buffer, 0, read);
digest.update(buffer, 0, read)
read = inputStream.read(buffer)
} while (read > 0)
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/eotree/EOAnonExpr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package eotree;

public class EOAnonExpr extends EOBnd {
public EOAnonExpr(EOExpr expr) {
super(expr);
}

@Override
public String generateEO(int indent) {
return expr.generateEO(indent);
}
}
26 changes: 26 additions & 0 deletions src/main/java/eotree/EOAttribute.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package eotree;

/**
* EBNF representation:
* <code>
* '@' | name [ '...' ]
* </code>
*/
public class EOAttribute extends EONode {
public static final EOAttribute DECORATEE = new EOAttribute("@", false);
public static final EOAttribute PARENT = new EOAttribute("^", false);
public static final EOAttribute CURRENT = new EOAttribute("$", false);

public String name;
public boolean isVarArg;

public EOAttribute(String name, boolean isVarArg) {
this.name = name;
this.isVarArg = isVarArg;
}

@Override
public String generateEO(int indent) {
return name + (isVarArg ? " ..." : "");
}
}
21 changes: 21 additions & 0 deletions src/main/java/eotree/EOAttributes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package eotree;

import java.util.List;
import java.util.stream.Collectors;

public class EOAttributes extends EONode {
public List<EOAttribute> attributes;

public EOAttributes(List<EOAttribute> attributes) {
this.attributes = attributes;
}

@Override
public String generateEO(int indent) {
return "[" +
attributes.stream()
.map(attribute -> attribute.generateEO(indent))
.collect(Collectors.joining(" "))
+ "]";
}
}
9 changes: 9 additions & 0 deletions src/main/java/eotree/EOBnd.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package eotree;

public abstract class EOBnd extends EONode {
public EOExpr expr;

public EOBnd(EOExpr expr) {
this.expr = expr;
}
}
15 changes: 15 additions & 0 deletions src/main/java/eotree/EOBndExpr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package eotree;

public class EOBndExpr extends EOBnd {
public EOBndName bndName;

public EOBndExpr(EOExpr expr, EOBndName bndName) {
super(expr);
this.bndName = bndName;
}

@Override
public String generateEO(int indent) {
return expr.generateEO(indent) + " > " + bndName.generateEO(0);
}
}
14 changes: 14 additions & 0 deletions src/main/java/eotree/EOBndName.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package eotree;

public class EOBndName extends EONode {
public String name;

public EOBndName(String name) {
this.name = name;
}

@Override
public String generateEO(int indent) {
return name;
}
}
20 changes: 20 additions & 0 deletions src/main/java/eotree/EOComment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package eotree;

/**
* EBNF representation:
* <code>
* '#' ANY EOL
* </code>
*/
public class EOComment extends EONode {
public String comment;

public EOComment(String comment) {
this.comment = comment;
}

@Override
public String generateEO(int indent) {
return "# " + comment;
}
}
21 changes: 21 additions & 0 deletions src/main/java/eotree/EOCopy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package eotree;

import java.util.List;
import java.util.stream.Collectors;

public class EOCopy extends EOExpr {
public EOExpr trg;
public List<EOBnd> args;

public EOCopy(EOExpr trg, List<EOBnd> args) {
this.trg = trg;
this.args = args;
}

@Override
public String generateEO(int indent) {
return trg.generateEO(indent) + args.stream()
.map(arg -> " " + arg.generateEO(indent + 1))
.collect(Collectors.joining());
}
}
22 changes: 22 additions & 0 deletions src/main/java/eotree/EODot.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package eotree;

import java.util.Optional;

public class EODot extends EOExpr {
public Optional<EOExpr> src;
public String name;

public EODot(Optional<EOExpr> src, String name) {
this.src = src;
this.name = name;
}

@Override
public String generateEO(int indent) {
return
src
.map(eoExpr -> eoExpr.generateEO(indent) + ".")
.orElse(indent(indent))
+ name;
}
}
4 changes: 4 additions & 0 deletions src/main/java/eotree/EOExpr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package eotree;

public abstract class EOExpr extends EONode {
}
30 changes: 30 additions & 0 deletions src/main/java/eotree/EOLicense.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package eotree;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
* EBNF representation:
* <code>
* { comment EOL } EOL
* </code>
*/
public class EOLicense extends EONode {
public List<EOComment> comments;

public EOLicense(List<EOComment> comments) {
this.comments = comments;
}

public EOLicense(EOComment... comments) {
this(Arrays.stream(comments).collect(Collectors.toList()));
}

@Override
public String generateEO(int indent) {
return comments.stream()
.map(comment -> comment.generateEO(indent))
.collect(Collectors.joining("\n"));
}
}
22 changes: 22 additions & 0 deletions src/main/java/eotree/EOMeta.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package eotree;

/**
* EBNF representation:
* <code>
* '+' name '␣' ANY EOL
* </code>
*/
public class EOMeta extends EONode {
public String name;
public String value;

public EOMeta(String name, String value) {
this.name = name;
this.value = value;
}

@Override
public String generateEO(int indent) {
return "+" + name + " " + value;
}
}
31 changes: 31 additions & 0 deletions src/main/java/eotree/EOMetas.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package eotree;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* EBNF representation:
* <code>
* { meta EOL } EOL
* </code>
*/
public class EOMetas extends EONode {
public Optional<String> packageName;
public List<EOMeta> metas;

public EOMetas(Optional<String> packageName, List<EOMeta> metas) {
this.packageName = packageName;
this.metas = metas;
}

@Override
public String generateEO(int indent) {
return packageName
.map(p -> "+package " + p + "\n")
.orElse("") +
metas.stream()
.map(m -> m.generateEO(indent))
.collect(Collectors.joining("\n"));
}
}
11 changes: 11 additions & 0 deletions src/main/java/eotree/EONode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package eotree;

public abstract class EONode {
public static final int INDENT_SIZE = 2;

public static String indent(int indent) {
return " ".repeat(indent * INDENT_SIZE);
}

public abstract String generateEO(int indent);
}
Loading

1 comment on commit 7346153

@0pdd
Copy link
Member

@0pdd 0pdd commented on 7346153 Oct 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to retrieve PDD puzzles from the code base and submit them to GitHub. If you think that it's a bug on our side, please submit it to yegor256/0pdd:

set -x && set -e && set -o pipefail && cd /tmp/0pdd20210801-12-f1ew7f/polystat/j2eo && pdd -v -f /tmp/20211005-15168-187yrhf [1]: + set -e + set -o pipefail + cd /tmp/0pdd20210801-12-f1ew7f/polystat/j2eo + pdd -v -f /tmp/20211005-15168-187yrhf My version is 0.20.6 Ruby version is 2.6.0 at...

Please, copy and paste this stack trace to GitHub:

UserError
set -x && set -e && set -o pipefail && cd /tmp/0pdd20210801-12-f1ew7f/polystat/j2eo && pdd -v -f /tmp/20211005-15168-187yrhf [1]:
+ set -e
+ set -o pipefail
+ cd /tmp/0pdd20210801-12-f1ew7f/polystat/j2eo
+ pdd -v -f /tmp/20211005-15168-187yrhf

My version is 0.20.6
Ruby version is 2.6.0 at x86_64-linux
Reading /tmp/0pdd20210801-12-f1ew7f/polystat/j2eo
651 file(s) found, 551 excluded
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/Verbosity.png is a binary file (29722 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/FlexProperties.png is a binary file (26767 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/3.png is a binary file (7316 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/6.png is a binary file (15611 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/BisonProperties.png is a binary file (27186 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/2.png is a binary file (11445 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/Flex_debuging.png is a binary file (27219 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/Properties.png is a binary file (31446 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/4.png is a binary file (12213 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/1.png is a binary file (31654 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/custom_build_rules/docs/5.png is a binary file (11534 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/win_bison.exe is a binary file (665600 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/win_flex.exe is a binary file (569344 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/bin/bison_mac is a binary file (487680 bytes)
/tmp/0pdd20210801-12-f1ew7f/polystat/j2eo/gradle/wrapper/gradle-wrapper.jar is a binary file (59203 bytes)
Reading bin/changelog.md...
Reading bin/custom_build_rules/README.md...
Reading bin/custom_build_rules/win_flex_only/win_flex_custom_build.targets...
Reading bin/custom_build_rules/win_flex_only/win_flex_custom_build.props...
Reading bin/custom_build_rules/win_flex_only/win_flex_custom_build.xml...
Reading bin/custom_build_rules/win_bison_only/win_bison_custom_build.xml...
Reading bin/custom_build_rules/win_bison_only/win_bison_custom_build.props...
Reading bin/custom_build_rules/win_bison_only/win_bison_custom_build.targets...
Reading bin/custom_build_rules/win_flex_bison/win_flex_bison_custom_build.props...
Reading bin/custom_build_rules/win_flex_bison/win_flex_bison_custom_build.targets...
Reading bin/custom_build_rules/win_flex_bison/win_flex_bison_custom_build.xml...
Reading bin/data/local.mk...
Reading bin/data/README.md...
Reading bin/data/bison-default.css...
Reading bin/data/m4sugar/m4sugar.m4...
Reading bin/data/m4sugar/foreach.m4...
Reading bin/data/skeletons/java-skel.m4...
Reading bin/data/skeletons/location.cc...
Reading bin/data/skeletons/lalr1.java...
Reading bin/data/skeletons/c++.m4...
Reading bin/data/skeletons/traceon.m4...
Reading bin/data/skeletons/glr.cc...
Reading bin/data/skeletons/glr.c...
Reading bin/data/skeletons/c++-skel.m4...
Reading bin/data/skeletons/d.m4...
ERROR: bin/data/skeletons/d.m4; puzzle at line #298; TODO found, but puzzle can't be parsed, most probably because TODO is not followed by a puzzle marker, as this page explains: https://github.com/yegor256/pdd#how-to-format
If you can't understand the cause of this issue or you don't know how to fix it, please submit a GitHub issue, we will try to help you: https://github.com/yegor256/pdd/issues. This tool is still in its beta version and we will appreciate your feedback. Here is where you can find more documentation: https://github.com/yegor256/pdd/blob/master/README.md.
Exit code is 1

/app/objects/git_repo.rb:66:in `rescue in block in xml'
/app/objects/git_repo.rb:63:in `block in xml'
/app/vendor/ruby-2.6.0/lib/ruby/2.6.0/tempfile.rb:295:in `open'
/app/objects/git_repo.rb:62:in `xml'
/app/objects/puzzles.rb:36:in `deploy'
/app/objects/job.rb:38:in `proceed'
/app/objects/job_starred.rb:33:in `proceed'
/app/objects/job_recorded.rb:32:in `proceed'
/app/objects/job_emailed.rb:35:in `proceed'
/app/objects/job_commiterrors.rb:36:in `proceed'
/app/objects/job_detached.rb:48:in `exclusive'
/app/objects/job_detached.rb:36:in `block in proceed'
/app/objects/job_detached.rb:36:in `fork'
/app/objects/job_detached.rb:36:in `proceed'
/app/0pdd.rb:357:in `block in <top (required)>'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1675:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1675:in `block in compile!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1013:in `block (3 levels) in route!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1032:in `route_eval'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1013:in `block (2 levels) in route!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1061:in `block in process_route'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1059:in `catch'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1059:in `process_route'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1011:in `block in route!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1008:in `each'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1008:in `route!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1129:in `block in dispatch!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `block in invoke'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `catch'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `invoke'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1124:in `dispatch!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:939:in `block in call!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `block in invoke'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `catch'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1101:in `invoke'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:939:in `call!'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:929:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.1.0/lib/rack/protection/xss_header.rb:18:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.1.0/lib/rack/protection/path_traversal.rb:16:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.1.0/lib/rack/protection/json_csrf.rb:26:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.1.0/lib/rack/protection/base.rb:50:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.1.0/lib/rack/protection/base.rb:50:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.1.0/lib/rack/protection/frame_options.rb:31:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-2.2.3/lib/rack/logger.rb:17:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-2.2.3/lib/rack/common_logger.rb:38:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:253:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:246:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-2.2.3/lib/rack/method_override.rb:24:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:216:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1991:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1542:in `block in call'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1769:in `synchronize'
/app/vendor/bundle/ruby/2.6.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1542:in `call'
/app/vendor/bundle/ruby/2.6.0/gems/rack-2.2.3/lib/rack/handler/webrick.rb:95:in `service'
/app/vendor/ruby-2.6.0/lib/ruby/2.6.0/webrick/httpserver.rb:140:in `service'
/app/vendor/ruby-2.6.0/lib/ruby/2.6.0/webrick/httpserver.rb:96:in `run'
/app/vendor/ruby-2.6.0/lib/ruby/2.6.0/webrick/server.rb:307:in `block in start_thread'

Please sign in to comment.