diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b63da45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..d13da9c --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# デフォルトの無視対象ファイル +/shelf/ +/workspace.xml +# エディターベースの HTTP クライアントリクエスト +/httpRequests/ +# 環境に依存する Maven ホームディレクトリのパス +/mavenHomeManager.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/RDLApplicationRuntime/build.gradle b/RDLApplicationRuntime/build.gradle new file mode 100644 index 0000000..15c9952 --- /dev/null +++ b/RDLApplicationRuntime/build.gradle @@ -0,0 +1,16 @@ +plugins { + id 'java-library' +} + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ApplicationRuntime.java b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ApplicationRuntime.java new file mode 100644 index 0000000..d879dc9 --- /dev/null +++ b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ApplicationRuntime.java @@ -0,0 +1,17 @@ +package org.nittalab.rdl.applicationruntime; + +public class ApplicationRuntime { + private ApplicationState applicationState = new ApplicationState(); + + public UIState getUIState() { + return applicationState.getUIState(); + } + + public TableState getTableState() { + return applicationState.getTableState(); + } + + public String getCurTableKey(String tableId) { + return null; + } +} diff --git a/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ApplicationState.java b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ApplicationState.java new file mode 100644 index 0000000..ea5279a --- /dev/null +++ b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ApplicationState.java @@ -0,0 +1,14 @@ +package org.nittalab.rdl.applicationruntime; + +public class ApplicationState { + private UIState uiState = new UIState(); + private TableState tableState = new TableState(); + + public UIState getUIState() { + return uiState; + } + + public TableState getTableState() { + return tableState; + } +} diff --git a/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ConstraintHandler.java b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ConstraintHandler.java new file mode 100644 index 0000000..33927b8 --- /dev/null +++ b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/ConstraintHandler.java @@ -0,0 +1,6 @@ +package org.nittalab.rdl.applicationruntime; + +public interface ConstraintHandler { + public void beforeEvent(); + public void afterEvent(); +} diff --git a/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/TableState.java b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/TableState.java new file mode 100644 index 0000000..d05b048 --- /dev/null +++ b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/TableState.java @@ -0,0 +1,11 @@ +package org.nittalab.rdl.applicationruntime; + +public class TableState { + public String getValue(String tableId, String key, int columnNo) { + return null; + } + + public void updateValue(String tableId, String key, int columnNo, String value) { + + } +} diff --git a/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/UIState.java b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/UIState.java new file mode 100644 index 0000000..857e135 --- /dev/null +++ b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/UIState.java @@ -0,0 +1,23 @@ +package org.nittalab.rdl.applicationruntime; + +public class UIState { + public void changeScreen(String nextScreenId) { + + } + + public String getWidgetText(String screenId, String widgetId) { + return null; + } + + public void setWidgetText(String screenId, String widgetId, String text) { + + } + + public String getCurWidgetText(String widgetId) { + return null; + } + + public String getCurWidgetState(String widgetId) { + return null; + } +} diff --git a/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/WidgetEventReceiver.java b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/WidgetEventReceiver.java new file mode 100644 index 0000000..bd14adc --- /dev/null +++ b/RDLApplicationRuntime/src/main/java/org/nittalab/rdl/applicationruntime/WidgetEventReceiver.java @@ -0,0 +1,5 @@ +package org.nittalab.rdl.applicationruntime; + +public interface WidgetEventReceiver { + public void onWidgetStateChanged(); +} diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..d82bd4e --- /dev/null +++ b/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'java' + id 'application' +} + +application { + mainClass = 'org.nittalab.rdlworkbench.Main' +} + +group = 'org.nittalab' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + implementation project(':RDLApplicationRuntime') + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..249e583 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar Binary files differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..9bc3ee7 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Sep 04 18:24:05 JST 2026 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..1b6c787 --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..d652066 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,3 @@ +rootProject.name = 'RDLWorkbench' + +include 'RDLApplicationRuntime' \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/Main.java b/src/main/java/org/nittalab/rdlworkbench/Main.java new file mode 100644 index 0000000..ec045d0 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/Main.java @@ -0,0 +1,7 @@ +package org.nittalab.rdlworkbench; + +public class Main { + public static void main(String[] args) { + + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ASTNode.java b/src/main/java/org/nittalab/rdlworkbench/ast/ASTNode.java new file mode 100644 index 0000000..e871fc4 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ASTNode.java @@ -0,0 +1,13 @@ +package org.nittalab.rdlworkbench.ast; + +public abstract class ASTNode { + private ASTNode parent; + + public ASTNode getParent() { + return parent; + } + + public void setParent(ASTNode parent) { + this.parent = parent; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/AbstractTypeDeclaration.java b/src/main/java/org/nittalab/rdlworkbench/ast/AbstractTypeDeclaration.java new file mode 100644 index 0000000..6f1e6e7 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/AbstractTypeDeclaration.java @@ -0,0 +1,13 @@ +package org.nittalab.rdlworkbench.ast; + +public class AbstractTypeDeclaration extends BodyDeclaration { + protected String typeName = null; + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/AnnotatableType.java b/src/main/java/org/nittalab/rdlworkbench/ast/AnnotatableType.java new file mode 100644 index 0000000..bc16a58 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/AnnotatableType.java @@ -0,0 +1,26 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents an abstract base class for AST types that can have annotations. + * This class extends the functionality of {@link Type} by introducing support + * for attaching annotations to the type. + *

+ * Subclasses of this class represent specific kinds of types in the AST that + * allow annotations, such as primitive types or other specialized types. + * + * @author s-yamagiwa + */ +public abstract class AnnotatableType extends Type { + private final List annotations = new ArrayList<>(); + + public void addAnnotation(Annotation annotation) { + annotations.add(annotation); + } + + public List getAnnotations() { + return annotations; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Annotation.java b/src/main/java/org/nittalab/rdlworkbench/ast/Annotation.java new file mode 100644 index 0000000..ab4fb9c --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Annotation.java @@ -0,0 +1,57 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class Annotation extends ASTNode { + private String name = null; + private Map keyValueMap = null; + + public Annotation(String name) { + this.name = name; + keyValueMap = new HashMap<>(); + } + + public Annotation(String name, String value) { + this.name = name; + keyValueMap = new HashMap<>(); + keyValueMap.put("value", value); + } + + public String getElementName() { + return name; + } + + public Map getParams() { + return keyValueMap; + } + + public Object getValue(String key) { + return keyValueMap.get(key); + } + + public void addParam(String key, Object value) { + keyValueMap.put(key, value); + } + + public String toString() { + String code = "@" + name; + Set keySet = keyValueMap.keySet(); + if (keySet.size() == 0) { + return code; + } else if (keySet.size() == 1 && keySet.iterator().next().equals("value")) { + code += "(" + keyValueMap.get("value").toString() + ")"; + } else { + code += "("; + String delimitar = ""; + for (String key: keySet) { + Object value = keyValueMap.get(key); + code += delimitar + key + " = \"" + value.toString() + "\""; + delimitar = ", "; + } + code += ")"; + } + return code; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Assignment.java b/src/main/java/org/nittalab/rdlworkbench/ast/Assignment.java new file mode 100644 index 0000000..9285fad --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Assignment.java @@ -0,0 +1,42 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents an assignment expression node in AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + */ +public class Assignment extends Expression { + private Expression left; + private Expression right; + + public Assignment(Expression left, Expression right) { + this.left = left; + this.right = right; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + return new Assignment(left.replace(variable, expression), right.replace(variable, expression)); + } + + public Expression getLeft() { + return left; + } + + public void setLeft(Expression left) { + this.left = left; + } + + public Expression getRight() { + return right; + } + + public void setRight(Expression right) { + this.right = right; + } + + @Override + public String toString() { + return left.toString() + " " + "=" + " " + right.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Block.java b/src/main/java/org/nittalab/rdlworkbench/ast/Block.java new file mode 100644 index 0000000..45fa80c --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Block.java @@ -0,0 +1,107 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.ArrayList; +import java.util.List; + +public class Block extends Statement { + private List statements = new ArrayList<>(); + + public List getStatements2() { + return statements; + } + + public void setStatements(List statements) { + this.statements = statements; + } + + public void addFirstStatement(Statement statement) { + statements.add(0, statement); + } + + public void addStatement(Statement statement) { + statements.add(statement); + } + + public void addFirstStatements(List statements) { + this.statements.addAll(0, statements); + } + + public void addStatements(List statements) { + this.statements.addAll(statements); + } + + public boolean contains(List statements) { + if (statements.size() == 0) return true; + for (int i = 0; i < this.statements.size(); i++) { + Statement st = this.statements.get(i); + if (st.equals(statements.get(0))) { + if (statements.size() == 1) return true; + int j = 1; + for (int k = i + 1; k < this.statements.size(); k++) { + Statement st2 = this.statements.get(k); + if (st2.equals(statements.get(j))) { + j++; + if (j == statements.size()) return true; + } + } + } + } + return false; + } + + //==================================================== + //TODO: CodeGenerator修正後削除 + + public List getStatements() { + List strings = new ArrayList<>(); + for (Statement stmt : statements) { + if (stmt != null) { + strings.add(stmt.toString()); + } + } + return strings; + } + + public void addFirstStatement(String statement) { + if (statement != null) { + this.addFirstStatement(new Statement() { + @Override + public String toString() { + return statement; + } + }); + } + } + + public void addStatement(String statement) { + if (statement != null) { + this.addStatement(new PlainStatement(statement)); + } + } + + //==================================================== + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{\n"); + + for (Statement statement : statements) { + if (statement != null) { + String content = statement.toString(); + + // split statement + String[] lines = content.split("\n"); + + // Tab + for (String line : lines) { + sb.append("\t").append(line).append("\n"); + } + } + } + + sb.append("}"); + return sb.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/BodyDeclaration.java b/src/main/java/org/nittalab/rdlworkbench/ast/BodyDeclaration.java new file mode 100644 index 0000000..078a1e3 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/BodyDeclaration.java @@ -0,0 +1,13 @@ +package org.nittalab.rdlworkbench.ast; + +public abstract class BodyDeclaration extends ASTNode { + private int modifiers = 0; + + public int getModifiers() { + return modifiers; + } + + public void setModifiers(int modifiers) { + this.modifiers = modifiers; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ClassInstanceCreation.java b/src/main/java/org/nittalab/rdlworkbench/ast/ClassInstanceCreation.java new file mode 100644 index 0000000..6dc8ff0 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ClassInstanceCreation.java @@ -0,0 +1,71 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.ArrayList; +import java.util.List; + +public class ClassInstanceCreation extends Expression { + private Type type; + + private List arguments; + + public ClassInstanceCreation(Type type) { + this(type, List.of()); + } + + public ClassInstanceCreation(Type type, List arguments) { + this.type = type; + this.arguments = arguments; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + List replacedExpressions = new ArrayList<>(); + + for (Expression argument : arguments) { + replacedExpressions.add(argument.replace(variable, expression)); + } + + return new ClassInstanceCreation(type, replacedExpressions); + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public List getArguments() { + return arguments; + } + + public void setArguments(List arguments) { + this.arguments = arguments; + } + + public void addArgument(Expression expression) { + arguments.add(expression); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + + builder.append("new "); + builder.append(type.toString()); + builder.append("("); + for (int i = 0; i < arguments.size(); i++) { + Expression argument = arguments.get(i); + + builder.append(argument.toString()); + + if (i < arguments.size() - 1) { + builder.append(", "); + } + } + builder.append(")"); + + return builder.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/CodeUtil.java b/src/main/java/org/nittalab/rdlworkbench/ast/CodeUtil.java new file mode 100644 index 0000000..0960970 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/CodeUtil.java @@ -0,0 +1,13 @@ +package org.nittalab.rdlworkbench.ast; + +public class CodeUtil { + + public static String insertTab(String code) { + String newString = ""; + String[] lines = code.split("\n"); + for (String line: lines) { + newString = newString + "\t" + line + "\n"; + } + return newString; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/CompilationUnit.java b/src/main/java/org/nittalab/rdlworkbench/ast/CompilationUnit.java new file mode 100644 index 0000000..9cdfe74 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/CompilationUnit.java @@ -0,0 +1,67 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.ArrayList; +import java.util.List; + +public class CompilationUnit extends ASTNode { + private String fileName = null; + private List imports = new ArrayList<>(); + private List types = new ArrayList<>(); + private List interfaces = new ArrayList<>(); + + public CompilationUnit(TypeDeclaration type) { + types.add(type); + if(type.getTypeName().contains("<")) + fileName = type.getTypeName().split("<")[0] + ".java"; + else + fileName = type.getTypeName() + ".java"; + } + + public CompilationUnit(InterfaceDeclaration interfaceDeclaration) { + interfaces.add(interfaceDeclaration); + fileName = interfaceDeclaration.getTypeName() + ".java"; + } + + public List imports() { + return imports; + } + + public List types() { + return types; + } + + public void addImport(ImportDeclaration imp) { + imports.add(imp); + } + + public void addType(TypeDeclaration type) { + types.add(type); + } + + public List interfaces() { + return interfaces; + } + + public void addInterface(InterfaceDeclaration interfaceDeclaration) { + interfaces.add(interfaceDeclaration); + } + + public String getFileName() { + return fileName; + } + + public String toString() { + String result = ""; + for (ImportDeclaration imp: imports) { + result += imp.toString(); + } + result +="\n"; + for (TypeDeclaration type: types) { + result += type.toString(); + } + for (InterfaceDeclaration iDec: interfaces) { + result += iDec.toString(); + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Constant.java b/src/main/java/org/nittalab/rdlworkbench/ast/Constant.java new file mode 100644 index 0000000..d441be0 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Constant.java @@ -0,0 +1,32 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents a constant in the AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + */ +public class Constant extends Expression { + private String value; + + public Constant(String value) { + this.value = value; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + return this; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/EnhancedForStatement.java b/src/main/java/org/nittalab/rdlworkbench/ast/EnhancedForStatement.java new file mode 100644 index 0000000..e4da98f --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/EnhancedForStatement.java @@ -0,0 +1,23 @@ +package org.nittalab.rdlworkbench.ast; + +public class EnhancedForStatement extends Statement { + + private VariableDeclaration singleVariableDeclaration; + private Expression expression; + private Statement body; + + public VariableDeclaration getParameter() { return singleVariableDeclaration; } + public void setParameter(VariableDeclaration parameter) { this.singleVariableDeclaration = parameter; } + + public Expression getExpression() { return expression; } + public void setExpression(Expression expression) { this.expression = expression; } + + public Statement getBody() { return body; } + public void setBody(Statement body) { this.body = body; } + + @Override + public String toString() { + String typeName = singleVariableDeclaration.getType().getImplementationTypeName(); + return "for (" + typeName + " " + singleVariableDeclaration.getName() + " : " + expression + ") " + body; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Expression.java b/src/main/java/org/nittalab/rdlworkbench/ast/Expression.java new file mode 100644 index 0000000..5fbb9ec --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Expression.java @@ -0,0 +1,19 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Abstract base class for all expression nodes in the abstract syntax tree (AST). + * + * @author s-yamagiwa + */ +public abstract class Expression extends ASTNode { + /** + * Replace {@code variable} with {@code expression} in AST. + * + * @param variable The variable to be replaced + * @param expression The expression that {@code variable} is replaced to + * @return A duplicated expression that is replaced with a given {@code expression} + * @implNote The instance of any member must be immutable + * @apiNote All variables match to the given one will be replaced with the given {@code expression} + */ + public abstract Expression replace(Variable variable, Expression expression); +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ExpressionStatement.java b/src/main/java/org/nittalab/rdlworkbench/ast/ExpressionStatement.java new file mode 100644 index 0000000..a0e65fe --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ExpressionStatement.java @@ -0,0 +1,17 @@ +package org.nittalab.rdlworkbench.ast; + +public class ExpressionStatement extends Statement{ + private Expression expression; + + public ExpressionStatement(Expression expression) { + this.expression = expression; + } + + public Expression getExpression() { return expression; } + public void setExpression(Expression expression) { this.expression = expression; } + + @Override + public String toString() { + return expression + ";"; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/FieldAccess.java b/src/main/java/org/nittalab/rdlworkbench/ast/FieldAccess.java new file mode 100644 index 0000000..187af27 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/FieldAccess.java @@ -0,0 +1,50 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents field accesses in AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + */ +public class FieldAccess extends Expression { + private Expression expression; + + private String fieldName; + + public FieldAccess(String fieldName) { + this(null, fieldName); + } + + public FieldAccess(Expression expression, String fieldName) { + this.expression = expression; + this.fieldName = fieldName; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + return new FieldAccess(expression.replace(variable, expression), fieldName); + } + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + @Override + public String toString() { + if (expression == null) { + return fieldName; + } + return expression + "." + fieldName; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/FieldDeclaration.java b/src/main/java/org/nittalab/rdlworkbench/ast/FieldDeclaration.java new file mode 100644 index 0000000..b38af0d --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/FieldDeclaration.java @@ -0,0 +1,90 @@ +package org.nittalab.rdlworkbench.ast; + +import models.algebra.Type; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class FieldDeclaration extends BodyDeclaration implements IAnnotatable { + private Type type; + private String fieldName; + private String initializer = null; + private String initializationBlock = null; + private Map annotations = new HashMap<>(); + + public FieldDeclaration(Type type, String fieldName) { + this.type = type; + this.fieldName = fieldName; + } + + public FieldDeclaration(Type type, String fieldName, String initializer) { + this.type = type; + this.fieldName = fieldName; + this.initializer = initializer; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public String getName() { + return fieldName; + } + + public void setName(String fieldName) { + this.fieldName = fieldName; + } + + public String getInitializer() { + return initializer; + } + + public void setInitializer(String initializer) { + this.initializer = initializer; + } + + public String getInitializationBlock() { + return initializationBlock; + } + + public void setInitializationBlock(String initializationBlock) { + this.initializationBlock = initializationBlock; + } + + @Override + public Annotation getAnnotation(String name) { + return annotations.get(name); + } + + @Override + public Collection getAnnotations() { + return annotations.values(); + } + + @Override + public void addAnnotation(Annotation annotation) { + annotations.put(annotation.getElementName(), annotation); + } + + public String toString() { + String code = ""; + for (Annotation annotation: getAnnotations()) { + code += annotation.toString() + "\n"; + } + if (initializationBlock != null) { + code += "private " + type.getInterfaceTypeName() + " " + fieldName + ";\n" + initializationBlock + "\n"; + } else { + if (initializer == null) { + code += "private " + type.getInterfaceTypeName() + " " + fieldName + ";\n"; + } else { + code += "private " + type.getInterfaceTypeName() + " " + fieldName + " = " + initializer + ";\n"; + } + } + return code; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ForStatement.java b/src/main/java/org/nittalab/rdlworkbench/ast/ForStatement.java new file mode 100644 index 0000000..f7defd5 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ForStatement.java @@ -0,0 +1,70 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.ArrayList; +import java.util.List; + +public class ForStatement extends Statement { + + private List initializers = new ArrayList<>(); + private Expression optionalConditionExpression; + private List updaters = new ArrayList<>(); + private Statement body; + + public List getInitializers() { + return initializers; + } + + public void setInitializers(List initializers) { + this.initializers = initializers; + } + + public Expression getExpression() { + return optionalConditionExpression; + } + + public void setExpression(Expression expression) { + this.optionalConditionExpression = expression; + } + + public List getUpdaters() { + return updaters; + } + + public void setUpdaters(List updaters) { + this.updaters = updaters; + } + + public Statement getBody() { + return body; + } + + public void setBody(Statement body) { + this.body = body; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("for ("); + + for (int i = 0; i < initializers.size(); i++) { + String init = initializers.get(i).toString(); + sb.append(init.endsWith(";") ? init.substring(0, init.length() - 1) : init); + if (i < initializers.size() - 1) sb.append(", "); + } + sb.append("; "); + + if (optionalConditionExpression != null) sb.append(optionalConditionExpression); + sb.append("; "); + + for (int i = 0; i < updaters.size(); i++) { + String update = updaters.get(i).toString(); + sb.append(update.endsWith(";") ? update.substring(0, update.length() - 1) : update); + if (i < updaters.size() - 1) sb.append(", "); + } + sb.append(") "); + + if (body != null) sb.append(body); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/IAnnotatable.java b/src/main/java/org/nittalab/rdlworkbench/ast/IAnnotatable.java new file mode 100644 index 0000000..5a2c86a --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/IAnnotatable.java @@ -0,0 +1,9 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.Collection; + +public interface IAnnotatable { + Annotation getAnnotation(String name); + Collection getAnnotations(); + void addAnnotation(Annotation annotation); +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/IfStatement.java b/src/main/java/org/nittalab/rdlworkbench/ast/IfStatement.java new file mode 100644 index 0000000..1239698 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/IfStatement.java @@ -0,0 +1,43 @@ +package org.nittalab.rdlworkbench.ast; + +public class IfStatement extends Statement { + + private Expression expression; + private Statement thenStatement; + private Statement elseStatement; + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public Statement getThenStatement() { + return thenStatement; + } + + public void setThenStatement(Statement thenStatement) { + this.thenStatement = thenStatement; + } + + public Statement getElseStatement() { + return elseStatement; + } + + public void setElseStatement(Statement elseStatement) { + this.elseStatement = elseStatement; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("if ").append(expression); + sb.append(thenStatement); + if (elseStatement != null) { + sb.append(" else ").append(elseStatement); + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ImportDeclaration.java b/src/main/java/org/nittalab/rdlworkbench/ast/ImportDeclaration.java new file mode 100644 index 0000000..8d65586 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ImportDeclaration.java @@ -0,0 +1,21 @@ +package org.nittalab.rdlworkbench.ast; + +public class ImportDeclaration { + private String name; + + public ImportDeclaration(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String toString() { + return "import " + name + ";\n"; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/InfixExpression.java b/src/main/java/org/nittalab/rdlworkbench/ast/InfixExpression.java new file mode 100644 index 0000000..a05f753 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/InfixExpression.java @@ -0,0 +1,55 @@ +package org.nittalab.rdlworkbench.ast; + +import models.algebra.Symbol; + +/** + * Represents an infix expression in AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + */ +public class InfixExpression extends Expression { + private Symbol operator; + + private Expression leftOperand; + private Expression rightOperand; + + public InfixExpression(Symbol operator, Expression leftOperand, Expression rightOperand) { + this.operator = operator; + this.leftOperand = leftOperand; + this.rightOperand = rightOperand; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + return new InfixExpression(operator, leftOperand.replace(variable, expression), rightOperand.replace(variable, expression)); + } + + public Symbol getOperator() { + return this.operator; + } + + public void setOperator(Symbol operator) { + this.operator = operator; + } + + public Expression getLeftOperand() { + return leftOperand; + } + + public void setLeftOperand(Expression expression) { + this.leftOperand = expression; + } + + public Expression getRightOperand() { + return rightOperand; + } + + public void setRightOperand(Expression expression) { + this.rightOperand = expression; + } + + @Override + public String toString() { + return leftOperand.toString() + " " + operator.toString() + " " + rightOperand.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/InterfaceDeclaration.java b/src/main/java/org/nittalab/rdlworkbench/ast/InterfaceDeclaration.java new file mode 100644 index 0000000..377699d --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/InterfaceDeclaration.java @@ -0,0 +1,67 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.*; + + +public class InterfaceDeclaration extends AbstractTypeDeclaration implements IAnnotatable { + private List methods = new ArrayList<>(); + private Map annotations = new HashMap<>(); + + public InterfaceDeclaration(String typeName) { + this.typeName = typeName; + } + + public void addMethod(MethodDeclaration method) { + methods.add(method); + } + + public void removeMethod(MethodDeclaration method) { + methods.remove(method); + } + + public List getMethods() { + return methods; + } + + @Override + public Annotation getAnnotation(String name) { + return annotations.get(name); + } + + @Override + public Collection getAnnotations() { + return annotations.values(); + } + + @Override + public void addAnnotation(Annotation annotation) { + annotations.put(annotation.getElementName(), annotation); + } + + public String toString() { + String code = ""; + for (Annotation annotation : getAnnotations()) { + code += annotation.toString() + "\n"; + } + code += "public interface " + typeName + " {\n"; + for (MethodDeclaration m : methods) { + String signature = "\t"; + if (m.getReturnType() == null) { + signature += "void "; + } else { + signature += m.getReturnType().getInterfaceTypeName() + " "; + } + signature += m.getName() + "("; + if (m.getParameters() != null) { + for (int i = 0; i < m.getParameters().size(); i++) { + signature += m.getParameters().get(i).toString(); + if (i < m.getParameters().size() - 1) signature += ", "; + } + } + signature += ");\n"; + code += signature; + } + code += "}"; + return code; + } +} \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Lexer.java b/src/main/java/org/nittalab/rdlworkbench/ast/Lexer.java new file mode 100644 index 0000000..ed3510e --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Lexer.java @@ -0,0 +1,55 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * The Lexer class provides functionalities for parsing and iterating through + * a source string of text character by character. + * + * @author s-yamagiwa; + */ +public class Lexer { + private final String source; + private int position; + + public Lexer(String source) { + this.source = source; + this.position = 0; + } + + /** + * Retrieves the next character without advancing the position. + * + * @return The next character. + */ + public char peek() { + if (position >= source.length()) { + return '\0'; // End of line + } + + return source.charAt(position); + } + + /** + * Retrieves the next character after advancing the position. + * + * @return The next character. + */ + public char peekNext() { + if (position + 1 >= source.length()) { + return '\0'; // End of line + } + + return source.charAt(position + 1); + } + + /** + * Advances the position by one character. + * + * @return The character that was previously at the current position. + */ + public char advance() { + char current = peek(); + position++; + + return current; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/MethodDeclaration.java b/src/main/java/org/nittalab/rdlworkbench/ast/MethodDeclaration.java new file mode 100644 index 0000000..47e7ec8 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/MethodDeclaration.java @@ -0,0 +1,190 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.*; + +public class MethodDeclaration extends BodyDeclaration implements IAnnotatable { + private String name = null; + private boolean isConstructor = false; + private Type returnType = null; + private List parameters = null; + private Block body = null; + private Map annotations = new HashMap<>(); + private Throws thrws = null; + + public MethodDeclaration(String methodName) { + this(methodName, false); + } + + public MethodDeclaration(String methodName, Type returnType) { + this(methodName, false); + this.returnType = returnType; + } + + public MethodDeclaration(String methodName, boolean isConstructor) { + this.name = methodName; + this.isConstructor = isConstructor; + } + + public MethodDeclaration(String methodName, boolean isConstructor, Type returnType, List parameters) { + this(methodName, isConstructor, returnType, parameters, null); + } + + public MethodDeclaration(String methodName, boolean isConstructor, Type returnType, List parameters, Block body) { + this(methodName, isConstructor); + this.returnType = returnType; + this.parameters = parameters; + this.body = body; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isConstructor() { + return isConstructor; + } + + public void setConstructor(boolean isConstructor) { + this.isConstructor = isConstructor; + } + + public Type getReturnType() { + return returnType; + } + + public void setReturnType(Type returnType) { + this.returnType = returnType; + } + + public List getParameters() { + return parameters; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + public void addParameter(VariableDeclaration parameter) { + if (parameters == null) { + parameters = new ArrayList<>(); + } + parameters.add(parameter); + } + + public Block getBody() { + if (body == null) { + body = new Block(); + } + return body; + } + + public void setBody(Block body) { + this.body = body; + } + + public void addUniqueStatement(Statement statement) { + if (body == null) { + body = new Block(); + body.addStatement(statement); + return; + } + if (body.contains(List.of(statement))) return; + body.addStatement(statement); + } + + public void addStatement(Statement statement) { + if (body == null) { + body = new Block(); + } + body.addStatement(statement); + } + + public void addUniqueStatement(String statement) { + if (body == null) { + body = new Block(); + body.addStatement(statement); + return; + } + if (body.contains(List.of(new PlainStatement(statement)))) return; + body.addStatement(statement); + } + + public void addStatement(String statement) { + if (body == null) { + body = new Block(); + } + body.addStatement(statement); + } + + public void addFirstStatement(Statement statement) { + if (body == null) { + body = new Block(); + } + body.addFirstStatement(statement); + } + + public void addFirstStatement(String statement) { + if (body == null) { + body = new Block(); + } + body.addFirstStatement(statement); + } + + public void addThrow(String exception) { + if (thrws == null) { + thrws = new Throws(); + } + thrws.addException(exception); + } + + public Throws getThrows() { + return thrws; + } + + @Override + public Annotation getAnnotation(String name) { + return annotations.get(name); + } + + @Override + public Collection getAnnotations() { + return annotations.values(); + } + + @Override + public void addAnnotation(Annotation annotation) { + annotations.put(annotation.getElementName(), annotation); + } + + public String toString() { + String code = ""; + for (Annotation annotation: getAnnotations()) { + code += annotation.toString() + "\n"; + } + code += "public "; + if (returnType == null) { + if(!isConstructor) code += "void "; + }else { + code += returnType.toString() + " "; + } + code += (name + "("); + if (parameters != null) { + for (int i = 0; i < parameters.size(); i++) { + code += parameters.get(i).toString(); + if (i < parameters.size() - 1) code += ", "; + } + } + code += ") "; + + if (body != null) { + code += body.toString(); + } else { + code += ";"; + } + return code; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/MethodInvocation.java b/src/main/java/org/nittalab/rdlworkbench/ast/MethodInvocation.java new file mode 100644 index 0000000..6058303 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/MethodInvocation.java @@ -0,0 +1,107 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a method invocation in AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + * @apiNote Type arguments aren't supported because it isn't necessary in DTRAM code generator. + */ +public class MethodInvocation extends Expression { + /** + * The receiver expression of the invocation + * defaults to {@code null} + */ + private Expression receiver; + + /** + * The method name to be called by this invocation + */ + private String methodName; + + /** + * All arguments used in the called method + */ + private List arguments; + + public MethodInvocation(String methodName) { + this(null, methodName); + } + + public MethodInvocation(Expression receiver, String methodName) { + this(receiver, methodName, List.of()); + } + + public MethodInvocation(Expression receiver, String methodName, List arguments) { + this.receiver = receiver; + this.methodName = methodName; + this.arguments = arguments; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + List replacedExpressions = new ArrayList<>(); + + for (Expression argument : arguments) { + replacedExpressions.add(argument.replace(variable, expression)); + } + + if (receiver == null) { + return new MethodInvocation(null, methodName, replacedExpressions); + } + + return new MethodInvocation(receiver.replace(variable, expression), methodName, replacedExpressions); + } + + public Expression getReceiver() { + return receiver; + } + + public void setReceiver(Expression receiver) { + this.receiver = receiver; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public List getArguments() { + return arguments; + } + + public void setArguments(List arguments) { + this.arguments = arguments; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + if (receiver != null) { + builder.append(receiver.toString()).append("."); + } + + builder.append(methodName).append("("); + + if (arguments != null && !arguments.isEmpty()) { + for (int i = 0; i < arguments.size(); i++) { + Expression argument = arguments.get(i); + + builder.append(argument.toString()); + + if (i < arguments.size() - 1) { + builder.append(", "); + } + } + } + + builder.append(")"); + + return builder.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Modifier.java b/src/main/java/org/nittalab/rdlworkbench/ast/Modifier.java new file mode 100644 index 0000000..6d47367 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Modifier.java @@ -0,0 +1,29 @@ +package org.nittalab.rdlworkbench.ast; + +public class Modifier extends ASTNode { + public static final int ABSTRACT = 0x0400; + public static final int PRIVATE = 0x0002; + public static final int PROTECTED = 0x0004; + public static final int PUBLIC = 0x0001; + public static final int STATIC = 0x0008; + + public static boolean isAbstract(int flags) { + return (flags & ABSTRACT) != 0; + } + + public static boolean isPrivate(int flags) { + return (flags & PRIVATE) != 0; + } + + public static boolean isProtected(int flags) { + return (flags & PROTECTED) != 0; + } + + public static boolean isPublic(int flags) { + return (flags & PUBLIC) != 0; + } + + public static boolean isStatic(int flags) { + return (flags & STATIC) != 0; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ParameterizedType.java b/src/main/java/org/nittalab/rdlworkbench/ast/ParameterizedType.java new file mode 100644 index 0000000..93a1c28 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ParameterizedType.java @@ -0,0 +1,109 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.List; + +/** + * Represents a parameterized type in an abstract syntax tree (AST). + * A parameterized type consists of a base type and a set of type arguments. + *

+ * For example, List<String> is a parameterized type where + * List is the base type and String is the type argument. + * + * @author s-yamagiwa + */ +public class ParameterizedType extends Type { + /** + * The base type of the parameterized type. + *

+ * For example, List in List<String> is a base type. + */ + private Type type; + + /** + * The type arguments of the parameterized type. + * Defaults to an empty list. + *

+ * For example, String in List<String> is a type argument. + */ + private List typeArguments; + + public ParameterizedType(Type type, List typeArguments) { + this.type = type; + this.typeArguments = typeArguments; + } + + public ParameterizedType(Type type) { + this(type, List.of()); + } + + /** + * Adds a type argument to the parameterized type. + * + * @param type The type argument to add. Only {@link SimpleType}s are allowed for now. + */ + public void addTypeArgument(Type type) { + typeArguments.add(type); + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + /** + * Returns the type arguments of the parameterized type. + * Only {@link SimpleType}s are allowed for now. + *

+ * It can be empty if it is the type of created instances like in the following example. + * new List<>() or new HashMap<>() + * + * @return The type arguments of the parameterized type. + */ + public List getTypeArguments() { + return typeArguments; + } + + public void setTypeArguments(List typeArguments) { + this.typeArguments = typeArguments; + } + + + /** + * Replace all type arguments and their descendant types that match the replacedType with the replacingType. + * @param replacedType the type to be replaced + * @param replacingType the type to replace with + */ + public void replaceSubTypes(Type replacedType, Type replacingType) { + for (int i = 0; i < typeArguments.size(); i++) { + Type typeArgment = typeArguments.get(i); + if (typeArgment.equals(replacedType)) { + typeArguments.set(i, replacingType); + } else if (typeArgment instanceof ParameterizedType) { + ((ParameterizedType) typeArgment).replaceSubTypes(replacedType, replacingType); + } + } + } + + @Override + public String toString() { + if (typeArguments.isEmpty()) { + return type.toString(); + } + + StringBuilder builder = new StringBuilder(); + builder.append(type.toString()); + builder.append("<"); + for (int i = 0; i < typeArguments.size(); i++) { + builder.append(typeArguments.get(i).toString()); + if (i < typeArguments.size() - 1) { + builder.append(", "); + } + } + builder.append(">"); + + return builder.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ParenthesizedExpression.java b/src/main/java/org/nittalab/rdlworkbench/ast/ParenthesizedExpression.java new file mode 100644 index 0000000..3a18824 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ParenthesizedExpression.java @@ -0,0 +1,33 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents a parenthesized expression in AST (Abstract Syntax Tree) + * This class is used to save the priority of each expression + * + * @author s-yamagiwa + */ +public class ParenthesizedExpression extends Expression { + private Expression expression; + + public ParenthesizedExpression(Expression expression) { + this.expression = expression; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + return new ParenthesizedExpression(this.expression.replace(variable, expression)); + } + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + @Override + public String toString() { + return "(" + expression.toString() + ")"; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/PlainExpression.java b/src/main/java/org/nittalab/rdlworkbench/ast/PlainExpression.java new file mode 100644 index 0000000..2215e98 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/PlainExpression.java @@ -0,0 +1,23 @@ +package org.nittalab.rdlworkbench.ast; + +//==================================================== +//TODO: CodeGenerator修正後削除 +//==================================================== + +public class PlainExpression extends Expression { + private String expression; + + public PlainExpression(String expression) { + this.expression = expression; + } + + @Override + public Expression replace(Variable variable, Expression newExpression) { + return new PlainExpression(expression.replace(variable.toString(), newExpression.toString())); + } + + @Override + public String toString() { + return expression; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/PlainStatement.java b/src/main/java/org/nittalab/rdlworkbench/ast/PlainStatement.java new file mode 100644 index 0000000..c197353 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/PlainStatement.java @@ -0,0 +1,18 @@ +package org.nittalab.rdlworkbench.ast; + +//==================================================== +//TODO: CodeGenerator修正後削除 +//==================================================== + +public class PlainStatement extends Statement { + private String code; + + public PlainStatement(String code) { + this.code = code; + } + + @Override + public String toString() { + return code; + } +} \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/PostfixExpression.java b/src/main/java/org/nittalab/rdlworkbench/ast/PostfixExpression.java new file mode 100644 index 0000000..ff86184 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/PostfixExpression.java @@ -0,0 +1,58 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents a postfix expression in AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + */ +public class PostfixExpression extends Expression { + public enum Operator { + INCREMENT("++"), DECREMENT("--"); + + Operator(String symbol) { + this.symbol = symbol; + } + + private final String symbol; + + @Override + public String toString() { + return symbol; + } + } + + private Expression operand; + + private Operator operator; + + public PostfixExpression(Expression operand, Operator operator) { + this.operand = operand; + this.operator = operator; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + return new PostfixExpression(operand.replace(variable, expression), operator); + } + + public Expression getOperand() { + return operand; + } + + public void setOperand(Expression operand) { + this.operand = operand; + } + + public Operator getOperator() { + return operator; + } + + public void setOperator(Operator operator) { + this.operator = operator; + } + + @Override + public String toString() { + return operand.toString() + operator.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/PrefixExpression.java b/src/main/java/org/nittalab/rdlworkbench/ast/PrefixExpression.java new file mode 100644 index 0000000..16b3adf --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/PrefixExpression.java @@ -0,0 +1,58 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents a prefix expression in AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + */ +public class PrefixExpression extends Expression { + public enum Operator { + INCREMENT("++"), DECREMENT("--"), PLUS("+"), MINUS("-"), NOT("!"); + + Operator(String symbol) { + this.symbol = symbol; + } + + private final String symbol; + + @Override + public String toString() { + return symbol; + } + } + + private Expression operand; + + private Operator operator; + + public PrefixExpression(Expression operand, Operator operator) { + this.operand = operand; + this.operator = operator; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + return new PrefixExpression(operand.replace(variable, expression), operator); + } + + public Expression getOperand() { + return operand; + } + + public void setOperand(Expression operand) { + this.operand = operand; + } + + public Operator getOperator() { + return operator; + } + + public void setOperator(Operator operator) { + this.operator = operator; + } + + @Override + public String toString() { + return operator.toString() + operand.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/PrimitiveType.java b/src/main/java/org/nittalab/rdlworkbench/ast/PrimitiveType.java new file mode 100644 index 0000000..00fbb23 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/PrimitiveType.java @@ -0,0 +1,34 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents a primitive type in the abstract syntax tree (AST). + * This class extends the {@code AnnotatableType}, allowing annotations + * to be attached to primitive types. + *

+ * Primitive types are: {@code boolean}, {@code byte}, {@code char}, {@code short}, {@code int}, {@code long}, {@code float}, {@code double} and {@code void} + * + * @author s-yamagiwa + */ +public class PrimitiveType extends AnnotatableType { + private String typeName; + + public PrimitiveType(String typeName) { + this.typeName = typeName; + } + + @Override + public String toString() { + if (getAnnotations().isEmpty()) { + return typeName; + } + + StringBuilder builder = new StringBuilder(); + for (Annotation annotation : getAnnotations()) { + builder.append(annotation.toString()); + builder.append(" "); + } + builder.append(typeName); + + return builder.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ReturnStatement.java b/src/main/java/org/nittalab/rdlworkbench/ast/ReturnStatement.java new file mode 100644 index 0000000..964900e --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ReturnStatement.java @@ -0,0 +1,21 @@ +package org.nittalab.rdlworkbench.ast; + +public class ReturnStatement extends Statement{ + private Expression expression; + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + @Override + public String toString() { + if (expression != null) { + return "return " + expression + ";"; + } + return "return;"; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/SimpleType.java b/src/main/java/org/nittalab/rdlworkbench/ast/SimpleType.java new file mode 100644 index 0000000..c3f3d76 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/SimpleType.java @@ -0,0 +1,39 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents a simple type in the AST, which is a type with a single identifier. + * For example, String, List, Map or MyClass. + * + * @author s-yamagiwa + */ +public class SimpleType extends AnnotatableType { + private String name; + + public SimpleType(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + if (getAnnotations().isEmpty()) { + return name; + } + + StringBuilder builder = new StringBuilder(); + for (Annotation annotation : getAnnotations()) { + builder.append(annotation.toString()); + builder.append(" "); + } + builder.append(name); + + return builder.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Statement.java b/src/main/java/org/nittalab/rdlworkbench/ast/Statement.java new file mode 100644 index 0000000..8b18777 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Statement.java @@ -0,0 +1,15 @@ +package org.nittalab.rdlworkbench.ast; + +public abstract class Statement extends ASTNode { + + @Override + public abstract String toString(); + + @Override + public boolean equals(Object another) { + if (!(another instanceof Statement)) { + return false; + } + return toString().equals(another.toString()); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/SuperMethodInvocation.java b/src/main/java/org/nittalab/rdlworkbench/ast/SuperMethodInvocation.java new file mode 100644 index 0000000..b030d0c --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/SuperMethodInvocation.java @@ -0,0 +1,74 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a super method invocation in AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + * @apiNote Type arguments aren't supported because it isn't necessary in DTRAM code generator. + */ +public class SuperMethodInvocation extends Expression { + private String methodName; + private List arguments; + + public SuperMethodInvocation(String methodName) { + this(methodName, List.of()); + } + + public SuperMethodInvocation(String methodName, List arguments) { + this.methodName = methodName; + this.arguments = arguments; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + List replacedExpressions = new ArrayList<>(); + + for (Expression argument : arguments) { + replacedExpressions.add(argument.replace(variable, expression)); + } + + return new SuperMethodInvocation(methodName, replacedExpressions); + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public List getArguments() { + return arguments; + } + + public void setArguments(List arguments) { + this.arguments = arguments; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + + builder.append("super.").append(methodName).append("("); + + if (!arguments.isEmpty()) { + for (int i = 0; i < arguments.size(); i++) { + Expression argument = arguments.get(i); + + builder.append(argument.toString()); + + if (i < arguments.size() - 1) { + builder.append(", "); + } + } + } + + builder.append(");"); + + return builder.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/ThisExpression.java b/src/main/java/org/nittalab/rdlworkbench/ast/ThisExpression.java new file mode 100644 index 0000000..5de7ebf --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/ThisExpression.java @@ -0,0 +1,13 @@ +package org.nittalab.rdlworkbench.ast; + +public class ThisExpression extends Expression { + @Override + public Expression replace(Variable variable, Expression expression) { + return this; + } + + @Override + public String toString() { + return "this"; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Throws.java b/src/main/java/org/nittalab/rdlworkbench/ast/Throws.java new file mode 100644 index 0000000..2246851 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Throws.java @@ -0,0 +1,29 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.HashSet; +import java.util.Set; + +public class Throws extends ASTNode { + private Set exceptions = new HashSet<>(); + + public Throws() { + } + + public void addException(String exception) { + exceptions.add(exception); + } + + public Set getExceptions() { + return exceptions; + } + + public String toString() { + String code = "throws "; + String delimiter = ""; + for (String exception: exceptions) { + code += delimiter + exception; + delimiter = ", "; + } + return code; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Type.java b/src/main/java/org/nittalab/rdlworkbench/ast/Type.java new file mode 100644 index 0000000..5545c68 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Type.java @@ -0,0 +1,37 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents an abstract base class for all types in an abstract syntax tree (AST). + * A type can represent various forms such as primitive types, simple types, + * parameterized types, or others as defined by subclasses. + * + * @author s-yamagiwa + */ +public abstract class Type extends ASTNode implements models.algebra.Type.ITypeImpl { + /** + * Returns whether this type is a primitive type or not. + * + * @return true if this type is a primitive type, false otherwise. + */ + public final boolean isPrimitiveType() { + return (this instanceof PrimitiveType); + } + + /** + * Returns whether this type is a simple type or not. + * + * @return true if this type is a simple type, false otherwise. + */ + public final boolean isSimpleType() { + return (this instanceof SimpleType); + } + + /** + * Returns whether this type is a parameterized type or not. + * + * @return true if this type is a parameterized type, false otherwise. + */ + public final boolean isParameterizedType() { + return (this instanceof ParameterizedType); + } +} \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/TypeDeclaration.java b/src/main/java/org/nittalab/rdlworkbench/ast/TypeDeclaration.java new file mode 100644 index 0000000..2e4a5ea --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/TypeDeclaration.java @@ -0,0 +1,98 @@ +package org.nittalab.rdlworkbench.ast; + +import java.util.*; + +public class TypeDeclaration extends AbstractTypeDeclaration implements IAnnotatable { + private List fields = new ArrayList<>(); + private List methods = new ArrayList<>(); + private Map annotations = new HashMap<>(); + private List implementsInterfaces = new ArrayList<>(); + + public TypeDeclaration(String typeName) { + this.typeName = typeName; + } + + public TypeDeclaration(String typeName, List fields) { + this.typeName = typeName; + this.fields = fields; + } + + public TypeDeclaration(String typeName, List fields, List methods) { + this.typeName = typeName; + this.fields = fields; + this.methods = methods; + } + + public void addImplementsInterface(String interfaceName) { + implementsInterfaces.add(interfaceName); + } + + public List getImplementsInterfaces() { + return implementsInterfaces; + } + + public void addField(FieldDeclaration field) { + fields.add(field); + } + + public void addMethod(MethodDeclaration method) { + methods.add(method); + } + + public void removeMethod(MethodDeclaration method) { + methods.remove(method); + } + + public void removeField(FieldDeclaration field) { + fields.remove(field); + } + + public List getFields() { + return fields; + } + + public List getMethods() { + return methods; + } + + public MethodDeclaration createConstructor() { + MethodDeclaration constructor = new MethodDeclaration(typeName, true); + addMethod(constructor); + return constructor; + } + + @Override + public Annotation getAnnotation(String name) { + return annotations.get(name); + } + + @Override + public Collection getAnnotations() { + return annotations.values(); + } + + @Override + public void addAnnotation(Annotation annotation) { + annotations.put(annotation.getElementName(), annotation); + } + + public String toString() { + String code = ""; + for (Annotation annotation: getAnnotations()) { + code += annotation.toString() + "\n"; + } + code += "public class " + typeName; + if (!implementsInterfaces.isEmpty()) { + code += " implements " + String.join(", ", implementsInterfaces); + } + code += " {\n"; + for (FieldDeclaration f: fields) { + code += "\t" + f.toString(); + } + for (MethodDeclaration m: methods) { + code += CodeUtil.insertTab(m.toString()); + } + code += "}"; + return code; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/TypeLiteral.java b/src/main/java/org/nittalab/rdlworkbench/ast/TypeLiteral.java new file mode 100644 index 0000000..5e3c59e --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/TypeLiteral.java @@ -0,0 +1,32 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents a type literal expression in the AST. + * + * @author s-yamagiwa + */ +public class TypeLiteral extends Expression { + private Type type; + + public TypeLiteral(Type type) { + this.type = type; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + return this; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + @Override + public String toString() { + return type.toString(); + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/Variable.java b/src/main/java/org/nittalab/rdlworkbench/ast/Variable.java new file mode 100644 index 0000000..24767cb --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/Variable.java @@ -0,0 +1,35 @@ +package org.nittalab.rdlworkbench.ast; + +/** + * Represents a variable in the AST (Abstract Syntax Tree) + * + * @author s-yamagiwa + */ +public class Variable extends Expression { + private String name; + + public Variable(String name) { + this.name = name; + } + + @Override + public Expression replace(Variable variable, Expression expression) { + if (this == variable) { + return expression; + } + return this; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/VariableDeclaration.java b/src/main/java/org/nittalab/rdlworkbench/ast/VariableDeclaration.java new file mode 100644 index 0000000..6aae27b --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/VariableDeclaration.java @@ -0,0 +1,68 @@ +package org.nittalab.rdlworkbench.ast; + +import models.algebra.Type; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class VariableDeclaration extends ASTNode implements IAnnotatable { + private Type type; + private String variableName; + private Expression optionalInitializer; + private Map annotations = new HashMap<>(); + + public VariableDeclaration(Type type, String variableName) { + this.type = type; + this.variableName = variableName; + } + + public VariableDeclaration(Type type, String variableName, Expression initializer) { + this(type, variableName); + this.optionalInitializer = initializer; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public String getName() { + return variableName; + } + + public void setName(String variableName) { + this.variableName = variableName; + } + + public Expression getInitializer() { return optionalInitializer; } + + public void setInitializer(Expression initializer) { this.optionalInitializer = initializer; } + + @Override + public Annotation getAnnotation(String name) { + return annotations.get(name); + } + + @Override + public Collection getAnnotations() { + return annotations.values(); + } + + @Override + public void addAnnotation(Annotation annotation) { + annotations.put(annotation.getElementName(), annotation); + } + + public String toString() { + String code = ""; + code += type.getInterfaceTypeName() + " " + variableName; + if (optionalInitializer != null) { + code += " = " + optionalInitializer; + } + return code; + } +} diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/VariableDeclarationStatement.java b/src/main/java/org/nittalab/rdlworkbench/ast/VariableDeclarationStatement.java new file mode 100644 index 0000000..cd1fb61 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/VariableDeclarationStatement.java @@ -0,0 +1,82 @@ +package org.nittalab.rdlworkbench.ast; + +import models.algebra.Type; + +import java.util.ArrayList; +import java.util.List; + +public class VariableDeclarationStatement extends Statement { + + private List modifiers = new ArrayList<>(); + private Type type = null; + private List fragments = new ArrayList<>(); + + public List getModifiers() { + return modifiers; + } + + public void setModifiers(List modifiers) { + this.modifiers = modifiers; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public List getFragments() { + return fragments; + } + + public void addFragment(VariableDeclaration fragment) { + if (fragment == null) return; + + if (this.type == null) { + this.type = fragment.getType(); + this.fragments.add(fragment); + } else { + if (this.type.equals(fragment.getType())) { + this.fragments.add(fragment); + } else { + System.err.println("Type mismatch: " + fragment); + } + } + } + + public void setFragments(List fragments) { + this.fragments = fragments; + + if (fragments != null && !fragments.isEmpty()) { + this.type = fragments.get(0).getType(); + } else { + this.type = null; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + for (Integer mod : modifiers) { + if (mod == Modifier.PRIVATE) sb.append("private "); + else if (mod == Modifier.PUBLIC) sb.append("public "); + else if (mod == Modifier.PROTECTED) sb.append("protected "); + else if (mod == Modifier.STATIC) sb.append("static "); + } + + if (this.type != null) { + sb.append(this.type.getInterfaceTypeName()).append(" "); + } + + for (int i = 0; i < fragments.size(); i++) { + sb.append(fragments.get(i).toString()); + if (i < fragments.size() - 1) sb.append(", "); + } + + sb.append(";"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/org/nittalab/rdlworkbench/ast/WhileStatement.java b/src/main/java/org/nittalab/rdlworkbench/ast/WhileStatement.java new file mode 100644 index 0000000..b16c5a5 --- /dev/null +++ b/src/main/java/org/nittalab/rdlworkbench/ast/WhileStatement.java @@ -0,0 +1,33 @@ +package org.nittalab.rdlworkbench.ast; + +public class WhileStatement extends Statement { + + private Expression expression; + private Statement body; + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public Statement getBody() { + return body; + } + + public void setBody(Statement body) { + this.body = body; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("while (").append(expression).append(") "); + if (body != null) { + sb.append(body); + } + return sb.toString(); + } +} \ No newline at end of file