From: Not Zed Date: Thu, 23 Mar 2023 08:50:14 +0000 (+1030) Subject: Initial import. X-Git-Url: https://code.zedzone.au/cvs?a=commitdiff_plain;h=ae1896278ef339934b8842660553d87cd2dd8f08;p=compilerz Initial import. --- ae1896278ef339934b8842660553d87cd2dd8f08 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e2dc638 --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ + +dist_VERSION=0.0.99 +dist_NAME=compilerz +dist_EXTRA= \ + README \ + build.xml \ + nbproject/build-impl.xml \ + nbproject/genfiles.properties \ + nbproject/project.properties \ + nbproject/project.xml + +include config.make + +java_MODULES = \ + notzed.scripta + +# auto-generate the _COMMANDS variables +define install-bin= +$1_COMMANDS = $(notdir $(wildcard src/$1/$(TARGET)/bin/*)) +bin/$1/$(TARGET)/bin/%: src/$1/$(TARGET)/bin/% + install -D -t $$(@D) $$< +endef +$(foreach mod,$(java_MODULES),$(eval $(call install-bin,$(mod)))) + +include java.make + +asm = org.ow2.asm:asm:9.4 \ + org.ow2.asm:asm-util:9.4 \ + org.ow2.asm:asm-tree:9.4 \ + org.ow2.asm:asm-analysis:9.4 \ + org.ow2.asm:asm-commons:9.4 + +maven_central_JARS = $(asm) + +include antlr4.make +include maven.make diff --git a/README b/README new file mode 100644 index 0000000..f9057e1 --- /dev/null +++ b/README @@ -0,0 +1,2 @@ + +Expriments with antlr and asm. diff --git a/antlr4.make b/antlr4.make new file mode 100644 index 0000000..09e622a --- /dev/null +++ b/antlr4.make @@ -0,0 +1,57 @@ +# +# Copyright (C) 2023 Michael Zucchi +# +# This is the copyright for antlr4.make +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# This processes antlr4 files. Include after java.make, before maven.make. + +# _ANTLR4 = list of grammar files without '.g4' extension. + +# They must be in src//gen/.g4 +# The sources are generated in the usual gen directory + +antlr4 = org.antlr:antlr4:4.12.0 \ + org.antlr:antlr4-runtime:4.12.0 \ + org.antlr:antlr-runtime:3.5.3 \ + org.antlr:ST4:4.3.4 \ + +maven_central_JARS += $(antlr4) + +antlr4_CLASSPATH=.lib/antlr4-4.12.0.jar \ + .lib/antlr4-runtime-4.12.0.jar \ + .lib/antlr-runtime-3.5.3.jar \ + .lib/ST4-4.3.4.jar + +dist_EXTRA+=antlr4.make + +define antlr4_targets= +$(if $($1-$2_ANTLR4PACKAGE),,$(error src/gen/$1/gen/gen.make: no $1-$2_ANTLR4PACKAGE defined)) +bin/status/$1-$2.antlr: src/$1/gen/$2.g4 + mkdir -p bin/gen/$1/gen bin/status + cd src/$1/gen && \ + $(JAVA) -cp $(subst $S,:,$(realpath $(antlr4_CLASSPATH))) \ + org.antlr.v4.Tool \ + -o ../../../bin/gen/$1/classes/$(subst .,/,$($1-$2_ANTLR4PACKAGE)) \ + -package $($1-$2_ANTLR4PACKAGE) \ + $($1-$2_ANTLR4FLAGS) \ + $2.g4 + touch $$@ +bin/status/$1.depjava: bin/status/$1-$2.antlr +endef + +#$(foreach m,$(java_MODULES),$(foreach g,$($m_ANTLR4),$(info $(call antlr4_targets,$m,$g)))) +$(foreach m,$(java_MODULES),$(foreach g,$($m_ANTLR4),$(eval $(call antlr4_targets,$m,$g)))) diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..412f012 --- /dev/null +++ b/build.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + Builds, tests, and runs the project compilerz. + + + diff --git a/config.make.in b/config.make.in new file mode 100644 index 0000000..eed42de --- /dev/null +++ b/config.make.in @@ -0,0 +1,14 @@ + +TARGET ?= linux-amd64 + +JAVA_HOME ?= /usr/local/jdk +JAVAFX_HOME ?= /usr/local/javafx-sdk + +JAVAMODPATH = $(JAVAFX_HOME)/lib .lib bin/$(TARGET)/lib +JAVACFLAGS = --source 19 + +JAVA ?= $(JAVA_HOME)/bin/java +JAVAC ?= $(JAVA_HOME)/bin/javac +JAR ?= $(JAVA_HOME)/bin/jar +JMOD ?= $(JAVA_HOME)/bin/jmod + diff --git a/java.make b/java.make new file mode 100644 index 0000000..ada3e80 --- /dev/null +++ b/java.make @@ -0,0 +1,425 @@ +# +# Copyright (C) 2019,2022 Michael Zucchi +# +# This is the copyright for java.make +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# General purpose modular java makefile that supports native library +# compilation directly. Non-recrusve implementation. +# +# Uses metamake programming with some file conventions to implement +# auto-make-like features. + +# Define modules +# -------------- +# java_MODULES list of java modules to compile. The sources must +# exist in src//classes. Resource files are +# stored in src//classes. Source-code +# generators must exist in src//gen. Native +# libraries must exist in src//jni. + +# native_MODULES list of native-only "modules". + + +# Global variables + +# JAVA_HOME location of jdk. +# JAVAC java compiler to use. Default is 'javac' on the path. +# JAVACFLAGS javac flags applied to all invocations. +# JAR jar command. +# JARFLAGS jar flags +# JMOD jmod command. +# JMODFLAGS jmod flags. +# JAVAFLAGS java flags for run targets + +# Module specific variables + +# _JDEPMOD Lists modules which this one depends on. + +# _JAVACFLAGS Extra module-specific flags for each command. +# _JARFLAGS +# _JMODFLAGS + +# all paths are relative to the root package name + +# _JAVA Java sources. If not set it is found from src//classes/(*.java) +# _RESOURCES .jar resources. If not set it is found from src//classes/(not *.java) +# _JAVA_GENERATED Java generated sources. +# _RESOURCES_GENERATED Java generated sources. + +# Variables for use in fragments + +# gen.make and jni.make can additionally make use of these variables + +# _gendir Location for files used in Java generation process (per project). +# _genjavadir Location where _JAVA_GENERATED .java files will be created (per project). +# _objdir Location for c objects (per target). +# _incdir Location for output includes, .jmod staging. +# _libdir Location for output libraries, .jmod staging. May point to _bindir. +# _bindir Location for output commands, .jmod staging. + +# Define libraries +# ---------------- + +# Each module can define one or more native libraries. + +# These are compiled after the java sources have been compiled as that +# process also generates any native binding headers. + +# _NATIVE_LIBRARIES list of libraries to build. +# library names match System.loadLibrary(). + +# Global variables + +# _LDFLAGS +# _LDLIBS +# _CPPFLAGS +# _CFLAGS +# _CC +# _CXXFLAGS +# _CXX +# SO shared library suffix +# LIB shared library prefix + +# Utility functions +# +# $(call library-path,,) will resolve to the library file name. + +# Per library variables. + +# _SOURCES .c source files for library. Paths are relative to src//native. +# _CXXSOURCES .c source files for library. Paths are relative to src//native. +# _HEADERS header files for install/jmod +# _COMMANDS commands/bin/scripts for install/jmod + +# _LDFLAGS link flags +# _LIBADD extra objects to add to link line +# _LDLIBS link libraries +# _CPPFLAGS c and c++ pre-processor flags. "-Isrc//jni -Ibin/include/" is implicit. +# _CCFLAGS c compiler flags +# _CXXFLAGS c++ compiler flags + +# _DEPENDENCIES A list of other objects on which this library depends before linking. + +# .c and .cc files have dependencies automatically generated + +# Targets +# ------- + +# make gen only generate java sources +# make clean rm -rf bin +# make dist create dist tar in bin/ +# make | make jar make all jars and jmods + +# Outputs +# ------- + +# All intermediate and output files are written to bin/ + +# This layout is enforced by javac +# bin/include// .h files from javac -h +# bin/modules// .class files from javac + +# This layout is convenient for netbeans +# bin/gen//gen/ .c, exe files for generator free use +# bin/gen//classes/ .java files from generator _JAVA_GENERATED + +# Working files +# bin/status/ marker files for makefile + +# bin///lib .so librareies for jmod _LIBRARIES = libname +# bin///obj .o, .d files for library _SOURCES +# bin///include .h files for jmod _HEADERS +# bin///.jmod .jmod module + +# Output files +# bin//lib/ modular jar files and shared libraries for GNU/linux dev +# bin//include/ header files for exported shared libraries +# bin//bin/ shared libraries for microsoft dev +# bin//jmods/ jmod files for 'jlink' use. + +# ###################################################################### + +all_MODULES = $(java_MODULES) $(native_MODULES) + +E:= +S:=$(E) $(E) +SO=$($(TARGET)_SO) +LIB=$($(TARGET)_LIB) + +# Define some useful variables before including fragments +define common_variables= +$1_gendir:=bin/gen/$1/gen +$1_genjavadir:=bin/gen/$1/classes +$1_objdir:=bin/$1/$(TARGET)/obj +$1_incdir:=bin/$1/$(TARGET)/include +$1_libdir:=$$(if $$(filter windows-%,$(TARGET)),bin/$1/$(TARGET)/bin,bin/$1/$(TARGET)/lib) +$1_bindir:=bin/$1/$(TARGET)/bin +endef + +define java_variables= +ifndef $1_JAVA +$1_JAVA := $$(shell cd src/$1/classes && find * -type f -name '*.java') +endif +ifndef $1_RESOURCES +$1_RESOURCES := $$(shell cd src/$1/classes && find * -type f \! -name '*.java') +endif +endef + +java_libdir:=$(if $(filter windows-%,$(TARGET)),bin/$(TARGET)/bin,bin/$(TARGET)/lib) +java_bindir:=bin/$(TARGET)/bin +java_jardir:=bin/$(TARGET)/lib +java_incdir:=bin/$(TARGET)/include +java_jmoddir:=bin/$(TARGET)/jmods + +$(foreach module,$(java_MODULES) $(native_MODULES),$(eval $(call common_variables,$(module)))) +$(foreach module,$(java_MODULES),$(eval $(call java_variables,$(module)))) + +# ###################################################################### + +all: +jar: +gen: + +.PHONY: all clean jar gen $(java_MODULES) dist +clean: + rm -rf bin + +# dist things +dist_TAR = bin/$(dist_NAME)-$(dist_VERSION).tar.gz +dist_FILES = config.make.in java.make Makefile src $(dist_EXTRA) + +# Gen is things that go into the jar (sources and resources) +include $(wildcard $(all_MODULES:%=src/%/gen/gen.make)) +# Native is things that go into the sdk/jmod +include $(wildcard $(all_MODULES:%=src/%/native/native.make)) + +# ###################################################################### + +# create module depencies +# variables: +# _sdk is the target location of an expanded 'sdk' for this module +# it resides in a common location bin// +# _jmod is the target location of a staging area for jmod files +# is resides in a per-module lcoation bin/// +# _java is all the targets that will cause the invocation of javac +# it includes the module source, generated sources, and sentinals for generated sources + +# targets: +# bin/status/.depjava marks all source/generated sources are ready/updated +# bin/status/.depjar all compiled class files and resources are ready/updated +# bin/status/.sdk all files are available in bin/ as if it was an installed image + +define module_vars= +$1_sdk := $(addprefix $(java_bindir)/,$($1_COMMANDS)) $(addprefix $(java_libdir)/,$($1_LIBRARIES)) $($1_NATIVE_LIBRARIES:%=$(java_libdir)/lib%.so) +$1_jmod := $(addprefix $($1_bindir)/,$($1_COMMANDS)) $(addprefix $($1_libdir)/,$($1_LIBRARIES)) $($1_NATIVE_LIBRARIES:%=$($1_libdir)/lib%.so) +$1_java :=$($1_JAVA:%=src/$1/classes/%) $($1_JAVA_GENERATED:%=$($1_genjavadir)/%) +$1_resources:= $($1_RESOURCES:%=bin/modules/$1/%) $($1_RESOURCES_GENERATED:%=bin/modules/$1/%) +$1_depjava := $($1_API:%=bin/status/$1-%.export) $(patsubst %,bin/status/%.classes, $(filter $($1_JDEPMOD),$(java_MODULES))) + +#ifneq ("$$(strip $$($1_java) $$($1_depjava))", "") +bin/status/$1.depjava: $$($1_java) $$($1_depjava) + @install -d $$(@D) + touch $$@ +bin/status/$1.depjar: bin/status/$1.classes $$($1_resources) + @install -d $$(@D) + touch $$@ +bin/status/$1.depmod: bin/status/$1.classes $$($1_resources) $$($1_jmod) + @install -d $$(@D) + touch $$@ +bin/status/$1.sdk: $(java_jardir)/$1.jar +jar: $(java_jardir)/$1.jar +gen: bin/status/$1.depjava +$1 all: $(java_jardir)/$1.jar $(java_jmoddir)/$1.jmod +#else +# acutally not sure here? +#$1 all: bin/status/$1.sdk +#endif + +$1-sdk sdk: bin/status/$1.sdk + +bin/status/$1.sdk: $$($1_sdk) $$($1_jmod) + @install -d $$(@D) + touch $$@ + +endef + +#$(foreach m,$(all_MODULES),$(info $(call module_vars,$m))) +$(foreach m,$(all_MODULES),$(eval $(call module_vars,$m))) + +# ###################################################################### +# notzed.nativez export-api +# ###################################################################### + +define api_targets= +bin/status/$1-$2.export: src/$1/gen/$2.api src/$1/gen/$2.h +bin/status/$1-$2.export: + mkdir -p bin/gen/$1/gen bin/status + $(NATIVEZ_HOME)/bin/export-api \ + -w bin/gen/$1/gen -d bin/gen/$1/classes $($1_APIFLAGS) $($1_$2_APIFLAGS) src/$1/gen/$2.api + touch $$@ + +bin/status/$1-$2.export.d: + @$(NATIVEZ_HOME)/bin/export-api -M -MT "$$(@:.d=) $$@" -MF $$@ \ + -w bin/gen/$1/gen -d bin/gen/$1/classes $($1_APIFLAGS) $($1_$2_APIFLAGS) src/$1/gen/$2.api 2>/dev/null + +$(if $(filter clean dist gen,$(MAKECMDGOALS)),,-include bin/status/$1-$2.export.d) +endef + +$(foreach m,$(all_MODULES),$(foreach a,$($m_API),$(eval $(call api_targets,$m,$a)))) + +# ###################################################################### +# Java +# ###################################################################### + +# Build targets for java modules + +define java_targets= + +# Create (modular) jar +$(java_jardir)/$1.jar: bin/status/$1.depjar + @install -d $$(@D) + $(JAR) cf $$@ \ + $(JARFLAGS) $$($(1)_JARFLAGS) \ + -C bin/modules/$(1) . + +# Create a jmod +$(java_jmoddir)/$1.jmod: bin/status/$1.depmod + rm -f $$@ + @install -d $$(@D) + $$(JMOD) create \ + $$(JMODFLAGS) $$($(1)_JMODFLAGS) \ + --target-platform $(TARGET) \ + --class-path bin/modules/$(1) \ + $$(if $$(wildcard bin/$(1)/$(TARGET)/include),--header-files bin/$(1)/$(TARGET)/include) \ + $$(if $$(wildcard src/$(1)/legal),--legal-notices src/$(1)/legal) \ + $$(if $$(wildcard bin/$(1)/$(TARGET)/bin),--cmds bin/$(1)/$(TARGET)/bin) \ + $$(if $$(wildcard bin/$(1)/$(TARGET)/lib),--libs bin/$(1)/$(TARGET)/lib) \ + $$@ + +# Create an IDE source zip, paths have to match --module-source-path +$(java_jardir)/$1-sources.zip: bin/status/$1.depjar + @install -d $$(@D) + $(JAR) -c -f $$@ -M \ + $$($1_JAVA:%=-C src/$1/classes %) \ + $$($1_JAVA_GENERATED:%=-C bin/gen/$1/classes %) + +# resources +bin/modules/$1/%: src/$1/classes/% + install -vD $$< $$@ +bin/modules/$1/%: $($1_gejavadir)/% + install -vD $$< $$@ + +# Compile module. +bin/status/$1.classes: bin/status/$1.depjava + @install -d $$(@D) + $(JAVAC) \ + --module-source-path "src/*/classes:bin/gen/*/classes" \ + $(if $(JAVAMODPATH),--module-path $(subst $(S),:,$(JAVAMODPATH))) \ + $(JAVACFLAGS) $($1_JAVACFLAGS) \ + -d bin/modules \ + -m $1 \ + $$($1_JAVA:%=src/$1/classes/%) \ + $$($1_JAVA_GENERATED:%=bin/gen/$1/classes/%) + touch $$@ +endef + +#$(foreach module,$(java_MODULES),$(info $(call java_targets,$(module)))) +$(foreach module,$(java_MODULES),$(eval $(call java_targets,$(module)))) + +# ###################################################################### + +# setup run-* targets +define run_targets= +run-$1/$2: bin/status/$1.sdk $($1_JDEPMOD:%=bin/status/%.sdk) + LD_LIBRARY_PATH=$(FFMPEG_HOME)/lib \ + $(JAVA) \ + $(if $(strip $(JAVAMODPATH) $($1_JAVAMODPATH)),--module-path $(subst $(S),:,$(strip $(JAVAMODPATH) $($1_JAVAMODPATH)))) \ + $(JMAINFLAGS) $($1_JMAINFLAGS) \ + -m $1/$2 \ + $(ARGV) +.PHONY: run-$1/$2 +endef + +#$(foreach module,$(java_MODULES),$(foreach main,$($(module)_JMAIN),$(info $(call run_targets,$(module),$(main))))) +$(foreach module,$(java_MODULES),$(foreach main,$($(module)_JMAIN),$(eval $(call run_targets,$(module),$(main))))) + +# ###################################################################### +# C and c++ native library support +# ###################################################################### + +define native_library= +# Rule for library $$2 in module $$1 +$2_OBJS = $(patsubst %.c, $($1_objdir)/%.o, $($2_SOURCES)) \ + $(patsubst %.cc, $($1_objdir)/%.o, $($2_CXXSOURCES)) +$2_SRCS = $(addprefix src/$1/native/,$($2_SOURCES)) +$2_SO = $($1_libdir)/$(LIB)$2$(SO) + +# Copy anything from staging area for jmods bin/module//* to sdk area bin//* +$(java_libdir)/%: $($(1)_libdir)/% + @install -d $$(@D) + ln -fs $$(abspath $$<) $$@ +$(java_bindir)/%: $($(1)_bindir)/% + @install -d $$(@D) + ln -fs $$(abspath $$<) $$@ +$(java_incdir)/%: $($(1)_incdir)/% + @install -d $$(@D) + ln -fs $$(abspath $$<) $$@ + +$($1_libdir)/$(LIB)$2$(SO): $$($2_OBJS) $($2_LIBADD) $($2_DEPENDENCIES) + @install -d $$(@D) + $($(TARGET)_CC) -o $$@ -shared \ + $($(TARGET)_LDFLAGS) $($2_LDFLAGS) $$($2_OBJS) $($2_LIBADD) $($(TARGET)_LDLIBS) $($2_LDLIBS) + +$($1_objdir)/%.o: src/$1/native/%.c + @install -d $$(@D) + $($(TARGET)_CC) -Isrc/$1/native -Ibin/include/$1 \ + $($(TARGET)_CPPFLAGS) $($2_CPPFLAGS) \ + $($(TARGET)_CFLAGS) $($2_CFLAGS) -c -o $$@ $$< + +$($1_objdir)/%.o: src/$1/native/%.cc + @install -d $$(@D) + $($(TARGET)_CXX) -Isrc/$1/native -Ibin/include/$1 \ + $($(TARGET)_CPPFLAGS) $($2_CPPFLAGS) \ + $($(TARGET)_CXXFLAGS) $($2_CXXFLAGS) -c -o $$@ $$< + +# auto-dependencies for c files +$($1_objdir)/%.d: src/$1/native/%.c + @install -d $$(@D) + @rm -f $$@ + @$($(TARGET)_CC) -MM -MT "$$(@:.d=.o) $$@" -Isrc/$1/jni -Ibin/include/$1 \ + $($(TARGET)_CPPFLAGS) $($2_CPPFLAGS) $$< -o $$@ 2>/dev/null + +# auto-dependencies for c++ files +$($1_objdir)/%.d: src/$1/native/%.cc + @install -d $$(@D) + @rm -f $$@ + @$($(TARGET)_CXX) -MM -MT "$$(@:.d=.o) $$@" -Isrc/$1/jni -Ibin/include/$1 \ + $($(TARGET)_CPPFLAGS) $($2_CPPFLAGS) $$< -o $$@ 2>/dev/null + +$(if $(filter clean dist gen,$(MAKECMDGOALS)),,-include $$($2_OBJS:.o=.d)) +endef + +#$(foreach module,$(all_MODULES),$(foreach library,$($(module)_NATIVE_LIBRARIES),$(info $(call native_library,$(module),$(library))))) +$(foreach module,$(all_MODULES),$(foreach library,$($(module)_NATIVE_LIBRARIES),$(eval $(call native_library,$(module),$(library))))) + +# ###################################################################### + +dist: + @install -d bin + tar cfz bin/$(dist_NAME)-$(dist_VERSION).tar.gz \ + --transform=s,^,$(dist_NAME)-$(dist_VERSION)/, \ + $(dist_FILES) diff --git a/maven.make b/maven.make new file mode 100644 index 0000000..c48227c --- /dev/null +++ b/maven.make @@ -0,0 +1,87 @@ +# +# Copyright (C) 2021 Michael Zucchi +# +# This is the copyright for maven.make +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# This lets one download maven packages using simple automake syntax. + +# maven__URL = baseurl + +# Define the base url. maven_central_URL is already defined as +# maven_central_URL:=https://repo1.maven.org/maven2 + +# maven__JARS = group:artifact:version group:artifact:version ... + +# Define the artifacts required from the given maven repository. + +# That's it! + +# It defines several make targets. + +# make maven-init +# Will download the jar files. + +# make maven-verify +# Will download and check the signatures using gpg. The public key +# required for verification must be imported to gpg separately. + +# make distclean +# Will delete .lib + +# define maven central +maven_central_URL:=https://repo1.maven.org/maven2 +maven_repository_URL:=https://mvnrepository.com/artifact + +# find out what repositories the makefile defined +maven_REPOS=$(patsubst maven_%_URL,%,$(filter maven_%_URL,$(.VARIABLES))) + +dist_EXTRA+=maven.make + +# (group artifact version baseurl) +define maven_func= +$2_jar=.lib/$2-$3.jar +.lib/$2-$3.jar: + mkdir -p .lib + wget -O $$@ $(4)/$(subst .,/,$1)/$2/$3/$2-$3.jar || ( rm $$@ ; exit 1 ) +.lib/$2-$3.pom: + mkdir -p .lib + wget -O $$@ $(4)/$(subst .,/,$1)/$2/$3/$2-$3.pom || ( rm $$@ ; exit 1 ) +.lib-sources/$2-$3-sources.jar: + mkdir -p .lib-sources + wget -O $$@ $(4)/$(subst .,/,$1)/$2/$3/$2-$3-sources.jar || ( rm $$@ ; exit 1 ) +.lib-javadoc/$2-$3-javadoc.jar: + mkdir -p .lib-javadoc + wget -O $$@ $(4)/$(subst .,/,$1)/$2/$3/$2-$3-javadoc.jar || ( rm $$@ ; exit 1 ) +.lib/$2-$3.jar.asc: .lib/$2-$3.jar + wget -O $$@ $(4)/$(subst .,/,$1)/$2/$3/$2-$3.jar.asc + gpg --batch --verify $$@ $$< || ( rm $$@ ; echo "GPG verification failed, you may need to import the public key." ; exit 1 ) +maven-init: .lib/$2-$3.jar .lib-sources/$2-$3-sources.jar .lib-javadoc/$2-$3-javadoc.jar .lib/$2-$3.pom +maven-verify: .lib/$2-$3.jar.asc +endef + +maven-init: +maven-verify: + +.PHONY: maven-init maven-verify + +$(foreach repo,$(maven_REPOS),\ + $(foreach jar,$(maven_$(repo)_JARS), \ + $(eval $(call maven_func,$(word 1,$(subst :, ,$(jar))),$(word 2,$(subst :, ,$(jar))),$(word 3,$(subst :, ,$(jar))),$(maven_$(repo)_URL))))) + +distclean: + rm -rf .lib .lib-javadoc .lib-sources + diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml new file mode 100644 index 0000000..74009e9 --- /dev/null +++ b/nbproject/build-impl.xml @@ -0,0 +1,1866 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +package netbeans; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +public class CoalesceKeyvalue extends Task { + private String property; + + public void setProperty(String property) { + this.property = property; + } + + private String value; + + public void setValue(String value) { + this.value = value; + } + + private String valueSep; + + public void setValueSep(String valueSep) { + this.valueSep = valueSep; + } + + private String entrySep; + + public void setEntrySep(String entrySep) { + this.entrySep = entrySep; + } + + private String multiSep; + + public void setMultiSep(String multiSep) { + this.multiSep = multiSep; + } + + private String outSep; + + public void setOutSep(String outSep) { + this.outSep = outSep; + } + + @Override + public void execute() throws BuildException { + List<String> result = new ArrayList<>(); + Map<String, List<String>> module2Paths = new HashMap<>(); + + for (String entry : value.split(Pattern.quote(entrySep))) { + String[] keyValue = entry.split(Pattern.quote(valueSep), 2); + if (keyValue.length == 1) { + result.add(keyValue[0]); + } else { + module2Paths.computeIfAbsent(keyValue[0], s -> new ArrayList<>()) + .add(keyValue[1].trim()); + } + } + module2Paths.entrySet() + .stream() + .forEach(e -> result.add(e.getKey() + valueSep + e.getValue().stream().collect(Collectors.joining(multiSep)))); + getProject().setProperty(property, result.stream().collect(Collectors.joining(" " + entrySep))); + } + +} + + + + +package netbeans; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +public class ModsourceRegexp extends Task { + private String property; + + public void setProperty(String property) { + this.property = property; + } + + private String filePattern; + + public void setFilePattern(String filePattern) { + this.filePattern = filePattern; + } + + private String modsource; + + public void setModsource(String modsource) { + this.modsource = modsource; + } + + private List<String> expandGroup(String grp) { + List<String> exp = new ArrayList<>(); + String item = ""; + int depth = 0; + + for (int i = 0; i < grp.length(); i++) { + char c = grp.charAt(i); + switch (c) { + case '{': + if (depth++ == 0) { + continue; + } + break; + case '}': + if (--depth == 0) { + exp.add(item); + continue; + } + break; + case ',': + if (depth == 1) { + exp.add(item); + item = ""; + continue; + } + default: + break; + } + item = item + c; + } + return exp; + } + + private List<String> pathVariants(String spec) { + return pathVariants(spec, new ArrayList<>()); + } + + private List<String> pathVariants(String spec, List<String> res) { + int start = spec.indexOf('{'); + if (start == -1) { + res.add(spec); + return res; + } + int depth = 1; + int end; + for (end = start + 1; end < spec.length() && depth > 0; end++) { + char c = spec.charAt(end); + switch (c) { + case '{': depth++; break; + case '}': depth--; break; + } + } + String prefix = spec.substring(0, start); + String suffix = spec.substring(end); + expandGroup(spec.substring(start, end)).stream().forEach(item -> { + pathVariants(prefix + item + suffix, res); + }); + return res; + } + + private String toRegexp2(String spec, String filepattern, String separator) { + List<String> prefixes = new ArrayList<>(); + List<String> suffixes = new ArrayList<>(); + pathVariants(spec).forEach(item -> { + suffixes.add(item); + }); + String tail = ""; + String separatorString = separator; + if ("\\".equals(separatorString)) { + separatorString = "\\\\"; + } + if (filepattern != null && !Objects.equals(filepattern, tail)) { + tail = separatorString + filepattern; + } + return "([^" + separatorString +"]+)\\Q" + separator + "\\E(" + suffixes.stream().collect(Collectors.joining("|")) + ")" + tail; + } + + @Override + public void execute() throws BuildException { + getProject().setProperty(property, toRegexp2(modsource, filePattern, getProject().getProperty("file.separator"))); + } + +} + + + + +package netbeans; + +import java.io.File; +import java.util.Arrays; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; + +public class ModuleInfoSelector extends BaseExtendSelector { + + @Override + public boolean isSelected(File basedir, String filename, File file) throws BuildException { + String extension = Arrays.stream(getParameters()) + .filter(p -> "extension".equals(p.getName())) + .map(p -> p.getValue()) + .findAny() + .get(); + return !new File(file, "module-info." + extension).exists(); + } + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @{paths} + + + + + + + + + + + + @{paths} + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set src.gen.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.modules.dir + Must set dist.javadoc.dir + Must set build.test.modules.dir + Must set build.test.results.dir + Must set build.classes.excludes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No main class specified + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties new file mode 100644 index 0000000..f0c9780 --- /dev/null +++ b/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=78569814 +build.xml.script.CRC32=d88c472e +build.xml.stylesheet.CRC32=32069288@1.21 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=78569814 +nbproject/build-impl.xml.script.CRC32=160900c8 +nbproject/build-impl.xml.stylesheet.CRC32=d1ebcf0f@1.21 diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..31e3525 --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,105 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=compilerz +application.vendor=notzed +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +build.modules.dir=${build.dir}/modules +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.modules.dir=${build.dir}/test/modules +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.modulepath=\ + ${run.modulepath} +debug.test.classpath=\ + ${run.test.classpath} +debug.test.modulepath=\ + ${run.test.modulepath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.javadoc.dir=${dist.dir}/javadoc +dist.jlink.dir=${dist.dir}/jlink +dist.jlink.output=${dist.jlink.dir}/compilerz +endorsed.classpath= +excludes= +file.reference.antlr4-runtime-4.12.0.jar=.lib/antlr4-runtime-4.12.0.jar +file.reference.asm-9.4.jar=.lib/asm-9.4.jar +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.external.vm=false +javac.modulepath=\ + ${file.reference.asm-9.4.jar}:\ + ${file.reference.antlr4-runtime-4.12.0.jar} +javac.processormodulepath= +javac.processorpath=\ + ${javac.classpath} +javac.source=19 +javac.target=19 +javac.test.classpath=\ + ${javac.classpath} +javac.test.modulepath=\ + ${javac.modulepath}:\ + ${build.modules.dir} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.html5=false +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.reference.antlr4-runtime-4.12.0.jar=.lib-javadoc/antlr4-runtime-4.12.0-javadoc.jar +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +# The jlink additional root modules to resolve +jlink.additionalmodules= +# The jlink additional command line parameters +jlink.additionalparam= +jlink.launcher=true +jlink.launcher.name=compilerz +main.class=au.notzed.scripta.Compiler +platform.active=default_platform +project.license=gpl3-notzed +run.classpath= +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.modulepath=\ + ${javac.modulepath}:\ + ${build.modules.dir} +run.test.classpath=\ + ${javac.test.classpath} +run.test.modulepath=\ + ${javac.test.modulepath}:\ + ${build.test.modules.dir} +source.encoding=UTF-8 +source.reference.antlr4-runtime-4.12.0.jar=.lib-sources/antlr4-runtime-4.12.0-sources.jar +src.dir=src +src.dir.path=classes +src.gen.dir=bin/gen +src.gen.dir.path=classes +test.src.dir=src +test.src.dir.path=tests diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..4be5939 --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,16 @@ + + + org.netbeans.modules.java.j2semodule + + + compilerz + + + + + + + + + + diff --git a/src/notzed.scripta/classes/au/notzed/scripta/AST.java b/src/notzed.scripta/classes/au/notzed/scripta/AST.java new file mode 100644 index 0000000..7756507 --- /dev/null +++ b/src/notzed.scripta/classes/au/notzed/scripta/AST.java @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2023 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package au.notzed.scripta; + +import java.util.List; +import java.util.Optional; + +public abstract class AST { + + public final int lineNo; + + // visit children how? + public abstract void accept(ASTVisitor av); + + public void visitChildren(ASTVisitor av) { + } + + public void accept(List list, ASTVisitor av) { + for (AST s: list) { + s.accept(av); + } + } + + public AST(int lineNo) { + this.lineNo = lineNo; + } + + enum ReferenceScope { + LOCAL, + GLOBAL, + PLAYER + } + + enum XUnaryOp { + NOP, // for + + NEG, + NOT, + } + + enum XBinaryOp { + // arithmetic + ADD, + SUB, + MUL, + DIV, + MOD, + // bitwise + LSR, + LSL, + ASR, + AND, + ORR, + XOR, + // compare + CLT, + CLE, + CGT, + CGE, + CEQ, + CNE, + // boolean + AAND, + OOR, + XXOR, + } + + public static class ScriptA extends AST { + List statements; + + public ScriptA(List statements) { + super(0); + this.statements = statements; + } + + @Override + public void accept(ASTVisitor av) { + accept(statements, av); + } + } + + public static class Statements extends AST { + List statements; + + public Statements(int lineNo, List statements) { + super(lineNo); + this.statements = statements; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + accept(statements, av); + } + + public static final Statements EMPTY = new Statements(0, List.of()); + } + + /* **** statements */ + public abstract static class Statement extends AST { + public Statement(int lineNo) { + super(lineNo); + } + } + + static class SIf extends Statement { + final Expression test; + final Statements then; + final Optional rest; + + public SIf(int lineNo, Expression test, Statements then) { + super(lineNo); + this.test = test; + this.then = then; + this.rest = Optional.empty(); + } + + public SIf(int lineNo, Expression test, Statements then, Statements rest) { + super(lineNo); + this.test = test; + this.then = then; + this.rest = Optional.of(rest); + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + test.accept(av); + then.accept(av); + rest.ifPresent(r -> r.accept(av)); + } + } + + static class SWhile extends Statement { + final Expression test; + final Statements when; + + public SWhile(int lineNo, Expression test, Statements when) { + super(lineNo); + this.test = test; + this.when = when; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + test.accept(av); + when.accept(av); + } + } + + static class SDeclare extends Statement { + final XReference ref; + + public SDeclare(int lineNo, AST.XReference ref) { + super(lineNo); + this.ref = ref; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + ref.accept(av); + } + } + + static class SAssign extends Statement { + final XReference ref; + final Expression value; + + public SAssign(int lineNo, AST.XReference ref, AST.Expression value) { + super(lineNo); + this.ref = ref; + this.value = value; + + System.out.printf(" new assign %s = %s\n", ref, value); + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + ref.accept(av); + value.accept(av); + } + } + + enum SBreakType { + CONTINUE, + BREAK, + } + + static class SBreak extends Statement { + SBreakType op; + Optional label; + + public SBreak(int lineNo, SBreakType op) { + super(lineNo); + this.op = op; + this.label = Optional.empty(); + } + + public SBreak(int lineNo, SBreakType op, String label) { + super(lineNo); + this.label = Optional.of(label); + this.op = op; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + } + + static class SReturn extends Statement { + Optional res; + + public SReturn(int lineNo) { + super(lineNo); + res = Optional.empty(); + } + + public SReturn(int lineNo, Expression res) { + super(lineNo); + this.res = Optional.of(res); + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + res.ifPresent(r -> r.accept(av)); + } + } + + static class SCall extends Statement { + XCall call; + + public SCall(int lineNo, XCall call) { + super(lineNo); + this.call = call; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + call.accept(av); + } + } + + /* **** expressions */ + abstract static class Expression extends AST { + public Expression(int lineNo) { + super(lineNo); + } + } + + static class XUnary extends Expression { + XUnaryOp op; + Expression right; + + public XUnary(int lineNo, XUnaryOp op, Expression right) { + super(lineNo); + this.op = op; + this.right = right; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + right.accept(av); + } + } + + static class XBinary extends Expression { + XBinaryOp op; + Expression left, right; + + public XBinary(int lineNo, XBinaryOp op, Expression left, Expression right) { + super(lineNo); + this.op = op; + this.left = left; + this.right = right; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + left.accept(av); + right.accept(av); + } + } + + static class XReference extends Expression { + String name; + + public XReference(int lineNo, String name) { + super(lineNo); + this.name = name; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + } + + static class XCall extends Expression { + XReference ref; + List params; + + public XCall(int lineNo, XReference ref, List params) { + super(lineNo); + this.ref = ref; + this.params = params; + + System.out.printf("new call: %s ", ref.name); + params.forEach(p -> System.out.printf(" %s", p)); + System.out.println(); + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + ref.accept(av); + accept(params, av); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("[call "); + sb.append(ref); + params.forEach(x -> sb.append(x.toString()).append(", ")); + sb.append("]"); + return sb.toString(); + } + } + + // return type? + static class XFunction extends Expression { + final List params; + final Statements statements; + + public XFunction(int lineNo, List params, Statements statements) { + super(lineNo); + this.params = params; + this.statements = statements; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + + @Override + public void visitChildren(ASTVisitor av) { + statements.accept(av); + } + } + + static class XInteger extends Expression { + long value; + + public XInteger(int lineNo, long value) { + super(lineNo); + this.value = value; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + } + + static class XReal extends Expression { + double value; + + public XReal(int lineNo, double value) { + super(lineNo); + this.value = value; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + } + + static class XString extends Expression { + String value; + + public XString(int lineNo, String value) { + super(lineNo); + this.value = value; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + } + + static class XBool extends Expression { + boolean value; + + public XBool(int lineNo, boolean value) { + super(lineNo); + this.value = value; + } + + @Override + public void accept(ASTVisitor av) { + av.visit(this); + } + } +} diff --git a/src/notzed.scripta/classes/au/notzed/scripta/ASTBuilder.java b/src/notzed.scripta/classes/au/notzed/scripta/ASTBuilder.java new file mode 100644 index 0000000..742f119 --- /dev/null +++ b/src/notzed.scripta/classes/au/notzed/scripta/ASTBuilder.java @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2023 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package au.notzed.scripta; + +import au.notzed.scripta.AST.*; +import static au.notzed.scripta.ScriptAParser.*; +import java.util.ArrayList; +import java.util.List; + +import org.antlr.v4.runtime.Token; + +public class ASTBuilder extends ScriptABaseVisitor { + + List errors = new ArrayList<>(); + + @Override + public AST.ScriptA visitScript(ScriptContext ctx) { + return new ScriptA(visitStatements(ctx.statements()).statements); + } + + @Override + public AST.Statements visitStatements(StatementsContext ctx) { + System.out.printf("statements %s\n", ctx); + return new AST.Statements(ctx.start.getLine(), ctx.statement().stream().map(this::visitStatement).toList()); + } + + public AST.Statement visitStatement(StatementContext ctx) { + System.out.println("visit statement " + ctx.getText()); + return (AST.Statement)visit(ctx); + } + + @Override + public AST.SIf visitIfStatement(IfStatementContext ctx) { + System.out.println("visit if statement " + ctx.getText()); + ValueExprContext valX = ctx.valueExpr(); + AST ast = ctx.valueExpr().accept(this); + if (ctx.rest == null) { + return new AST.SIf(ctx.start.getLine(), (Expression)ctx.valueExpr().accept(this), visitStatements(ctx.then)); + } else { + return new AST.SIf(ctx.start.getLine(), (Expression)ctx.valueExpr().accept(this), visitStatements(ctx.then), visitStatements(ctx.rest)); + } + } + + @Override + public AST.SWhile visitWhileStatement(WhileStatementContext ctx) { + System.out.println("visit while statement " + ctx.getText()); + return new SWhile(ctx.start.getLine(), (Expression)ctx.valueExpr().accept(this), visitStatements(ctx.when)); + } + + @Override + public AST visitDeclStatement(DeclStatementContext ctx) { + System.out.println("visit decl statement " + ctx.getText()); + return new SDeclare(ctx.start.getLine(), visitReference(ctx.reference())); + } + + @Override + public AST.SAssign visitAssignStatement(AssignStatementContext ctx) { + System.out.println("visit assign statement " + ctx.getText()); + return new AST.SAssign(ctx.start.getLine(), visitReference(ctx.reference()), visitValueExpr(ctx.valueExpr())); + } + + public AST.Expression visitValueExpr(ValueExprContext ctx) { + return (AST.Expression)ctx.accept(this); + } + + @Override + public AST visitCallStatement(CallStatementContext ctx) { + System.out.println("visit call statement " + ctx.getText()); + return new SCall(ctx.start.getLine(), visitCallExpr(ctx.callExpr())); + } + + @Override + public AST.XFunction visitFuncExpr(FuncExprContext ctx) { + System.out.println("visit func expr " + ctx.getText()); + return new XFunction( + ctx.start.getLine(), + ctx.ID().stream().map(a -> a.getText()).toList(), + ctx.statements() != null + ? visitStatements(ctx.statements()) + : AST.Statements.EMPTY + ); + } + + @Override + public AST.XCall visitCallExpr(CallExprContext ctx) { + return new XCall( + ctx.start.getLine(), + visitReference(ctx.reference()), + ctx.valueExpr().stream().map(v -> (AST.Expression)v.accept(this)).toList()); + } + + @Override + public AST visitBreakStatement(BreakStatementContext ctx) { + switch (ctx.start.getType()) { + case BREAK: + case CONTINUE: + case RETURN: + break; + default: + throw new UnsupportedOperationException(); + } + return super.visitBreakStatement(ctx); + } + + @Override + public AST.SReturn visitReturnStatement(ReturnStatementContext ctx) { + if (ctx.valueExpr() != null) { + return new AST.SReturn(ctx.start.getLine(), visitValueExpr(ctx.valueExpr())); + } else { + return new AST.SReturn(ctx.start.getLine()); + } + } + + /* ***************************************************************** */ + @Override + public AST.Expression visitValueGroupExpr(ValueGroupExprContext ctx) { + System.out.printf("visit group\n"); + return visitValueExpr(ctx.valueExpr()); + } + + XUnaryOp valueUnaryOp(Token op) { + switch (op.getType()) { + case ADD: + return XUnaryOp.NOP; + case SUB: + return XUnaryOp.NEG; + case NOT: + return XUnaryOp.NOT; + default: + throw new UnsupportedOperationException(op.getLine() + ": " + VOCABULARY.getDisplayName(op.getType())); + } + } + + @Override + public AST.XUnary visitValueUnaryExpr(ValueUnaryExprContext ctx) { + return new AST.XUnary( + ctx.start.getLine(), + valueUnaryOp(ctx.op), + (Expression)visit(ctx.rightValue)); + } + + XBinaryOp valueBinaryOp(Token op) { + switch (op.getType()) { + case ADD: + return XBinaryOp.ADD; + case SUB: + return XBinaryOp.SUB; + case MUL: + return XBinaryOp.MUL; + case DIV: + return XBinaryOp.DIV; + case MOD: + return XBinaryOp.MOD; + case AAND: + return XBinaryOp.AAND; + case OOR: + return XBinaryOp.OOR; + case XXOR: + return XBinaryOp.XXOR; + case LT: + return XBinaryOp.CLT; + case LE: + return XBinaryOp.CLE; + case GT: + return XBinaryOp.CGT; + case GE: + return XBinaryOp.CGE; + case EQ: + return XBinaryOp.CEQ; + case NE: + return XBinaryOp.CNE; + default: + throw new UnsupportedOperationException(op.getLine() + ": " + VOCABULARY.getDisplayName(op.getType())); + } + } + + @Override + public AST.XBinary visitValueBinaryExpr(ValueBinaryExprContext ctx) { + XBinary xb = new XBinary( + ctx.op.getLine(), + valueBinaryOp(ctx.op), + (Expression)visit(ctx.leftValue), + (Expression)visit(ctx.rightValue)); + System.out.printf("visit binary %s %s %s\n", xb.left, xb.op, xb.right); + return new XBinary( + ctx.op.getLine(), + valueBinaryOp(ctx.op), + (Expression)visit(ctx.leftValue), + (Expression)visit(ctx.rightValue)); + } + + Expression visitLiteral(Token lit) { + switch (lit.getType()) { + case INTEGER: { + try { + return new XInteger(lit.getLine(), Long.parseLong(lit.getText())); + } catch (NumberFormatException x) { + errors.add("Invalid INTEGER: " + lit.getText()); + return new XInteger(lit.getLine(), Long.MAX_VALUE); + } + } + case FLOAT: { + try { + return new XReal(lit.getLine(), Double.parseDouble(lit.getText())); + } catch (NumberFormatException x) { + errors.add("Invalid REAL: " + lit.getText()); + return new XReal(lit.getLine(), Double.NaN); + } + } + case STRING: + return new XString(lit.getLine(), lit.getText()); + case TRUE: + return new XBool(lit.getLine(), true); + case FALSE: + return new XBool(lit.getLine(), false); + default: + throw new UnsupportedOperationException(VOCABULARY.getDisplayName(lit.getType())); + } + } + + @Override + public AST visitLiteral(LiteralContext ctx) { + return visitLiteral(ctx.start); + } + + @Override + public AST.XReference visitReference(ReferenceContext ctx) { + return new XReference(ctx.start.getLine(), String.join(".", ctx.ID().stream().map(t -> t.getText()).toList())); + } +} diff --git a/src/notzed.scripta/classes/au/notzed/scripta/ASTPrinter.java b/src/notzed.scripta/classes/au/notzed/scripta/ASTPrinter.java new file mode 100644 index 0000000..e15e3a2 --- /dev/null +++ b/src/notzed.scripta/classes/au/notzed/scripta/ASTPrinter.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2023 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package au.notzed.scripta; + +import java.util.Iterator; + +public class ASTPrinter implements ASTVisitor { + StringBuilder d = new StringBuilder(); + + void down() { + d.append("\t"); + } + + void up() { + d.setLength(d.length() - 1); + } + + @Override + public void visit(AST.ScriptA a) { + ASTVisitor.super.visit(a); + } + + @Override + public void visit(AST.Statements s) { + s.statements.forEach(x -> x.accept(this)); + } + + @Override + public void visit(AST.SIf s) { + System.out.printf("%sif (", d); + s.test.accept(this); + System.out.println(")"); + down(); + s.then.accept(this); + up(); + s.rest.ifPresent(r -> { + System.out.printf("%selse", d); + down(); + r.accept(this); + up(); + }); + System.out.printf("%sfi\n", d); + } + + @Override + public void visit(AST.SWhile s) { + System.out.printf("%swhile (", d); + s.test.accept(this); + System.out.println(")"); + down(); + s.when.accept(this); + up(); + System.out.printf("%swend\n", d); + } + + @Override + public void visit(AST.SDeclare s) { + System.out.printf("var %s%s\n", d, s.ref.name); + } + + @Override + public void visit(AST.SAssign s) { + System.out.printf("%s%s = ", d, s.ref.name); + s.value.accept(this); + System.out.println(); + } + + @Override + public void visit(AST.SCall s) { + System.out.printf("%s", d); + s.call.accept(this); + System.out.println(); + } + + @Override + public void visit(AST.SBreak s) { + System.out.print(d); + System.out.print(s.op); + s.label.ifPresent(l -> System.out.print(" " + l)); + System.out.println(); + } + + @Override + public void visit(AST.SReturn s) { + System.out.print(d); + System.out.print("return"); + s.res.ifPresent(l -> { + System.out.print(" "); + l.accept(this); + }); + System.out.println(); + } + + /* *********************** */ + @Override + public void visit(AST.XUnary e) { + System.out.print(e.op); + System.out.print("( "); + e.right.accept(this); + System.out.print(" )"); + } + + @Override + public void visit(AST.XBinary e) { + System.out.print("( "); + e.left.accept(this); + System.out.print(" "); + System.out.print(e.op); + System.out.print(" "); + e.right.accept(this); + System.out.print(" )"); + } + + @Override + public void visit(AST.XCall e) { + e.ref.accept(this); + System.out.print("("); + Iterator it = e.params.iterator(); + if (it.hasNext()) + it.next().accept(this); + while (it.hasNext()) { + System.out.print(", "); + it.next().accept(this); + } + System.out.print(")"); + } + + @Override + public void visit(AST.XFunction e) { + System.out.print("function ("); + Iterator it = e.params.iterator(); + if (it.hasNext()) + System.out.print(it.next()); + while (it.hasNext()) { + System.out.print(", "); + System.out.print(it.next()); + } + System.out.print(") = {\n"); + down(); + visit(e.statements); + up(); + System.out.printf("%s}\n", d); + } + + @Override + public void visit(AST.XReference e) { + System.out.print(e.name); + } + + @Override + public void visit(AST.XBool e) { + System.out.printf("%s", e.value); + } + + @Override + public void visit(AST.XInteger e) { + System.out.printf("%dL", e.value); + } + + @Override + public void visit(AST.XReal e) { + System.out.printf("%fD", e.value); + } + + @Override + public void visit(AST.XString e) { + System.out.printf("`%s`", e.value); + } +} diff --git a/src/notzed.scripta/classes/au/notzed/scripta/ASTVisitor.java b/src/notzed.scripta/classes/au/notzed/scripta/ASTVisitor.java new file mode 100644 index 0000000..cd1548e --- /dev/null +++ b/src/notzed.scripta/classes/au/notzed/scripta/ASTVisitor.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2023 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package au.notzed.scripta; + +import au.notzed.scripta.AST.*; +import java.util.List; + +public interface ASTVisitor { + + public default void visit(ScriptA a) { + for (Statement s: a.statements) + s.accept(this); + //a.statements.forEach(s -> s.accept(this)); + } + + public default void visit(Statements s) { + s.visitChildren(this); + } + + // statements + public default void visit(Statement s) { + s.visitChildren(this); + } + + public default void visit(SIf s) { + s.visitChildren(this); + } + + public default void visit(SWhile s) { + s.visitChildren(this); + } + + public default void visit(SDeclare s) { + s.visitChildren(this); + } + + public default void visit(SAssign s) { + s.visitChildren(this); + } + + public default void visit(SBreak s) { + s.visitChildren(this); + } + + public default void visit(SCall s) { + s.visitChildren(this); + } + + public default void visit(SReturn s) { + s.visitChildren(this); + } + + // expressions + public default void visit(Expression e) { + e.visitChildren(this); + } + + public default void visit(XUnary e) { + e.visitChildren(this); + } + + public default void visit(XBinary e) { + e.visitChildren(this); + } + + public default void visit(XReference e) { + e.visitChildren(this); + } + + public default void visit(XCall e) { + e.visitChildren(this); + } + + public default void visit(XFunction e) { + e.visitChildren(this); + } + + public default void visit(XBool e) { + e.visitChildren(this); + } + + public default void visit(XInteger e) { + e.visitChildren(this); + } + + public default void visit(XReal e) { + e.visitChildren(this); + } + + public default void visit(XString e) { + e.visitChildren(this); + } + +} diff --git a/src/notzed.scripta/classes/au/notzed/scripta/Compiler.java b/src/notzed.scripta/classes/au/notzed/scripta/Compiler.java new file mode 100644 index 0000000..539a0c3 --- /dev/null +++ b/src/notzed.scripta/classes/au/notzed/scripta/Compiler.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2023 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package au.notzed.scripta; + +import static au.notzed.scripta.ScriptAParser.VOCABULARY; +import java.util.stream.Stream; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.tree.ParseTree; + +public class Compiler { + + static void dump(String s, ParseTree p) { + if (p.getPayload() instanceof ParserRuleContext t) { + System.out.printf("%s%s (%s)\n", s, t.start.getText(), t.getClass()); + } else if (p.getPayload() instanceof Token t) { + System.out.printf("%s%s\n", s, VOCABULARY.getDisplayName(t.getType())); + } else { + System.out.printf("%s%s\n", s, p.getPayload().getClass()); + } + for (int i = 0; i < p.getChildCount(); i++) { + dump(s + " ", p.getChild(i)); + } + } + + public static void main(String[] args) { + String src = """ + c = (2 + a) + a = 2 + b = 3 + c = (2 + a) + print(a + b, c, "hello", (3 + "foo")) + bob = function (a, b, c) { + return a + 2; + } + if (a == 2) { + return; + } + while (a < 1) { a = a + 0.1 } + """; + CharStream inputStream = CharStreams.fromString(src); + var lexer = new ScriptALexer(inputStream); + var tokenStream = new CommonTokenStream(lexer); + + int line[] = new int[1]; + Stream.of(src.split("\n")).map(l -> String.format("%5d: %s", ++line[0], l)).forEach(System.out::println); + + if (false) { + Token t; + while ((t = lexer.nextToken()).getType() != Token.EOF) { + System.out.println(t); + } + } + + var parser = new ScriptAParser(tokenStream); + var cst = parser.script(); + + dump(" ", cst); + + AST.ScriptA script = new ASTBuilder().visitScript(cst); + + System.out.printf("script(%d):\n", script.statements.size()); + script.statements.forEach(s -> System.out.printf(" %s\n", s)); + + new ASTPrinter().visit(script); + + if (false) { + System.out.println("visitor"); + new ASTVisitor() { + @Override + public void visit(AST.SCall s) { + System.out.printf(" call\n"); + ASTVisitor.super.visit(s); + } + + @Override + public void visit(AST.XBinary e) { + System.out.printf(" binary %s\n", e.op); + ASTVisitor.super.visit(e); + } + + @Override + public void visit(AST.XReference e) { + System.out.printf(" ref %s\n", e.name); + ASTVisitor.super.visit(e); + } + }.visit(script); + } + } + +} diff --git a/src/notzed.scripta/classes/au/notzed/scripta/Generator.java b/src/notzed.scripta/classes/au/notzed/scripta/Generator.java new file mode 100644 index 0000000..f3e1832 --- /dev/null +++ b/src/notzed.scripta/classes/au/notzed/scripta/Generator.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package au.notzed.scripta; + +public class Generator { + +} diff --git a/src/notzed.scripta/classes/module-info.java b/src/notzed.scripta/classes/module-info.java new file mode 100644 index 0000000..ee3fd02 --- /dev/null +++ b/src/notzed.scripta/classes/module-info.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +module notzed.scripta { + requires org.antlr.antlr4.runtime; + requires org.objectweb.asm; +} diff --git a/src/notzed.scripta/gen/ScriptA.g4 b/src/notzed.scripta/gen/ScriptA.g4 new file mode 100644 index 0000000..d991268 --- /dev/null +++ b/src/notzed.scripta/gen/ScriptA.g4 @@ -0,0 +1,96 @@ +// -*- Mode:text; tab-width:4; electric-indent-mode: nil; indent-line-function:insert-tab; -*- + +// A basic c-like language with optional ';' + +// if (test) { } [ else { } ] +// while (test) { } + +grammar ScriptA; + +script + : statements? EOF; + +statements + : statement (';'? statement)* ';'?; + +statement + : (label=ID ':')? IF '(' valueExpr ')' '{' then=statements? '}' ( ELSE '{' rest=statements? '}' )? # ifStatement +// | (label=ID ':')? SWITCH '(' valueExpr ')' '{' cases* '}' # switchStatement + | (label=ID ':')? WHILE '(' valueExpr ')' '{' when=statements? '}' # whileStatement + | scope? reference # declStatement + | scope? reference '=' valueExpr # assignStatement + | callExpr # callStatement + | CONTINUE (label=ID) ? # breakStatement + | BREAK (label=ID) ? # breakStatement + | RETURN valueExpr ? # returnStatement + ; + + +valueExpr + : '(' valueExpr ')' # valueGroupExpr + | op=('!'|'-'|'+') rightValue=valueExpr # valueUnaryExpr + | leftValue=valueExpr op=('*'|'/'|'%') rightValue=valueExpr # valueBinaryExpr + | leftValue=valueExpr op=('&'|'|'|'+'|'-') rightValue=valueExpr # valueBinaryExpr + | leftValue=valueExpr op=('&&'|'||'|'^^') rightValue=valueExpr # valueBinaryExpr + | leftValue=valueExpr op=(LT|LE|GT|GE|EQ|NE) rightValue=valueExpr # valueBinaryExpr + | lit=literal # valueLiteralExpr + | ref=reference # valueReferenceExpr + | call=callExpr # valueCallExpr + | func=funcExpr # valueFunctionExpr + ; + +callExpr : reference '(' (valueExpr (',' valueExpr)*)? ')'; +funcExpr : FUNC '(' (ID (',' ID) *) ? ')' '{' statements? '}'; + +IF : 'if'; +ELSE : 'else'; +SWITCH : 'switch'; +CASE : 'case'; +WHILE : 'while'; +CONTINUE : 'continue'; +BREAK : 'break'; +RETURN : 'return'; +FUNC : 'function'; +DEFAULT : 'default'; + +GLOBAL : 'global'; +LOCAL : 'local'; +PLAYER : 'player'; +CONST : 'const'; + +literal : INTEGER | FLOAT | STRING | TRUE | FALSE; +scope : GLOBAL | LOCAL | PLAYER | CONST; +reference : ID ('.' ID)*; + +TRUE : 'true'; +FALSE : 'false'; + +LT : '<'; +LE : '<='; +GT : '>'; +GE : '>='; +EQ : '=='; +NE : '!='; + +CMP : ( LT | LE | GT | GE | EQ | NE ); + +ADD : '+'; +SUB : '-'; +MUL : '*'; +DIV : '/'; +MOD : '%'; +NOT : '!'; + +AAND : '&&'; +OOR : '||'; +XXOR : '^^'; + +INTEGER : [0-9]+; +FLOAT : [0-9]+ '.' ([0-9]+)? ([eE] [+-]? [0-9]+)?; +STRING : '"' (~[\\"] | '\\' [\\"])* '"' + | '\'' (~[\\'] | '\\' [\\'])* '\''; +ID : [a-zA-Z_][0-9a-zA-Z_]*; + +NL : ( '\n' | '\r\n' | '\r' ) -> channel(HIDDEN); +COMMENT : '#' ~[\r\n]* -> channel(HIDDEN); +WS : [ \t] -> channel(HIDDEN); diff --git a/src/notzed.scripta/gen/gen.make b/src/notzed.scripta/gen/gen.make new file mode 100644 index 0000000..65969b7 --- /dev/null +++ b/src/notzed.scripta/gen/gen.make @@ -0,0 +1,5 @@ + +notzed.scripta_ANTLR4 = ScriptA +notzed.scripta-ScriptA_ANTLR4PACKAGE = au.notzed.scripta +notzed.scripta-ScriptA_ANTLR4FLAGS = -visitor -no-listener +