diff options
| author | michael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2010-02-04 15:18:07 +0000 |
|---|---|---|
| committer | michael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2010-02-04 15:18:07 +0000 |
| commit | e61c9c527aaa7f96e7235536853352e3ae32a278 (patch) | |
| tree | 79f0f01cf692f65b13bc0ca16aa0df37c89ae7c3 /packages/fcl-js | |
| parent | bc50a91efee1513bcf226eef21aef06eb87d6ff8 (diff) | |
| download | fpc-e61c9c527aaa7f96e7235536853352e3ae32a278.tar.gz | |
* Initial check-in
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@14859 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/fcl-js')
| -rw-r--r-- | packages/fcl-js/Makefile | 2354 | ||||
| -rw-r--r-- | packages/fcl-js/Makefile.fpc | 26 | ||||
| -rw-r--r-- | packages/fcl-js/README.TXT | 23 | ||||
| -rw-r--r-- | packages/fcl-js/fpmake.pp | 37 | ||||
| -rw-r--r-- | packages/fcl-js/src/jsbase.pp | 175 | ||||
| -rw-r--r-- | packages/fcl-js/src/jsparser.pp | 2100 | ||||
| -rw-r--r-- | packages/fcl-js/src/jsscanner.pp | 909 | ||||
| -rw-r--r-- | packages/fcl-js/src/jstree.pp | 963 | ||||
| -rw-r--r-- | packages/fcl-js/tests/tcparser.pp | 2311 | ||||
| -rw-r--r-- | packages/fcl-js/tests/tcscanner.pp | 983 | ||||
| -rw-r--r-- | packages/fcl-js/tests/testjs.ico | bin | 0 -> 137040 bytes | |||
| -rw-r--r-- | packages/fcl-js/tests/testjs.lpi | 261 | ||||
| -rw-r--r-- | packages/fcl-js/tests/testjs.lpr | 29 | ||||
| -rw-r--r-- | packages/fcl-js/tests/testjs.manifest | 17 | ||||
| -rw-r--r-- | packages/fcl-js/tests/testjs.rc | 1 |
15 files changed, 10189 insertions, 0 deletions
diff --git a/packages/fcl-js/Makefile b/packages/fcl-js/Makefile new file mode 100644 index 0000000000..86ad35946c --- /dev/null +++ b/packages/fcl-js/Makefile @@ -0,0 +1,2354 @@ +# +# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/11/06] +# +default: all +MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded +BSDs = freebsd netbsd openbsd darwin +UNIXs = linux $(BSDs) solaris qnx +LIMIT83fs = go32v2 os2 emx watcom +OSNeedsComspecToRunBatch = go32v2 watcom +FORCE: +.PHONY: FORCE +override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH))) +ifneq ($(findstring darwin,$(OSTYPE)),) +inUnix=1 #darwin +SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH))) +else +ifeq ($(findstring ;,$(PATH)),) +inUnix=1 +SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH))) +else +SEARCHPATH:=$(subst ;, ,$(PATH)) +endif +endif +SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE)))) +PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH)))) +ifeq ($(PWD),) +PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH)))) +ifeq ($(PWD),) +$(error You need the GNU utils package to use this Makefile) +else +PWD:=$(firstword $(PWD)) +SRCEXEEXT= +endif +else +PWD:=$(firstword $(PWD)) +SRCEXEEXT=.exe +endif +ifndef inUnix +ifeq ($(OS),Windows_NT) +inWinNT=1 +else +ifdef OS2_SHELL +inOS2=1 +endif +endif +else +ifneq ($(findstring cygdrive,$(PATH)),) +inCygWin=1 +endif +endif +ifdef inUnix +SRCBATCHEXT=.sh +else +ifdef inOS2 +SRCBATCHEXT=.cmd +else +SRCBATCHEXT=.bat +endif +endif +ifdef COMSPEC +ifneq ($(findstring $(OS_SOURCE),$(OSNeedsComspecToRunBatch)),) +ifndef RUNBATCH +RUNBATCH=$(COMSPEC) /C +endif +endif +endif +ifdef inUnix +PATHSEP=/ +else +PATHSEP:=$(subst /,\,/) +ifdef inCygWin +PATHSEP=/ +endif +endif +ifdef PWD +BASEDIR:=$(subst \,/,$(shell $(PWD))) +ifdef inCygWin +ifneq ($(findstring /cygdrive/,$(BASEDIR)),) +BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR)) +BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR))) +BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR)) +endif +endif +else +BASEDIR=. +endif +ifdef inOS2 +ifndef ECHO +ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ECHO),) +ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ECHO),) +ECHO=echo +else +ECHO:=$(firstword $(ECHO)) +endif +else +ECHO:=$(firstword $(ECHO)) +endif +endif +export ECHO +endif +override DEFAULT_FPCDIR=../.. +ifndef FPC +ifdef PP +FPC=$(PP) +endif +endif +ifndef FPC +FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH)))) +ifneq ($(FPCPROG),) +FPCPROG:=$(firstword $(FPCPROG)) +ifneq ($(CPU_TARGET),) +FPC:=$(shell $(FPCPROG) -P$(CPU_TARGET) -PB) +else +FPC:=$(shell $(FPCPROG) -PB) +endif +ifneq ($(findstring Error,$(FPC)),) +override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH))))) +else +ifeq ($(strip $(wildcard $(FPC))),) +FPC:=$(firstword $(FPCPROG)) +endif +endif +else +override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH))))) +endif +endif +override FPC:=$(subst $(SRCEXEEXT),,$(FPC)) +override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT) +FOUNDFPC:=$(strip $(wildcard $(FPC))) +ifeq ($(FOUNDFPC),) +FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH)))) +ifeq ($(FOUNDFPC),) +$(error Compiler $(FPC) not found) +endif +endif +ifndef FPC_COMPILERINFO +FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO) +endif +ifndef FPC_VERSION +FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO)) +endif +export FPC FPC_VERSION FPC_COMPILERINFO +unexport CHECKDEPEND ALLDEPENDENCIES +ifndef CPU_TARGET +ifdef CPU_TARGET_DEFAULT +CPU_TARGET=$(CPU_TARGET_DEFAULT) +endif +endif +ifndef OS_TARGET +ifdef OS_TARGET_DEFAULT +OS_TARGET=$(OS_TARGET_DEFAULT) +endif +endif +ifneq ($(words $(FPC_COMPILERINFO)),5) +FPC_COMPILERINFO+=$(shell $(FPC) -iSP) +FPC_COMPILERINFO+=$(shell $(FPC) -iTP) +FPC_COMPILERINFO+=$(shell $(FPC) -iSO) +FPC_COMPILERINFO+=$(shell $(FPC) -iTO) +endif +ifndef CPU_SOURCE +CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO)) +endif +ifndef CPU_TARGET +CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO)) +endif +ifndef OS_SOURCE +OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO)) +endif +ifndef OS_TARGET +OS_TARGET:=$(word 5,$(FPC_COMPILERINFO)) +endif +FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET) +FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE) +ifeq ($(CPU_TARGET),armeb) +ARCH=arm +override FPCOPT+=-Cb +else +ifeq ($(CPU_TARGET),armel) +ARCH=arm +override FPCOPT+=-CaEABI +else +ARCH=$(CPU_TARGET) +endif +endif +ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),) +TARGETSUFFIX=$(OS_TARGET) +SOURCESUFFIX=$(OS_SOURCE) +else +TARGETSUFFIX=$(FULL_TARGET) +SOURCESUFFIX=$(FULL_SOURCE) +endif +ifneq ($(FULL_TARGET),$(FULL_SOURCE)) +CROSSCOMPILE=1 +endif +ifeq ($(findstring makefile,$(MAKECMDGOALS)),) +ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),) +$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first) +endif +endif +ifneq ($(findstring $(OS_TARGET),$(BSDs)),) +BSDhier=1 +endif +ifeq ($(OS_TARGET),linux) +linuxHier=1 +endif +export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE +ifdef FPCDIR +override FPCDIR:=$(subst \,/,$(FPCDIR)) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=wrong +endif +else +override FPCDIR=wrong +endif +ifdef DEFAULT_FPCDIR +ifeq ($(FPCDIR),wrong) +override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR)) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=wrong +endif +endif +endif +ifeq ($(FPCDIR),wrong) +ifdef inUnix +override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION) +ifeq ($(wildcard $(FPCDIR)/units),) +override FPCDIR=/usr/lib/fpc/$(FPC_VERSION) +endif +else +override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH)))))) +override FPCDIR:=$(FPCDIR)/.. +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR:=$(FPCDIR)/.. +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR:=$(BASEDIR) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=c:/pp +endif +endif +endif +endif +endif +ifndef CROSSBINDIR +CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX)) +endif +ifeq ($(OS_TARGET),darwin) +ifeq ($(OS_SOURCE),darwin) +DARWIN2DARWIN=1 +endif +endif +ifndef BINUTILSPREFIX +ifndef CROSSBINDIR +ifdef CROSSCOMPILE +ifndef DARWIN2DARWIN +BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)- +endif +endif +endif +endif +UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX)) +ifeq ($(UNITSDIR),) +UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET)) +endif +PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra) +override PACKAGE_NAME=fcl-js +override PACKAGE_VERSION=2.5.1 +ifeq ($(FULL_TARGET),i386-linux) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-go32v2) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-win32) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-os2) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-freebsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-beos) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-haiku) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-netbsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-solaris) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-qnx) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-netware) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-openbsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-wdosx) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-darwin) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-emx) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-watcom) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-wince) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),i386-symbian) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),m68k-linux) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),m68k-amiga) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),m68k-atari) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),m68k-palmos) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),m68k-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc-linux) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc-macos) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),sparc-linux) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),sparc-solaris) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),sparc-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),x86_64-linux) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),x86_64-win64) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),arm-linux) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),arm-palmos) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),arm-darwin) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),arm-wince) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),arm-gba) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),arm-nds) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),arm-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),arm-symbian) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),avr-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),armeb-linux) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +ifeq ($(FULL_TARGET),armeb-embedded) +override TARGET_UNITS+=jsbase jstree jsscanner jsparser +endif +override INSTALL_FPCPACKAGE=y +ifeq ($(FULL_TARGET),i386-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-go32v2) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-win32) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-os2) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-freebsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-beos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-haiku) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-solaris) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-qnx) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netware) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-openbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-wdosx) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-emx) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-watcom) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-wince) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-symbian) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-amiga) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-atari) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-palmos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-macos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-solaris) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-win64) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-palmos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-wince) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-gba) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-nds) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-symbian) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),avr-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),armeb-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),armeb-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-linux) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-go32v2) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-win32) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-os2) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-freebsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-beos) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-haiku) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netbsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-solaris) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-qnx) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netware) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-openbsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-wdosx) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-darwin) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-emx) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-watcom) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-wince) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-embedded) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-symbian) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-linux) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-amiga) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-atari) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-palmos) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-embedded) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-linux) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-macos) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-linux) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-solaris) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-embedded) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-linux) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-win64) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-linux) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-palmos) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-darwin) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-wince) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-gba) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-nds) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-embedded) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-symbian) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),avr-embedded) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),armeb-linux) +override COMPILER_SOURCEDIR+=src +endif +ifeq ($(FULL_TARGET),armeb-embedded) +override COMPILER_SOURCEDIR+=src +endif +override SHARED_BUILD=n +override SHARED_BUILD=n +ifdef REQUIRE_UNITSDIR +override UNITSDIR+=$(REQUIRE_UNITSDIR) +endif +ifdef REQUIRE_PACKAGESDIR +override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR) +endif +ifdef ZIPINSTALL +ifneq ($(findstring $(OS_TARGET),$(UNIXs)),) +UNIXHier=1 +endif +else +ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),) +UNIXHier=1 +endif +endif +ifndef INSTALL_PREFIX +ifdef PREFIX +INSTALL_PREFIX=$(PREFIX) +endif +endif +ifndef INSTALL_PREFIX +ifdef UNIXHier +INSTALL_PREFIX=/usr/local +else +ifdef INSTALL_FPCPACKAGE +INSTALL_BASEDIR:=/pp +else +INSTALL_BASEDIR:=/$(PACKAGE_NAME) +endif +endif +endif +export INSTALL_PREFIX +ifdef INSTALL_FPCSUBDIR +export INSTALL_FPCSUBDIR +endif +ifndef DIST_DESTDIR +DIST_DESTDIR:=$(BASEDIR) +endif +export DIST_DESTDIR +ifndef COMPILER_UNITTARGETDIR +ifdef PACKAGEDIR_MAIN +COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX) +else +COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX) +endif +endif +ifndef COMPILER_TARGETDIR +COMPILER_TARGETDIR=. +endif +ifndef INSTALL_BASEDIR +ifdef UNIXHier +ifdef INSTALL_FPCPACKAGE +INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION) +else +INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME) +endif +else +INSTALL_BASEDIR:=$(INSTALL_PREFIX) +endif +endif +ifndef INSTALL_BINDIR +ifdef UNIXHier +INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin +else +INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin +ifdef INSTALL_FPCPACKAGE +ifdef CROSSCOMPILE +ifdef CROSSINSTALL +INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX) +else +INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX) +endif +else +INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX) +endif +endif +endif +endif +ifndef INSTALL_UNITDIR +INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX) +ifdef INSTALL_FPCPACKAGE +ifdef PACKAGE_NAME +INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME) +endif +endif +endif +ifndef INSTALL_LIBDIR +ifdef UNIXHier +INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib +else +INSTALL_LIBDIR:=$(INSTALL_UNITDIR) +endif +endif +ifndef INSTALL_SOURCEDIR +ifdef UNIXHier +ifdef BSDhier +SRCPREFIXDIR=share/src +else +ifdef linuxHier +SRCPREFIXDIR=share/src +else +SRCPREFIXDIR=src +endif +endif +ifdef INSTALL_FPCPACKAGE +ifdef INSTALL_FPCSUBDIR +INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME) +else +INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME) +endif +else +INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION) +endif +else +ifdef INSTALL_FPCPACKAGE +ifdef INSTALL_FPCSUBDIR +INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME) +else +INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME) +endif +else +INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source +endif +endif +endif +ifndef INSTALL_DOCDIR +ifdef UNIXHier +ifdef BSDhier +DOCPREFIXDIR=share/doc +else +ifdef linuxHier +DOCPREFIXDIR=share/doc +else +DOCPREFIXDIR=doc +endif +endif +ifdef INSTALL_FPCPACKAGE +INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME) +else +INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION) +endif +else +ifdef INSTALL_FPCPACKAGE +INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME) +else +INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc +endif +endif +endif +ifndef INSTALL_EXAMPLEDIR +ifdef UNIXHier +ifdef INSTALL_FPCPACKAGE +ifdef BSDhier +INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME) +else +ifdef linuxHier +INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples +else +INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME) +endif +endif +else +ifdef BSDhier +INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION) +else +ifdef linuxHier +INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION) +else +INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION) +endif +endif +endif +else +ifdef INSTALL_FPCPACKAGE +INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME) +else +INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples +endif +endif +endif +ifndef INSTALL_DATADIR +INSTALL_DATADIR=$(INSTALL_BASEDIR) +endif +ifndef INSTALL_SHAREDDIR +INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib +endif +ifdef CROSSCOMPILE +ifndef CROSSBINDIR +CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX)) +ifeq ($(CROSSBINDIR),) +CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE)) +endif +endif +else +CROSSBINDIR= +endif +BATCHEXT=.bat +LOADEREXT=.as +EXEEXT=.exe +PPLEXT=.ppl +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.so +SHAREDLIBPREFIX=libfp +STATICLIBPREFIX=libp +IMPORTLIBPREFIX=libimp +RSTEXT=.rst +ifeq ($(findstring 1.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),go32v1) +STATICLIBPREFIX= +SHORTSUFFIX=v1 +endif +ifeq ($(OS_TARGET),go32v2) +STATICLIBPREFIX= +SHORTSUFFIX=dos +IMPORTLIBPREFIX= +endif +ifeq ($(OS_TARGET),watcom) +STATICLIBPREFIX= +OEXT=.obj +ASMEXT=.asm +SHAREDLIBEXT=.dll +SHORTSUFFIX=wat +IMPORTLIBPREFIX= +endif +ifeq ($(OS_TARGET),linux) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=lnx +endif +ifeq ($(OS_TARGET),freebsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=fbs +endif +ifeq ($(OS_TARGET),netbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=nbs +endif +ifeq ($(OS_TARGET),openbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=obs +endif +ifeq ($(OS_TARGET),win32) +SHAREDLIBEXT=.dll +SHORTSUFFIX=w32 +endif +ifeq ($(OS_TARGET),os2) +BATCHEXT=.cmd +AOUTEXT=.out +STATICLIBPREFIX= +SHAREDLIBEXT=.dll +SHORTSUFFIX=os2 +ECHO=echo +IMPORTLIBPREFIX= +endif +ifeq ($(OS_TARGET),emx) +BATCHEXT=.cmd +AOUTEXT=.out +STATICLIBPREFIX= +SHAREDLIBEXT=.dll +SHORTSUFFIX=emx +ECHO=echo +IMPORTLIBPREFIX= +endif +ifeq ($(OS_TARGET),amiga) +EXEEXT= +SHAREDLIBEXT=.library +SHORTSUFFIX=amg +endif +ifeq ($(OS_TARGET),morphos) +EXEEXT= +SHAREDLIBEXT=.library +SHORTSUFFIX=mos +endif +ifeq ($(OS_TARGET),atari) +EXEEXT=.ttp +SHORTSUFFIX=ata +endif +ifeq ($(OS_TARGET),beos) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=be +endif +ifeq ($(OS_TARGET),haiku) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=hai +endif +ifeq ($(OS_TARGET),solaris) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=sun +endif +ifeq ($(OS_TARGET),qnx) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=qnx +endif +ifeq ($(OS_TARGET),netware) +EXEEXT=.nlm +STATICLIBPREFIX= +SHORTSUFFIX=nw +IMPORTLIBPREFIX=imp +endif +ifeq ($(OS_TARGET),netwlibc) +EXEEXT=.nlm +STATICLIBPREFIX= +SHORTSUFFIX=nwl +IMPORTLIBPREFIX=imp +endif +ifeq ($(OS_TARGET),macos) +BATCHEXT= +EXEEXT= +DEBUGSYMEXT=.xcoff +SHORTSUFFIX=mac +IMPORTLIBPREFIX=imp +endif +ifeq ($(OS_TARGET),darwin) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=dwn +endif +ifeq ($(OS_TARGET),gba) +EXEEXT=.gba +SHAREDLIBEXT=.so +SHORTSUFFIX=gba +endif +ifeq ($(OS_TARGET),symbian) +SHAREDLIBEXT=.dll +SHORTSUFFIX=symbian +endif +else +ifeq ($(OS_TARGET),go32v1) +PPUEXT=.pp1 +OEXT=.o1 +ASMEXT=.s1 +SMARTEXT=.sl1 +STATICLIBEXT=.a1 +SHAREDLIBEXT=.so1 +STATICLIBPREFIX= +SHORTSUFFIX=v1 +IMPORTLIBPREFIX= +endif +ifeq ($(OS_TARGET),go32v2) +STATICLIBPREFIX= +SHORTSUFFIX=dos +IMPORTLIBPREFIX= +endif +ifeq ($(OS_TARGET),watcom) +STATICLIBPREFIX= +SHORTSUFFIX=wat +IMPORTLIBPREFIX= +endif +ifeq ($(OS_TARGET),linux) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=lnx +endif +ifeq ($(OS_TARGET),freebsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=fbs +endif +ifeq ($(OS_TARGET),netbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=nbs +endif +ifeq ($(OS_TARGET),openbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=obs +endif +ifeq ($(OS_TARGET),win32) +PPUEXT=.ppw +OEXT=.ow +ASMEXT=.sw +SMARTEXT=.slw +STATICLIBEXT=.aw +SHAREDLIBEXT=.dll +SHORTSUFFIX=w32 +endif +ifeq ($(OS_TARGET),os2) +BATCHEXT=.cmd +PPUEXT=.ppo +ASMEXT=.so2 +OEXT=.oo2 +AOUTEXT=.out +SMARTEXT=.sl2 +STATICLIBPREFIX= +STATICLIBEXT=.ao2 +SHAREDLIBEXT=.dll +SHORTSUFFIX=os2 +ECHO=echo +IMPORTLIBPREFIX= +endif +ifeq ($(OS_TARGET),amiga) +EXEEXT= +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.library +SHORTSUFFIX=amg +endif +ifeq ($(OS_TARGET),atari) +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT=.ttp +SHORTSUFFIX=ata +endif +ifeq ($(OS_TARGET),beos) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=be +endif +ifeq ($(OS_TARGET),solaris) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=sun +endif +ifeq ($(OS_TARGET),qnx) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=qnx +endif +ifeq ($(OS_TARGET),netware) +STATICLIBPREFIX= +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.nlm +EXEEXT=.nlm +SHORTSUFFIX=nw +IMPORTLIBPREFIX=imp +endif +ifeq ($(OS_TARGET),netwlibc) +STATICLIBPREFIX= +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.nlm +EXEEXT=.nlm +SHORTSUFFIX=nwl +IMPORTLIBPREFIX=imp +endif +ifeq ($(OS_TARGET),macos) +BATCHEXT= +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +DEBUGSYMEXT=.xcoff +SHORTSUFFIX=mac +IMPORTLIBPREFIX=imp +endif +endif +ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),) +FPCMADE=fpcmade.$(SHORTSUFFIX) +ZIPSUFFIX=$(SHORTSUFFIX) +ZIPCROSSPREFIX= +ZIPSOURCESUFFIX=src +ZIPEXAMPLESUFFIX=exm +else +FPCMADE=fpcmade.$(TARGETSUFFIX) +ZIPSOURCESUFFIX=.source +ZIPEXAMPLESUFFIX=.examples +ifdef CROSSCOMPILE +ZIPSUFFIX=.$(SOURCESUFFIX) +ZIPCROSSPREFIX=$(TARGETSUFFIX)- +else +ZIPSUFFIX=.$(TARGETSUFFIX) +ZIPCROSSPREFIX= +endif +endif +ifndef ECHO +ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ECHO),) +ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ECHO),) +ECHO= __missing_command_ECHO +else +ECHO:=$(firstword $(ECHO)) +endif +else +ECHO:=$(firstword $(ECHO)) +endif +endif +export ECHO +ifndef DATE +DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(DATE),) +DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(DATE),) +DATE= __missing_command_DATE +else +DATE:=$(firstword $(DATE)) +endif +else +DATE:=$(firstword $(DATE)) +endif +endif +export DATE +ifndef GINSTALL +GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(GINSTALL),) +GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(GINSTALL),) +GINSTALL= __missing_command_GINSTALL +else +GINSTALL:=$(firstword $(GINSTALL)) +endif +else +GINSTALL:=$(firstword $(GINSTALL)) +endif +endif +export GINSTALL +ifndef CPPROG +CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(CPPROG),) +CPPROG= __missing_command_CPPROG +else +CPPROG:=$(firstword $(CPPROG)) +endif +endif +export CPPROG +ifndef RMPROG +RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(RMPROG),) +RMPROG= __missing_command_RMPROG +else +RMPROG:=$(firstword $(RMPROG)) +endif +endif +export RMPROG +ifndef MVPROG +MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MVPROG),) +MVPROG= __missing_command_MVPROG +else +MVPROG:=$(firstword $(MVPROG)) +endif +endif +export MVPROG +ifndef MKDIRPROG +MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MKDIRPROG),) +MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MKDIRPROG),) +MKDIRPROG= __missing_command_MKDIRPROG +else +MKDIRPROG:=$(firstword $(MKDIRPROG)) +endif +else +MKDIRPROG:=$(firstword $(MKDIRPROG)) +endif +endif +export MKDIRPROG +ifndef ECHOREDIR +ifndef inUnix +ECHOREDIR=echo +else +ECHOREDIR=$(ECHO) +endif +endif +ifndef COPY +COPY:=$(CPPROG) -fp +endif +ifndef COPYTREE +COPYTREE:=$(CPPROG) -Rfp +endif +ifndef MKDIRTREE +MKDIRTREE:=$(MKDIRPROG) -p +endif +ifndef MOVE +MOVE:=$(MVPROG) -f +endif +ifndef DEL +DEL:=$(RMPROG) -f +endif +ifndef DELTREE +DELTREE:=$(RMPROG) -rf +endif +ifndef INSTALL +ifdef inUnix +INSTALL:=$(GINSTALL) -c -m 644 +else +INSTALL:=$(COPY) +endif +endif +ifndef INSTALLEXE +ifdef inUnix +INSTALLEXE:=$(GINSTALL) -c -m 755 +else +INSTALLEXE:=$(COPY) +endif +endif +ifndef MKDIR +MKDIR:=$(GINSTALL) -m 755 -d +endif +export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR +ifndef PPUMOVE +PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(PPUMOVE),) +PPUMOVE= __missing_command_PPUMOVE +else +PPUMOVE:=$(firstword $(PPUMOVE)) +endif +endif +export PPUMOVE +ifndef FPCMAKE +FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(FPCMAKE),) +FPCMAKE= __missing_command_FPCMAKE +else +FPCMAKE:=$(firstword $(FPCMAKE)) +endif +endif +export FPCMAKE +ifndef ZIPPROG +ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ZIPPROG),) +ZIPPROG= __missing_command_ZIPPROG +else +ZIPPROG:=$(firstword $(ZIPPROG)) +endif +endif +export ZIPPROG +ifndef TARPROG +TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(TARPROG),) +TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(TARPROG),) +TARPROG= __missing_command_TARPROG +else +TARPROG:=$(firstword $(TARPROG)) +endif +else +TARPROG:=$(firstword $(TARPROG)) +endif +endif +export TARPROG +ASNAME=$(BINUTILSPREFIX)as +LDNAME=$(BINUTILSPREFIX)ld +ARNAME=$(BINUTILSPREFIX)ar +RCNAME=$(BINUTILSPREFIX)rc +ifneq ($(findstring 1.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),win32) +ifeq ($(CROSSBINDIR),) +ASNAME=asw +LDNAME=ldw +ARNAME=arw +endif +endif +endif +ifndef ASPROG +ifdef CROSSBINDIR +ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT) +else +ASPROG=$(ASNAME) +endif +endif +ifndef LDPROG +ifdef CROSSBINDIR +LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT) +else +LDPROG=$(LDNAME) +endif +endif +ifndef RCPROG +ifdef CROSSBINDIR +RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT) +else +RCPROG=$(RCNAME) +endif +endif +ifndef ARPROG +ifdef CROSSBINDIR +ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT) +else +ARPROG=$(ARNAME) +endif +endif +AS=$(ASPROG) +LD=$(LDPROG) +RC=$(RCPROG) +AR=$(ARPROG) +PPAS=ppas$(SRCBATCHEXT) +ifdef inUnix +LDCONFIG=ldconfig +else +LDCONFIG= +endif +ifdef DATE +DATESTR:=$(shell $(DATE) +%Y%m%d) +else +DATESTR= +endif +ifndef UPXPROG +ifeq ($(OS_TARGET),go32v2) +UPXPROG:=1 +endif +ifeq ($(OS_TARGET),win32) +UPXPROG:=1 +endif +ifdef UPXPROG +UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(UPXPROG),) +UPXPROG= +else +UPXPROG:=$(firstword $(UPXPROG)) +endif +else +UPXPROG= +endif +endif +export UPXPROG +ZIPOPT=-9 +ZIPEXT=.zip +ifeq ($(USETAR),bz2) +TAROPT=vj +TAREXT=.tar.bz2 +else +TAROPT=vz +TAREXT=.tar.gz +endif +override REQUIRE_PACKAGES=rtl +ifeq ($(FULL_TARGET),i386-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-go32v2) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-win32) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-os2) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-freebsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-beos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-haiku) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-netbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-solaris) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-qnx) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-netware) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-openbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-wdosx) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-emx) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-watcom) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-wince) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-symbian) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-amiga) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-atari) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-palmos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-macos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),sparc-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),sparc-solaris) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),sparc-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-win64) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-palmos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-wince) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-gba) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-nds) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-symbian) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),avr-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),armeb-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),armeb-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifdef REQUIRE_PACKAGES_RTL +PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR)))))) +ifneq ($(PACKAGEDIR_RTL),) +ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),) +UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX) +else +UNITDIR_RTL=$(PACKAGEDIR_RTL) +endif +ifdef CHECKDEPEND +$(PACKAGEDIR_RTL)/$(FPCMADE): + $(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE) +override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE) +endif +else +PACKAGEDIR_RTL= +UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR))))) +ifneq ($(UNITDIR_RTL),) +UNITDIR_RTL:=$(firstword $(UNITDIR_RTL)) +else +UNITDIR_RTL= +endif +endif +ifdef UNITDIR_RTL +override COMPILER_UNITDIR+=$(UNITDIR_RTL) +endif +endif +ifndef NOCPUDEF +override FPCOPTDEF=$(ARCH) +endif +ifneq ($(OS_TARGET),$(OS_SOURCE)) +override FPCOPT+=-T$(OS_TARGET) +endif +ifneq ($(CPU_TARGET),$(CPU_SOURCE)) +override FPCOPT+=-P$(ARCH) +endif +ifeq ($(OS_SOURCE),openbsd) +override FPCOPT+=-FD$(NEW_BINUTILS_PATH) +endif +ifndef CROSSBOOTSTRAP +ifneq ($(BINUTILSPREFIX),) +override FPCOPT+=-XP$(BINUTILSPREFIX) +endif +ifneq ($(BINUTILSPREFIX),) +override FPCOPT+=-Xr$(RLINKPATH) +endif +endif +ifdef UNITDIR +override FPCOPT+=$(addprefix -Fu,$(UNITDIR)) +endif +ifdef LIBDIR +override FPCOPT+=$(addprefix -Fl,$(LIBDIR)) +endif +ifdef OBJDIR +override FPCOPT+=$(addprefix -Fo,$(OBJDIR)) +endif +ifdef INCDIR +override FPCOPT+=$(addprefix -Fi,$(INCDIR)) +endif +ifdef LINKSMART +override FPCOPT+=-XX +endif +ifdef CREATESMART +override FPCOPT+=-CX +endif +ifdef DEBUG +override FPCOPT+=-gl +override FPCOPTDEF+=DEBUG +endif +ifdef RELEASE +ifneq ($(findstring 2.0.,$(FPC_VERSION)),) +ifeq ($(CPU_TARGET),i386) +FPCCPUOPT:=-OG2p3 +endif +ifeq ($(CPU_TARGET),powerpc) +FPCCPUOPT:=-O1r +endif +else +FPCCPUOPT:=-O2 +endif +override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n +override FPCOPTDEF+=RELEASE +endif +ifdef STRIP +override FPCOPT+=-Xs +endif +ifdef OPTIMIZE +override FPCOPT+=-O2 +endif +ifdef VERBOSE +override FPCOPT+=-vwni +endif +ifdef COMPILER_OPTIONS +override FPCOPT+=$(COMPILER_OPTIONS) +endif +ifdef COMPILER_UNITDIR +override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR)) +endif +ifdef COMPILER_LIBRARYDIR +override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR)) +endif +ifdef COMPILER_OBJECTDIR +override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR)) +endif +ifdef COMPILER_INCLUDEDIR +override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR)) +endif +ifdef CROSSBINDIR +override FPCOPT+=-FD$(CROSSBINDIR) +endif +ifdef COMPILER_TARGETDIR +override FPCOPT+=-FE$(COMPILER_TARGETDIR) +ifeq ($(COMPILER_TARGETDIR),.) +override TARGETDIRPREFIX= +else +override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/ +endif +endif +ifdef COMPILER_UNITTARGETDIR +override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR) +ifeq ($(COMPILER_UNITTARGETDIR),.) +override UNITTARGETDIRPREFIX= +else +override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/ +endif +else +ifdef COMPILER_TARGETDIR +override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR) +override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX) +endif +endif +ifdef CREATESHARED +override FPCOPT+=-Cg +ifeq ($(CPU_TARGET),i386) +override FPCOPT+=-Aas +endif +endif +ifeq ($(findstring 2.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),linux) +ifeq ($(CPU_TARGET),x86_64) +override FPCOPT+=-Cg +endif +endif +endif +ifdef LINKSHARED +endif +ifdef OPT +override FPCOPT+=$(OPT) +endif +ifdef FPCOPTDEF +override FPCOPT+=$(addprefix -d,$(FPCOPTDEF)) +endif +ifdef CFGFILE +override FPCOPT+=@$(CFGFILE) +endif +ifdef USEENV +override FPCEXTCMD:=$(FPCOPT) +override FPCOPT:=!FPCEXTCMD +export FPCEXTCMD +endif +override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET) +override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE) +ifneq ($(AFULL_TARGET),$(AFULL_SOURCE)) +override ACROSSCOMPILE=1 +endif +ifdef ACROSSCOMPILE +override FPCOPT+=$(CROSSOPT) +endif +override COMPILER:=$(FPC) $(FPCOPT) +ifeq (,$(findstring -s ,$(COMPILER))) +EXECPPAS= +else +ifeq ($(FULL_SOURCE),$(FULL_TARGET)) +ifdef RUNBATCH +EXECPPAS:=@$(RUNBATCH) $(PPAS) +else +EXECPPAS:=@$(PPAS) +endif +endif +endif +.PHONY: fpc_units +ifneq ($(TARGET_UNITS)$(TARGET_IMPLICITUNITS),) +override ALLTARGET+=fpc_units +override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS)) +override IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICITUNITS)) +override INSTALLPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES) +override CLEANPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES) +endif +fpc_units: $(COMPILER_UNITTARGETDIR) $(UNITPPUFILES) +ifdef TARGET_RSTS +override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS)) +override CLEANRSTFILES+=$(RSTFILES) +endif +.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared +$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET) + @$(ECHOREDIR) Compiled > $(FPCMADE) +fpc_all: $(FPCMADE) +fpc_smart: + $(MAKE) all LINKSMART=1 CREATESMART=1 +fpc_debug: + $(MAKE) all DEBUG=1 +fpc_release: + $(MAKE) all RELEASE=1 +.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res +$(COMPILER_UNITTARGETDIR): + $(MKDIRTREE) $(COMPILER_UNITTARGETDIR) +$(COMPILER_TARGETDIR): + $(MKDIRTREE) $(COMPILER_TARGETDIR) +%$(PPUEXT): %.pp + $(COMPILER) $< + $(EXECPPAS) +%$(PPUEXT): %.pas + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.pp + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.pas + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.lpr + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.dpr + $(COMPILER) $< + $(EXECPPAS) +%.res: %.rc + windres -i $< -o $@ +vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.inc $(COMPILER_INCLUDEDIR) +vpath %$(OEXT) $(COMPILER_UNITTARGETDIR) +vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR) +.PHONY: fpc_shared +override INSTALLTARGET+=fpc_shared_install +ifndef SHARED_LIBVERSION +SHARED_LIBVERSION=$(FPC_VERSION) +endif +ifndef SHARED_LIBNAME +SHARED_LIBNAME=$(PACKAGE_NAME) +endif +ifndef SHARED_FULLNAME +SHARED_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERSION)$(SHAREDLIBEXT) +endif +ifndef SHARED_LIBUNITS +SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS) +override SHARED_LIBUNITS:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED_LIBUNITS)) +endif +fpc_shared: +ifdef HASSHAREDLIB + $(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1 +ifneq ($(SHARED_BUILD),n) + $(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGETDIR) -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR) +endif +else + @$(ECHO) Shared Libraries not supported +endif +fpc_shared_install: +ifneq ($(SHARED_BUILD),n) +ifneq ($(SHARED_LIBUNITS),) +ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME)),) + $(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INSTALL_SHAREDDIR) +endif +endif +endif +.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall +ifdef INSTALL_UNITS +override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS)) +endif +ifdef INSTALL_BUILDUNIT +override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES)) +endif +ifdef INSTALLPPUFILES +override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) +ifneq ($(UNITTARGETDIRPREFIX),) +override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES))) +override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES)))) +endif +override INSTALL_CREATEPACKAGEFPC=1 +endif +ifdef INSTALLEXEFILES +ifneq ($(TARGETDIRPREFIX),) +override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES))) +endif +endif +fpc_install: all $(INSTALLTARGET) +ifdef INSTALLEXEFILES + $(MKDIR) $(INSTALL_BINDIR) +ifdef UPXPROG + -$(UPXPROG) $(INSTALLEXEFILES) +endif + $(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR) +endif +ifdef INSTALL_CREATEPACKAGEFPC +ifdef FPCMAKE +ifdef PACKAGE_VERSION +ifneq ($(wildcard Makefile.fpc),) + $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc + $(MKDIR) $(INSTALL_UNITDIR) + $(INSTALL) Package.fpc $(INSTALL_UNITDIR) +endif +endif +endif +endif +ifdef INSTALLPPUFILES + $(MKDIR) $(INSTALL_UNITDIR) + $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR) +ifneq ($(INSTALLPPULINKFILES),) + $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR) +endif +ifneq ($(wildcard $(LIB_FULLNAME)),) + $(MKDIR) $(INSTALL_LIBDIR) + $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR) +ifdef inUnix + ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME) +endif +endif +endif +ifdef INSTALL_FILES + $(MKDIR) $(INSTALL_DATADIR) + $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR) +endif +fpc_sourceinstall: distclean + $(MKDIR) $(INSTALL_SOURCEDIR) + $(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR) +fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS)) +ifdef HASEXAMPLES + $(MKDIR) $(INSTALL_EXAMPLEDIR) +endif +ifdef EXAMPLESOURCEFILES + $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR) +endif +ifdef TARGET_EXAMPLEDIRS + $(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR) +endif +.PHONY: fpc_distinstall +fpc_distinstall: install exampleinstall +.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall +ifndef PACKDIR +ifndef inUnix +PACKDIR=$(BASEDIR)/../fpc-pack +else +PACKDIR=/tmp/fpc-pack +endif +endif +ifndef ZIPNAME +ifdef DIST_ZIPNAME +ZIPNAME=$(DIST_ZIPNAME) +else +ZIPNAME=$(PACKAGE_NAME) +endif +endif +ifndef FULLZIPNAME +FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX) +endif +ifndef ZIPTARGET +ifdef DIST_ZIPTARGET +ZIPTARGET=DIST_ZIPTARGET +else +ZIPTARGET=install +endif +endif +ifndef USEZIP +ifdef inUnix +USETAR=1 +endif +endif +ifndef inUnix +USEZIPWRAPPER=1 +endif +ifdef USEZIPWRAPPER +ZIPPATHSEP=$(PATHSEP) +ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT)) +else +ZIPPATHSEP=/ +endif +ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR)) +ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR)) +ifdef USETAR +ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT) +ZIPCMD_ZIP:=$(TARPROG) cf$(TAROPT) $(ZIPDESTFILE) * +else +ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT) +ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) * +endif +fpc_zipinstall: + $(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1 + $(MKDIR) $(DIST_DESTDIR) + $(DEL) $(ZIPDESTFILE) +ifdef USEZIPWRAPPER +ifneq ($(ECHOREDIR),echo) + $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER) + $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER) + $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER) +else + echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER) + echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER) + echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER) +endif +ifdef inUnix + /bin/sh $(ZIPWRAPPER) +else +ifdef RUNBATCH + $(RUNBATCH) $(ZIPWRAPPER) +else + $(ZIPWRAPPER) +endif +endif + $(DEL) $(ZIPWRAPPER) +else + $(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE) +endif + $(DELTREE) $(PACKDIR) +fpc_zipsourceinstall: + $(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX) +fpc_zipexampleinstall: +ifdef HASEXAMPLES + $(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX) +endif +fpc_zipdistinstall: + $(MAKE) fpc_zipinstall ZIPTARGET=distinstall +.PHONY: fpc_clean fpc_cleanall fpc_distclean +ifdef EXEFILES +override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES)) +endif +ifdef CLEAN_UNITS +override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS)) +endif +ifdef CLEANPPUFILES +override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) +ifdef DEBUGSYMEXT +override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES)) +endif +override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES)) +override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES))) +endif +fpc_clean: $(CLEANTARGET) +ifdef CLEANEXEFILES + -$(DEL) $(CLEANEXEFILES) +endif +ifdef CLEANPPUFILES + -$(DEL) $(CLEANPPUFILES) +endif +ifneq ($(CLEANPPULINKFILES),) + -$(DEL) $(CLEANPPULINKFILES) +endif +ifdef CLEANRSTFILES + -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES)) +endif +ifdef CLEAN_FILES + -$(DEL) $(CLEAN_FILES) +endif +ifdef LIB_NAME + -$(DEL) $(LIB_NAME) $(LIB_FULLNAME) +endif + -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE) + -$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT) +fpc_cleanall: $(CLEANTARGET) +ifdef CLEANEXEFILES + -$(DEL) $(CLEANEXEFILES) +endif +ifdef COMPILER_UNITTARGETDIR +ifdef CLEANPPUFILES + -$(DEL) $(CLEANPPUFILES) +endif +ifneq ($(CLEANPPULINKFILES),) + -$(DEL) $(CLEANPPULINKFILES) +endif +ifdef CLEANRSTFILES + -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES)) +endif +endif + -$(DELTREE) units + -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT) +ifneq ($(PPUEXT),.ppu) + -$(DEL) *.o *.ppu *.a +endif + -$(DELTREE) *$(SMARTEXT) + -$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE) + -$(DEL) *_ppas$(BATCHEXT) +ifdef AOUTEXT + -$(DEL) *$(AOUTEXT) +endif +ifdef DEBUGSYMEXT + -$(DEL) *$(DEBUGSYMEXT) +endif +fpc_distclean: cleanall +.PHONY: fpc_baseinfo +override INFORULES+=fpc_baseinfo +fpc_baseinfo: + @$(ECHO) + @$(ECHO) == Package info == + @$(ECHO) Package Name..... $(PACKAGE_NAME) + @$(ECHO) Package Version.. $(PACKAGE_VERSION) + @$(ECHO) + @$(ECHO) == Configuration info == + @$(ECHO) + @$(ECHO) FPC.......... $(FPC) + @$(ECHO) FPC Version.. $(FPC_VERSION) + @$(ECHO) Source CPU... $(CPU_SOURCE) + @$(ECHO) Target CPU... $(CPU_TARGET) + @$(ECHO) Source OS.... $(OS_SOURCE) + @$(ECHO) Target OS.... $(OS_TARGET) + @$(ECHO) Full Source.. $(FULL_SOURCE) + @$(ECHO) Full Target.. $(FULL_TARGET) + @$(ECHO) SourceSuffix. $(SOURCESUFFIX) + @$(ECHO) TargetSuffix. $(TARGETSUFFIX) + @$(ECHO) + @$(ECHO) == Directory info == + @$(ECHO) + @$(ECHO) Required pkgs... $(REQUIRE_PACKAGES) + @$(ECHO) + @$(ECHO) Basedir......... $(BASEDIR) + @$(ECHO) FPCDir.......... $(FPCDIR) + @$(ECHO) CrossBinDir..... $(CROSSBINDIR) + @$(ECHO) UnitsDir........ $(UNITSDIR) + @$(ECHO) PackagesDir..... $(PACKAGESDIR) + @$(ECHO) + @$(ECHO) GCC library..... $(GCCLIBDIR) + @$(ECHO) Other library... $(OTHERLIBDIR) + @$(ECHO) + @$(ECHO) == Tools info == + @$(ECHO) + @$(ECHO) As........ $(AS) + @$(ECHO) Ld........ $(LD) + @$(ECHO) Ar........ $(AR) + @$(ECHO) Rc........ $(RC) + @$(ECHO) + @$(ECHO) Mv........ $(MVPROG) + @$(ECHO) Cp........ $(CPPROG) + @$(ECHO) Rm........ $(RMPROG) + @$(ECHO) GInstall.. $(GINSTALL) + @$(ECHO) Echo...... $(ECHO) + @$(ECHO) Shell..... $(SHELL) + @$(ECHO) Date...... $(DATE) + @$(ECHO) FPCMake... $(FPCMAKE) + @$(ECHO) PPUMove... $(PPUMOVE) + @$(ECHO) Upx....... $(UPXPROG) + @$(ECHO) Zip....... $(ZIPPROG) + @$(ECHO) + @$(ECHO) == Object info == + @$(ECHO) + @$(ECHO) Target Loaders........ $(TARGET_LOADERS) + @$(ECHO) Target Units.......... $(TARGET_UNITS) + @$(ECHO) Target Implicit Units. $(TARGET_IMPLICITUNITS) + @$(ECHO) Target Programs....... $(TARGET_PROGRAMS) + @$(ECHO) Target Dirs........... $(TARGET_DIRS) + @$(ECHO) Target Examples....... $(TARGET_EXAMPLES) + @$(ECHO) Target ExampleDirs.... $(TARGET_EXAMPLEDIRS) + @$(ECHO) + @$(ECHO) Clean Units......... $(CLEAN_UNITS) + @$(ECHO) Clean Files......... $(CLEAN_FILES) + @$(ECHO) + @$(ECHO) Install Units....... $(INSTALL_UNITS) + @$(ECHO) Install Files....... $(INSTALL_FILES) + @$(ECHO) + @$(ECHO) == Install info == + @$(ECHO) + @$(ECHO) DateStr.............. $(DATESTR) + @$(ECHO) ZipName.............. $(ZIPNAME) + @$(ECHO) ZipPrefix............ $(ZIPPREFIX) + @$(ECHO) ZipCrossPrefix....... $(ZIPCROSSPREFIX) + @$(ECHO) ZipSuffix............ $(ZIPSUFFIX) + @$(ECHO) FullZipName.......... $(FULLZIPNAME) + @$(ECHO) Install FPC Package.. $(INSTALL_FPCPACKAGE) + @$(ECHO) + @$(ECHO) Install base dir..... $(INSTALL_BASEDIR) + @$(ECHO) Install binary dir... $(INSTALL_BINDIR) + @$(ECHO) Install library dir.. $(INSTALL_LIBDIR) + @$(ECHO) Install units dir.... $(INSTALL_UNITDIR) + @$(ECHO) Install source dir... $(INSTALL_SOURCEDIR) + @$(ECHO) Install doc dir...... $(INSTALL_DOCDIR) + @$(ECHO) Install example dir.. $(INSTALL_EXAMPLEDIR) + @$(ECHO) Install data dir..... $(INSTALL_DATADIR) + @$(ECHO) + @$(ECHO) Dist destination dir. $(DIST_DESTDIR) + @$(ECHO) Dist zip name........ $(DIST_ZIPNAME) + @$(ECHO) +.PHONY: fpc_info +fpc_info: $(INFORULES) +.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \ + fpc_makefile_dirs +fpc_makefile: + $(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc +fpc_makefile_sub1: +ifdef TARGET_DIRS + $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS)) +endif +ifdef TARGET_EXAMPLEDIRS + $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS)) +endif +fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS)) +fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2 +fpc_makefiles: fpc_makefile fpc_makefile_dirs +all: fpc_all +debug: fpc_debug +smart: fpc_smart +release: fpc_release +units: fpc_units +examples: +shared: fpc_shared +install: fpc_install +sourceinstall: fpc_sourceinstall +exampleinstall: fpc_exampleinstall +distinstall: fpc_distinstall +zipinstall: fpc_zipinstall +zipsourceinstall: fpc_zipsourceinstall +zipexampleinstall: fpc_zipexampleinstall +zipdistinstall: fpc_zipdistinstall +clean: fpc_clean +distclean: fpc_distclean +cleanall: fpc_cleanall +info: fpc_info +makefiles: fpc_makefiles +.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles +ifneq ($(wildcard fpcmake.loc),) +include fpcmake.loc +endif +.NOTPARALLEL: diff --git a/packages/fcl-js/Makefile.fpc b/packages/fcl-js/Makefile.fpc new file mode 100644 index 0000000000..301377c892 --- /dev/null +++ b/packages/fcl-js/Makefile.fpc @@ -0,0 +1,26 @@ +# +# Makefile.fpc for Javascript Parser +# + +[package] +name=fcl-js +version=2.5.1 + +[target] +units=jsbase jstree jsscanner jsparser + +[install] +fpcpackage=y + +[default] +fpcdir=../.. + +[compiler] +includedir=src +sourcedir=src + +[shared] +build=n + +[rules] +.NOTPARALLEL: diff --git a/packages/fcl-js/README.TXT b/packages/fcl-js/README.TXT new file mode 100644 index 0000000000..1c9701d64f --- /dev/null +++ b/packages/fcl-js/README.TXT @@ -0,0 +1,23 @@ +This is a package that contains a Javascript Scanner/parser/Syntax tree. + +The following units are defined: + +jsbase: the definition of Javascript values. Used to represent constant values. +jstree: The Javascript syntax tree elements. Used in the parser to describe a source program +jsscanner: the Javascript scanner. Currently not yet unicode-enabled. +jsparser: the Javascript parser. Builds a complete javascript syntax tree. + +The tests directory contains a set of FPCUnit tests to test the scanner and parser. +It needs Lazarus to run. + +Todo: +- Add more tests. +- Unicode support. +- Runtime-engine ? + +The idea for the tree elements and the parser come from the Libsee library, +written by David Leonard. + +Enjoy! + +Michael.
\ No newline at end of file diff --git a/packages/fcl-js/fpmake.pp b/packages/fcl-js/fpmake.pp new file mode 100644 index 0000000000..76cdc0fa99 --- /dev/null +++ b/packages/fcl-js/fpmake.pp @@ -0,0 +1,37 @@ +{$ifndef ALLPACKAGES} +{$mode objfpc}{$H+} +program fpmake; + +uses fpmkunit; + +Var + P : TPackage; + T : TTarget; +begin + With Installer do + begin +{$endif ALLPACKAGES} + + P:=AddPackage('fcl-js'); +{$ifdef ALLPACKAGES} + P.Directory:='fcl-js'; +{$endif ALLPACKAGES} + P.Version:='1.0'; + P.Author := 'Michael Van Canneyt'; + P.License := 'LGPL with FPC modification'; + P.HomepageURL := 'www.freepascal.org'; + P.Email := 'michael@freepascal.org'; + P.Description := 'Javascript scanner/parser/syntax tree units'; + + P.SourcePath.Add('src'); + P.IncludePath.Add('src'); + + T:=P.Targets.AddUnit('jsbase.pp'); + T:=P.Targets.AddUnit('jstree.pp'); + T:=P.Targets.AddUnit('jsscanner.pp'); + T:=P.Targets.AddUnit('jsparser.pp'); +{$ifndef ALLPACKAGES} + Run; + end; +end. +{$endif ALLPACKAGES} diff --git a/packages/fcl-js/src/jsbase.pp b/packages/fcl-js/src/jsbase.pp new file mode 100644 index 0000000000..52e1bdda8e --- /dev/null +++ b/packages/fcl-js/src/jsbase.pp @@ -0,0 +1,175 @@ +unit jsbase; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils; + +Type + TJSType = (jstUNDEFINED,jstNull,jstBoolean,jstNumber,jstString,jstObject,jstReference,JSTCompletion); + + TJSString = WideString; + TJSNumber = Double; + + { TJSValue } + + TJSValue = Class(TObject) + private + FValueType: TJSType; + FValue : Record + Case Integer of + 0 : (P : Pointer); + 1 : (F : TJSNumber); + 2 : (I : Integer); + end; + procedure ClearValue(ANewValue: TJSType); + function GetAsBoolean: Boolean; + function GetAsCompletion: TObject; + function GetAsNumber: TJSNumber; + function GetAsObject: TObject; + function GetAsReference: TObject; + function GetAsString: TJSString; + function GetIsNull: Boolean; + function GetIsUndefined: Boolean; + procedure SetAsBoolean(const AValue: Boolean); + procedure SetAsCompletion(const AValue: TObject); + procedure SetAsNumber(const AValue: TJSNumber); + procedure SetAsObject(const AValue: TObject); + procedure SetAsReference(const AValue: TObject); + procedure SetAsString(const AValue: TJSString); + procedure SetIsNull(const AValue: Boolean); + procedure SetIsUndefined(const AValue: Boolean); + Public + Destructor Destroy; override; + Property ValueType : TJSType Read FValueType; + Property IsUndefined : Boolean Read GetIsUndefined Write SetIsUndefined; + Property IsNull : Boolean Read GetIsNull Write SetIsNull; + Property AsNumber : TJSNumber Read GetAsNumber Write SetAsNumber; + Property AsBoolean : Boolean Read GetAsBoolean Write SetAsBoolean; + Property AsObject : TObject Read GetAsObject Write SetAsObject; + Property AsString : TJSString Read GetAsString Write SetAsString; + Property AsReference : TObject Read GetAsReference Write SetAsReference; + Property AsCompletion : TObject Read GetAsCompletion Write SetAsCompletion; + end; + +implementation + +{ TJSValue } + + +function TJSValue.GetAsBoolean: Boolean; +begin + If (ValueType=jstBoolean) then + Result:=(FValue.I<>0) + else + Result:=False; +end; + +function TJSValue.GetAsCompletion: TObject; +begin + Result:=TObject(FValue.P); +end; + +function TJSValue.GetAsNumber: TJSNumber; +begin + If (ValueType=jstNumber) then + Result:=FValue.F; +end; + +function TJSValue.GetAsObject: TObject; +begin + If (ValueType=jstObject) then + Result:=TObject(FValue.P); +end; + +function TJSValue.GetAsReference: TObject; +begin + If (ValueType=jstReference) then + Result:=TObject(FValue.P); +end; + +function TJSValue.GetAsString: TJSString; +begin + If (ValueType=jstString) then + Result:=String(FValue.P); +end; + +function TJSValue.GetIsNull: Boolean; +begin + Result:=(ValueType=jstNull); +end; + +function TJSValue.GetIsUndefined: Boolean; +begin + Result:=(fValueType=jstUndefined); +end; + +procedure TJSValue.ClearValue(ANewValue : TJSType); + +begin + Case FValueType of + jstString : String(FValue.P):=''; + jstNumber : FValue.F:=0; + else + FValue.I:=0; + end; + FValueType:=ANewValue; +end; + +procedure TJSValue.SetAsBoolean(const AValue: Boolean); +begin + ClearValue(jstBoolean); + FValue.I:=Ord(AValue); +end; + +procedure TJSValue.SetAsCompletion(const AValue: TObject); +begin + ClearValue(jstBoolean); + FValue.P:=AValue; +end; + +procedure TJSValue.SetAsNumber(const AValue: TJSNumber); +begin + ClearValue(jstNumber); + FValue.F:=AValue; +end; + +procedure TJSValue.SetAsObject(const AValue: TObject); +begin + ClearValue(jstObject); + FValue.P:=AVAlue; +end; + +procedure TJSValue.SetAsReference(const AValue: TObject); +begin + ClearValue(jstReference); + FValue.P:=AVAlue; +end; + +procedure TJSValue.SetAsString(const AValue: TJSString); +begin + ClearValue(jstString); + String(FValue.P):=AValue; +end; + +procedure TJSValue.SetIsNull(const AValue: Boolean); +begin + ClearValue(jstNull); +end; + +procedure TJSValue.SetIsUndefined(const AValue: Boolean); +begin + ClearValue(jstUndefined); +end; + +destructor TJSValue.Destroy; +begin + ClearValue(jstUndefined); + inherited Destroy; +end; + + +end. + diff --git a/packages/fcl-js/src/jsparser.pp b/packages/fcl-js/src/jsparser.pp new file mode 100644 index 0000000000..0cd714934f --- /dev/null +++ b/packages/fcl-js/src/jsparser.pp @@ -0,0 +1,2100 @@ +unit jsparser; + +{$define debugparser} +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, jsscanner, jstree; + +Const + SEmptyLabel = ''; + +Type + + + { TJSLabelSet } + + TJSLabelSet = Class(TObject) + private + FCOnt: Boolean; + FNext: TJSLabelSet; + FTarget: Cardinal; + Public + Property Target : Cardinal Read FTarget Write FTarget; + Property Next : TJSLabelSet Read FNext Write FNext; // Linked list + Property Continuable : Boolean Read FCOnt Write FCont; + end; + + { TJSLabel } + + TJSLabel = Class(TObject) + private + FLabelSet: TJSLabelSet; + FLocationLine: Integer; + FLocationPos: Integer; + FLocationSource: String; + FName: String; + FNext: TJSLabel; + Public + Property Name : String Read FName Write FName; + Property LabelSet : TJSLabelSet Read FLabelSet Write FLabelSet; + Property LocationSource : String Read FLocationSource Write FLocationSource; + Property LocationLine : Integer Read FLocationLine Write FLocationLine; + Property LocationPos : Integer Read FLocationPos Write FLocationPos; + Property Next : TJSLabel Read FNext Write FNext; + end; + + { TJSParser } + + TJSParser = Class(TObject) + Private + FFunctionDepth: Integer; + FInput : TStream; + FIsLHS: Boolean; + FNoIn: Boolean; + FScanner : TJSScanner; + FCurrent : TJSToken; + FCurrentString : String; + FNextNewLine : Boolean; + FNextBol : Boolean; + FFreeScanner : Boolean; + FCurrentVars : TJSElementNodes; + FPeekToken: TJSToken; + FPeekTokenString: String; + FLabelSets, + FCurrentLabelSet:TJSLabelSet; + FLabels : TJSLabel; + function EnterLabel(ALabelName: String): TJSLabel; + procedure Expect(aToken: TJSToken); + procedure Consume(aToken: TJSToken); + procedure FreeCurrentLabelSet; + procedure LeaveLabel; + function LookupLabel(ALabelName: String; Kind: TJSToken): TJSLabel; + function ParseAdditiveExpression: TJSElement; + function ParseArguments: TJSarguments; + function ParseArrayLiteral: TJSElement; + function ParseAssignmentExpression: TJSElement; + function ParseBitwiseAndExpression: TJSElement; + function ParseBitwiseORExpression: TJSElement; + function ParseBitwiseXORExpression: TJSElement; + function ParseBlock: TJSElement; + function ParseBreakStatement: TJSElement; + function ParseConditionalExpression: TJSElement; + function ParseContinueStatement: TJSElement; + function ParseEmptyStatement: TJSElement; + function ParseEqualityExpression: TJSElement; + function ParseExpression: TJSElement; + function ParseExpressionStatement: TJSElement; + function ParseFormalParameterList: TStrings; + function ParseFunctionDeclaration: TJSFunctionDeclarationStatement; + function ParseFunctionExpression: TJSFunctionDeclarationStatement; + function ParseFunctionStatement: TJSElement; + function ParseFunctionBody: TJSFunctionBody; + function ParseIdentifier: String; + function ParseIfStatement: TJSElement; + function ParseIterationStatement: TJSElement; + function ParseLabeledStatement: TJSElement; + function ParseLeftHandSideExpression: TJSElement; + function ParseLiteral: TJSElement; + function ParseLogicalAndExpression: TJSElement; + function ParseLogicalORExpression: TJSElement; + function ParseMemberExpression: TJSElement; + function ParseMultiplicativeExpression: TJSElement; + function ParseNumericLiteral: TJSElement; + function ParseObjectLiteral: TJSElement; + function ParsePostFixExpression: TJSElement; + function ParsePrimaryExpression: TJSElement; + function ParseRegularExpressionLiteral: TJSElement; + function ParseRelationalExpression: TJSElement; + function ParseReturnStatement: TJSElement; + function ParseShiftExpression: TJSElement; + function ParseStatement: TJSElement; + function ParseStatementList: TJSElement; + function ParseStringLiteral: TJSElement; + function ParseSwitchStatement: TJSElement; + function ParseThrowStatement: TJSElement; + function ParseTryStatement: TJSElement; + function ParseUnaryExpression: TJSElement; + function ParseVariableDeclaration: TJSElement; + function ParseVariableDeclarationList: TJSElement; + function ParseVariableStatement: TJSElement; + function ParseWithStatement: TJSElement; + Protected + Procedure CheckParser; + Function CurrentLabelSet : TJSLabelSet; + function CurSource: String; + Function CurLine : Integer; + Function CurPos : Integer; + Function CreateElement(AElementClass : TJSElementClass) : TJSElement; + Procedure Error(Msg : String); + Procedure Error(Fmt : String; Args : Array of const); + // Parse functions + function ParseSourceElements: TJSSourceElements; + Property FunctionDepth : Integer Read FFunctionDepth Write FFunctionDepth; + Property NoIn : Boolean Read FNoIn Write FNoIn; + Property IsLHS : Boolean Read FIsLHS Write FIsLHS; + Public + Constructor Create(AInput: TStream); + Constructor Create(AScanner : TJSScanner); + Function Parse : TJSElement; + Function ParseProgram : TJSFunctionDeclarationStatement; + Function CurrentToken : TJSToken; + Function CurrentTokenString : String; + Function GetNextToken : TJSToken; + Function PeekNextToken : TJSToken; + Function IsEndOfLine : Boolean; + end; + +implementation + +uses typinfo; + +Resourcestring + SErrUnmatchedCurlyBrace = 'Unmatched }'; + SErrUnmatchedSquareBrace = 'Unmatched ]'; + SErrUnmatchedBrace = 'Unmatched )'; + SErrUnexpectedToken = 'Unexpected token: ''%s'''; + SErrTokenMismatch = 'Unexpected token: ''%s'', expected: ''%s'''; + SErrSemicolonOrInExpected = 'Unexpected token: ''%s'', expected ; or ''in'''; + SErrSemicolonExpected = 'Unexpected token: ''%s'', expected ;'; + SErrDuplicateLabelName = 'Duplicate label name: ''%s'''; + SErrLabelNotContinuable = 'Label ''%s'' is not suitable for continue.'; + SErrLabelNOtDefinedOrReachable = 'Label ''%s'' is not defined or not reachable.'; + SErrContinueNotInLoop = 'Continue statement not in loop'; + SErrBreakNotInLoop = 'Break statement not in loop'; + SErrReturnNotInFunction = 'return statement not in a function body'; + SErrCaseEndExpected = 'Unexpected token: Expected }, case or default clause'; + SErrDuplicateSwitchDefault = 'Duplicate default clause for switch statement'; + SErrNewlineAfterThrow = 'Newline after throw not allowed'; + SErrCatchFinallyExpected = 'Unexpected token: Expected ''catch'' or ''finally'''; + SErrArgumentsExpected = 'Unexpected token: Expected '','' or '')'', got %s'; + SErrArrayEnd = 'Unexpected token: Expected '','' or '']'', got %s'; + SErrObjectEnd = 'Unexpected token: Expected '','' or ''}'', got %s'; + SErrObjectElement = 'Unexpected token: Expected string, identifier or number after '','' got: %s'; + SErrLiteralExpected = 'Unexpected token: Expected: null, true, false, number, string, or regex, got: %s'; + SErrInvalidnumber = 'Invalid numerical value: %s'; + SErrInvalidRegularExpression = 'Invalid regular expression: %s'; + SErrFunctionNotAllowedHere = 'function keyword not allowed here'; + +{ TJSScanner } + +function TJSParser.CurrentToken: TJSToken; + +begin + Result:=FCurrent; +end; + +function TJSParser.CurrentTokenString: String; +begin + Result:=FCurrentString; +end; + +function TJSParser.GetNextToken: TJSToken; +begin + If (FPeekToken<>tjsunknown) then + begin + FCurrent:=FPeekToken; + FCurrentString:=FPeekTokenString; + FPeekToken:=tjsUnknown; + FPeekTokenString:=''; + end + else + begin + FCurrent:=FScanner.FetchToken; + FCurrentString:=FScanner.CurTokenString; + end; + {$ifdef debugparser}Writeln('GetNextToken : ',GetEnumName(TypeInfo(TJSToken),Ord(FCurrent)), ' As string: ',FCurrentString);{$endif debugparser} +end; + +function TJSParser.PeekNextToken: TJSToken; +begin + If (FPeekToken=tjsUnknown) then + begin + FPeekToken:=FScanner.FetchToken; + FPeekTokenString:=FScanner.CurTokenString; + end; + {$ifdef debugparser}Writeln('PeekNextToken : ',GetEnumName(TypeInfo(TJSToken),Ord(FPeekToken)), ' As string: ',FPeekTokenString);{$endif debugparser} + Result:=FPeekToken; +end; + +function TJSParser.IsEndOfLine: Boolean; +begin + Result:=FScanner.IsEndOfLine; +end; + + +function TJSParser.CurPos: Integer; +begin + If Assigned(FScanner) then + Result:=FScanner.CurColumn + else + Result:=0; +end; + +function TJSParser.CurLine: Integer; +begin + If Assigned(FScanner) then + Result:=FScanner.CurRow + else + Result:=0; +end; + +function TJSParser.CurSource: String; +begin + If Assigned(FScanner) then + Result:=FScanner.CurFileName + else + Result:=''; +end; + +procedure TJSParser.CheckParser; +begin + +end; + +Procedure TJSParser.LeaveLabel; + +Var + L : TJSLabel; + +begin + L:=FLabels; + FLabels:=FLabels.Next; + L.Free; // ?? +end; + +function TJSParser.LookupLabel(ALabelName : String; Kind : TJSToken) :TJSLabel; + +Var + L : TJSLabel; + +begin + L:=FLabels; + Result:=Nil; + While (L<>Nil) and (Result=Nil) do + begin + If (L.Name=ALabelName) then + begin + if (kind=tjsContinue) and (Not L.LabelSet.Continuable) and (ALabelName<>SEmptyLabel) then + Error(SErrLabelNotContinuable,[ALabelName]); + Result:=L; + end; + L:=L.Next; + end; + If (Result=Nil) then + begin + If (ALabelName<>'') then + Error(SErrLabelNOtDefinedOrReachable,[ALabelName]) + else if kind=tjsCOntinue then + Error(SErrContinueNotInLoop) + else + Error(SErrBreakNotInLoop); + end; +end; + +function TJSParser.EnterLabel(ALabelName : String) :TJSLabel; + +Var + L : TJSLabel; + +begin + If (ALAbelName<>SEmptyLabel) then + begin + L:=FLabels; + While (L<>Nil) do + begin + If (L.Name=ALabelName) then + Error(SErrDuplicateLabelName,[ALabelName]); + L:=L.Next; + end; + end; + L:=TJSLabel.Create; + L.Name:=ALabelName; + L.LabelSet:=CurrentLabelSet; + L.LocationSource:=Self.CurSource; + L.LocationLine:=CurLine; + L.LocationPos:=CurPos; + L.Next:=FLabels; + FLabels:=L; + Result:=L; +end; + +function TJSParser.CurrentLabelSet: TJSLabelSet; + +Var + LS : TJSLabelSet; + +begin + If (FCurrentLabelSet=Nil) then + begin + LS:=TJSLabelSet.Create; + If (FLabelSets=Nil) then + LS.Target:=1 + else + LS.Target:=FLabelSets.Target; + LS.Next:=FLabelSets; + FLabelSets:=LS; + FCurrentLabelSet:=LS; + end; + Result:=FCurrentLabelSet; +end; + +function TJSParser.CreateElement(AElementClass: TJSElementClass): TJSElement; +begin + Result:=AElementClass.Create(CurLine,CurPos,CurSource); +end; + +procedure TJSParser.Error(Msg: String); + +Var + ErrAt : String; + +begin + If Assigned(FScanner) then + If FScanner.CurFilename<>'' then + ErrAt:=Format('Error: file "%s" line %d, pos %d: ',[FScanner.CurFileName,FScanner.CurRow,FScanner.CurColumn]) + else + ErrAt:=Format('Error: line %d, pos %d: ',[FScanner.Currow,FScanner.CurColumn]); + Raise Exception.Create(ErrAt+Msg) +end; + +procedure TJSParser.Error(Fmt: String; Args: array of const); +begin + Error(Format(Fmt,Args)); +end; + +constructor TJSParser.Create(AInput: TStream); +begin + FInput:=AInput; + FCurrent:=TJSUnknown; + FScanner:=TJSScanner.Create(FInput); + FFreeScanner:=True; +end; + +constructor TJSParser.Create(AScanner: TJSScanner); +begin + FCurrent:=TJSUnknown; + FScanner:=AScanner; + FFreeScanner:=False; +end; + + + +Procedure TJSParser.Expect(aToken : TJSToken); + +begin + {$ifdef debugparser} Writeln('Expecting : ',GetEnumName(TypeInfo(TJSToken),Ord(AToken)), ' As string: ',TokenInfos[AToken]);{$endif debugparser} + If (CurrentToken<>aToken) then + Error(SerrTokenMismatch,[CurrenttokenString,TokenInfos[aToken]]); +end; + +procedure TJSParser.Consume(aToken: TJSToken); +begin + Expect(aToken); + GetNextToken; +end; + +function TJSParser.ParseIdentifier : String; + +begin + Result:=''; + Repeat + Expect(tjsIdentifier); + Result:=Result+CurrentTokenString; + GetNextToken; + If (CurrentToken=tjsDot) then + begin + If (Result<>'') then + Result:=Result+'.'; + GetNextToken; + end; + until (CurrentToken<>tjsIdentifier); +end; + +function TJSParser.ParseFormalParameterList : TStrings; + +begin + Result:=Nil; + While (CurrentToken=tjsIdentifier) do + begin + Expect(tjsIdentifier); + If (Result=Nil) then + Result:=TstringList.Create; + Result.Add(CurrentTokenString); + GetNextToken; + If (CurrentToken=tjsComma) then + GetNextToken; + end; +end; + + +function TJSParser.ParseFunctionDeclaration : TJSFunctionDeclarationStatement; + +Var + Id : String; + D : TJSFuncDef; + args : TStrings; + body : TJSFunctionBody; + +begin + {$ifdef debugparser} Writeln('>>> Entering ParseFunctionDeclaration');{$endif debugparser} + Consume(tjsFunction); + ID:=ParseIdentifier; + Consume(tjsBraceOpen); + Args:=ParseFormalParameterList; + try + Consume(tjsBraceClose); + Consume(tjsCurlyBraceOpen); + Inc(FFunctionDepth); + try + Body:=ParseFunctionBody; + try + // GetNextToken; not sure + Consume(tjsCurlyBraceClose); + D:=TJSFuncDef.Create; + try + D.Name:=ID; + If Assigned(Args)then + D.Params.Assign(Args); + D.Body:=Body; + Result:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement)); + Result.AFunction:=D; + except + FreeAndNil(D); + Raise; + end; + except + FreeAndNil(Body); + Raise; + end; + finally + Dec(FFunctionDepth); + end; + finally + FreeAndNil(Args); + end; + {$ifdef debugparser} Writeln('>>> Exiting ParseFunctionDeclaration');{$endif debugparser} +end; + +function TJSParser.ParseStatementList : TJSElement; + +Var + E : TJSElement; + SL : TJSSTatementList; + +begin + {$ifdef debugparser} Writeln('>>> ParseStatementList');{$endif debugparser} + E:=ParseStatement; + try + if (CurrentToken in [tjsCurlyBraceClose,tjsEof,tjsCase,tjsDefault]) then + Result:=E + else + begin + SL:=TJSSTatementList(CreateElement(TJSStatementList)); + try + SL.A:=E; + SL.B:=ParseStatementlist; + Result:=SL; + except + FreeAndNil(SL); + Raise; + end; + end; + except + FreeAndNil(E); + Raise; + end; + {$ifdef debugparser} Writeln('<<< ParseStatementList');{$endif debugparser} +end; + +function TJSParser.ParseBlock : TJSElement; + +begin + {$ifdef debugparser} Writeln('>>> ParseBlock');{$endif debugparser} + Consume(tjsCurlyBraceOpen); + If (CurrentToken=tjsCurlyBraceClose) then + Result:=CreateElement(TJSEmptyBlockStatement) + else + result:=ParseStatementList; + Consume(tjsCurlyBraceClose); + {$ifdef debugparser} Writeln('<<< ParseBlock');{$endif debugparser} +end; + +Function TJSParser.ParseArrayLiteral : TJSElement; + +Var + N : TJSArrayLiteral; + E : TJSArrayLiteralElement; + I : Integer; + +begin + Consume(tjsSquaredBraceOpen); + N:=TJSArrayLiteral(CreateElement(TJSArrayLiteral)); + Result:=N; + try + I:=0; + While (CurrentToken<>tjsSquaredBraceClose) do + begin + If (CurrentToken=tjsComma) then + begin + GetNextToken; + Inc(I); + end + else + begin + E:=N.Elements.AddElement; + E.Index:=I; + Inc(I); + E.Expr:=ParseAssignmentExpression; + If Not (CurrentToken in [tjsComma,tjsSquaredBraceClose]) then + Error(SErrArrayEnd,[CurrentTokenString]) + end; + end; + Consume(tjsSquaredBraceClose); + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseObjectLiteral : TJSElement; + +Var + N : TJSObjectLiteral; + E : TJSObjectLiteralElement; + I : Integer; + +begin + Consume(tjsCurlyBraceOpen); + N:=TJSObjectLiteral(CreateElement(TJSObjectLiteral)); + Result:=N; + try + While (CurrentToken<>tjsCurlyBraceClose) do + begin + If (CurrentToken in [tjsIdentifier,jsscanner.tjsString,tjsnumber]) then + begin + E:=N.Elements.AddElement; + E.Name:=CurrenttokenString; + GetNextToken; + end + else + Error(SErrObjectElement,[CurrentTokenString]); + Consume(tjsColon); + E.Expr:=ParseAssignmentExpression; + If Not (CurrentToken in [tjsComma,tjsCurlyBraceClose]) then + Error(SErrObjectEnd,[CurrentTokenString]) + end; + Consume(tjsCurlyBraceClose); + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseNumericLiteral : TJSElement; + +Var + L : TJSLiteral; + D : Double; + I : Integer; + +begin + {$ifdef debugparser} Writeln('Parsing numerical literal');{$endif debugparser} + Result:=Nil; + try + Val(CurrentTokenString,D,I); + If (I>0) then + Error(SErrInvalidnumber,[CurrentTokenString]); + L:=TJSLiteral(CreateElement(TJSLiteral)); + GetNextToken; + L.Value.AsNumber:=D; + Result:=L; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseStringLiteral : TJSElement; + +Var + L : TJSLiteral; + D : Double; + I : Integer; + +begin + {$ifdef debugparser} Writeln('Parsing string literal');{$endif debugparser} + Result:=Nil; + try + L:=TJSLiteral(CreateElement(TJSLiteral)); + L.Value.AsString:=CurrentTokenString; + GetNextToken; + Result:=L; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseRegularExpressionLiteral : TJSElement; + +Var + S,pa,fl : String; + P : integer; + R : TJSRegularExpressionLiteral; +begin + Result:=Nil; + If (CurrentToken=tjsRegex) then + begin + S:=CurrentTokenString; + P:=Length(S); + While (P>=1) and (S[P]<>'/') do + Dec(P); + If (P<=1) then + Error(SErrInvalidRegularExpression,[CurrentTokenString]); + pa:=Copy(S,2,P-1); + fl:=Copy(S,P,Length(S)-P+1); + R:=TJSRegularExpressionLiteral(CreateElement(TJSRegularExpressionLiteral)); + Result:=R; + R.Pattern.AsString:=Pa; + R.PatternFlags.AsString:=Fl; + R.Argv[0]:=R.Pattern; + R.Argv[1]:=R.PatternFlags; + end; + try + Consume(tjsRegEx); + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseLiteral : TJSElement; + +Var + L : TJSLiteral; + +begin + {$ifdef debugparser}Writeln('Parsing literal: ',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser} + Result:=Nil; + Case CurrentToken of + tjsNull : begin + L:=TJSLiteral(CreateElement(TJSLiteral)); + Result:=L; + L.Value.IsNull:=True; + GetNextToken; + end; + tjsTrue, + tjsFalse: begin + L:=TJSLiteral(CreateElement(TJSLiteral)); + Result:=L; + L.Value.AsBoolean:=(CurrentToken=tjsTrue); + GetNextToken; + end; + tjsNumber : Result:=ParseNumericLiteral; + jsscanner.tjsString : Result:=ParseStringLiteral; + tjsDiv, + tjsDivEq : Result:=ParseRegularExpressionLiteral + else + Error(SErrLiteralExpected,[CurrentTokenString]); + end; +end; + +Function TJSParser.ParsePrimaryExpression : TJSElement; + +Var + R : TJSPrimaryExpressionIdent; + +begin + Result:=Nil; + try + Case CurrentToken of + tjsThis : + begin + Result:=TJSPrimaryExpressionThis(CreateElement(TJSPrimaryExpressionThis)); + GetNextToken; + end; + tjsidentifier: + begin + R:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent)); + Result:=R; + R.AString:=CurrentTokenString; + GetNextToken; + end; + tjsSquaredBraceOpen: Result:=ParseArrayLiteral; + tjsCurlyBraceOpen: Result:=ParseObjectLiteral; + tjsBraceOpen: + begin + Writeln('Found brace !!'); + Consume(tjsBraceOpen); + Result:=ParseExpression; + Consume(tjsBraceClose); + end; + else + Result:=ParseLiteral; + end; // Case; + except + FreeAndNil(Result); + Raise; + end; +end; + + +Function TJSParser.ParseMemberExpression : TJSElement; + +Var + M : TJSDotMemberExpression; + B : TJSBracketMemberExpression; + C : TJSCallExpression; + Done : Boolean; + +begin + Case CurrentToken of + tjsFunction : Result:=ParseFunctionExpression; + tjsNew : Result:=ParseMemberExpression; + else + Result:=ParsePrimaryExpression + end; + try + Done:=False; + Repeat + Case CurrentToken of + tjsDot : + begin + M:=TJSDotMemberExpression(CreateElement(TJSDotMemberExpression)); + M.MExpr:=Result; + Result:=M; + GetNextToken; + If (CurrentToken=tjsIdentifier) then + M.Name:=CurrentTokenString; + Consume(tjsIdentifier); + end; + tjsSquaredBraceOpen: + begin + B:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression)); + B.MExpr:=Result; + Result:=B; + GetNextToken; + B.Name:=ParseExpression; + Consume(tjsSquaredBraceClose); + end; + else + Done:=True; + isLHS:=True; + end; + Until Done; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseArguments : TJSarguments; + +Var + E : TJSArrayLiteralElement; + +begin + Consume(tjsBraceOpen); + Result:=TJSArguments(CreateElement(TJSArguments)); + try + While (CurrentToken<>tjsBraceClose) do + begin + E:=Result.Elements.AddElement; + E.Expr:=ParseAssignmentExpression; + If (CurrentToken<>tjsBraceClose) then + If CurrentToken=tjsComma then + GetNextToken + else + Error(SErrArgumentsExpected,[CurrentTokenString]); + end; + Consume(tjsBraceClose); + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseLeftHandSideExpression : TJSElement; + +Var + M : TJSDotMemberExpression; + B : TJSBracketMemberExpression; + C : TJSCallExpression; + Done : Boolean; + +begin + Case CurrentToken of + tjsFunction : Result:=ParseFunctionExpression; + tjsNew : Result:=ParseMemberExpression; + else + Result:=ParsePrimaryExpression + end; + try + Done:=False; + Repeat + Case CurrentToken of + tjsDot : + begin + M:=TJSDotMemberExpression(CreateElement(TJSDotMemberExpression)); + M.MExpr:=Result; + Result:=M; + GetNextToken; + If (CurrentToken=tjsIdentifier) then + M.Name:=CurrentTokenString; + Consume(tjsIdentifier); + end; + tjsSquaredBraceOpen: + begin + B:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression)); + B.MExpr:=Result; + Result:=B; + GetNextToken; + B.Name:=ParseExpression; + Consume(tjsSquaredBraceClose); + end; + tjsBraceOpen: + begin + Writeln('Call expression !!'); + C:=TJSCallExpression(CreateElement(TJSCallExpression)); + C.Expr:=Result; + Result:=C; + C.Args:=ParseArguments; + end; + else + {$ifdef debugparser}Writeln('Leaving LHS');{$endif debugparser} + Done:=True; + isLHS:=True; + end; + Until Done; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParsePostFixExpression : TJSElement; +Var + R : TJSUnaryExpression; + +begin + {$ifdef debugparser} Writeln('ParsePostfixExpression');{$endif debugparser} + Result:=ParseLeftHandSideExpression; + Try + If (Not IsEndOfLine) and (CurrentToken in [tjsPlusPlus,tjsMinusMinus]) then + begin + If (CurrentToken=tjsPlusPLus) then + R:=TJSUnaryExpression(CreateElement(TJSUnaryPostPlusPlusExpression)) + else + R:=TJSUnaryExpression(CreateElement(TJSUnaryPostMinusMinusExpression)); + R.A:=Result; + Result:=R; + GetNextToken; + isLHS:=False; + end; + except + freeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseUnaryExpression : TJSElement; + +Var + C : TJSElementClass; + R : TJSUnaryExpression; + +begin + {$ifdef debugparser} Writeln('ParseUnaryExpression');{$endif debugparser} + C:=Nil; + Result:=Nil; + try + Case CurrentToken of + tjsDelete : C:=TJSUnaryDeleteExpression; + tjsVoid : C:=TJSUnaryVoidExpression; + tjsTypeOf : C:=TJSUnaryTypeOfExpression; + tjsPlusPlus : C:=TJSUnaryPrePlusPlusExpression; + tjsMinusMinus : C:=TJSUnaryPreMinusMinusExpression; + tjsPlus : C:=TJSUnaryPlusExpression; + tjsMinus : C:=TJSUnaryMinusExpression; + tjsInv : C:=TJSUnaryInvExpression; + tjsNot : C:=TJSUnaryNotExpression; + else + Result:=ParsePostFixExpression; + end; + If (Result=Nil) then + begin + {$ifdef debugparser} Writeln('Found Unary Expression',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser} + R:=TJSUnaryExpression(CreateElement(C)); + Result:=R; + GetNextToken; + R.A:=Self.ParseUnaryExpression; + isLHS:=False; + end; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseMultiplicativeExpression : TJSElement; + +Var + C : TJSElementClass; + R : TJSMultiplicativeExpression; + +begin + {$ifdef debugparser} Writeln('ParseMultiplicativeExpression');{$endif debugparser} + Result:=ParseUnaryExpression; + try + While (CurrentToken in [tjsMul,tjsDiv,tjsMod]) do + begin + if CurrentToken=tjsMul then + C:=TJSMultiplicativeExpressionMul + else if CurrentToken=tjsDiv then + C:=TJSMultiplicativeExpressionDiv + else + C:=TJSMultiplicativeExpressionMod; + R:=TJSMultiplicativeExpression(CreateElement(C)); + GetNextToken; + R.A:=Result; + Result:=R; + R.B:=ParseUnaryExpression; + isLHS:=False; + end; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseAdditiveExpression : TJSElement; + +Var + C : TJSElementClass; + R : TJSAdditiveExpression; + +begin + {$ifdef debugparser} Writeln('ParseAdditiveExpression');{$endif debugparser} + Result:=ParseMultiplicativeExpression; + try + While (CurrentToken in [tjsPlus,tjsMinus]) do + begin + if CurrentToken=tjsPlus then + C:=TJSAdditiveExpressionPlus + else + C:=TJSAdditiveExpressionMinus; + R:=TJSAdditiveExpression(CreateElement(C)); + GetNextToken; + R.A:=Result; + Result:=R; + R.B:=ParseMultiplicativeExpression; + isLHS:=False; + end; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseShiftExpression : TJSElement; + +Var + C : TJSElementClass; + R : TJSShiftExpression; + +begin + {$ifdef debugparser} Writeln('ParseShiftExpression');{$endif debugparser} + Result:=ParseAdditiveExpression; + try + While (CurrentToken in [tjsLshift,tjsRshift,tjsURShift]) do + begin + Case CurrentToken of + tjsLshift : C:=TJSLShiftExpression; + tjsRshift : C:=TJSRShiftExpression; + tjsURshift : C:=TJSURShiftExpression; + end; + R:=TJSShiftExpression(CreateElement(C)); + R.A:=Result; + Result:=R; + GetNextToken; + R.B:=ParseAdditiveExpression; + IsLHS:=False; + end; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseRelationalExpression: TJSElement; + +Var + S : Set of TJSToken; + C : TJSElementClass; + R : TJSRelationalExpression; + +begin + Result:=ParseShiftExpression; + try + S:=[tjsLT,tjsGT,tjsLE,tjsGE,tjsInstanceOf]; + If Not Noin then + Include(S,tjsIn); + While (CurrentToken in S) do + begin + Case CurrentToken of + tjsLT : C:=TJSRelationalExpressionLT; + tjsGT : C:=TJSRelationalExpressionGT; + tjsLE : C:=TJSRelationalExpressionLE; + tjsGE : C:=TJSRelationalExpressionGE; + tjsInstanceOf :C:=TJSRelationalExpressionInstanceOf; + tjsIn : C:=TJSRelationalExpressionIn; + end; + R:=TJSRelationalExpression(CreateElement(C)); + R.A:=Result; + Result:=R; + GetNextToken; + R.B:=ParseRelationalExpression; + IsLHS:=False; + end; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseEqualityExpression: TJSElement; + +Var + C : TJSElementClass; + E : TJSEqualityExpression; + +begin + Result:=ParseRelationalExpression; + try + While (CurrentToken in [tjsEq,tjsNE,tjsSEQ,tjsSNE]) do + begin + Case CurrentToken of + tjsEq : C:=TJSEqualityExpressionEQ; + tjsNE : C:=TJSEqualityExpressionNE; + tjsSEQ : C:=TJSEqualityExpressionSEQ; + tjsSNE : C:=TJSEqualityExpressionSNE; + end; + GetNextToken; + E:=TJSEqualityExpression(CreateElement(C)); + Result:=E; + E.A:=Result; + E.B:=ParseEqualityExpression; + E:=Nil; + IsLHS:=False; + end; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseBitwiseAndExpression : TJSElement; + +Var + L : TJSBitwiseAndExpression; + +begin + Result:=ParseEqualityExpression; + try + If (CurrentToken<>tjsAnd) then + exit; + GetNextToken; + L:=TJSBitwiseAndExpression(CreateElement(TJSBitwiseAndExpression)); + L.A:=Result; + Result:=L; + L.B:=ParseBitwiseAndExpression; + IsLHS:=False; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseBitwiseXORExpression : TJSElement; + +Var + L : TJSBitwiseXOrExpression; + +begin + Result:=ParseBitwiseAndExpression; + try + If (CurrentToken<>tjsXOr) then + exit; + GetNextToken; + L:=TJSBitwiseXOrExpression(CreateElement(TJSBitwiseXOrExpression)); + L.A:=Result; + Result:=L; + L.B:=ParseBitwiseXORExpression; + IsLHS:=False; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseBitwiseORExpression : TJSElement; + +Var + L : TJSBitwiseOrExpression; + +begin + {$ifdef debugparser} Writeln('ParseBitWiseOrExpression');{$endif debugparser} + Result:=ParseBitwiseXORExpression; + try + If (CurrentToken<>tjsOr) then + exit; + GetNextToken; + L:=TJSBitwiseOrExpression(CreateElement(TJSBitwiseOrExpression)); + L.A:=Result; + Result:=L; + L.B:=ParseBitwiseORExpression; + IsLHS:=False; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseLogicalAndExpression : TJSElement; + +Var + L : TJSLogicalAndExpression; + +begin + {$ifdef debugparser} Writeln('ParseLogicalAndExpression');{$endif debugparser} + Result:=ParseBitwiseORExpression; + try + If (CurrentToken<>tjsAndAnd) then + exit; + GetNextToken; + L:=TJSLogicalAndExpression(CreateElement(TJSLogicalAndExpression)); + L.A:=Result; + Result:=L; + L.B:=ParseLogicalAndExpression; + IsLHS:=False; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseLogicalORExpression : TJSElement; + +Var + L : TJSLogicalOrExpression; + +begin + {$ifdef debugparser} Writeln('ParseLogicalOrExpression');{$endif debugparser} + Result:=ParseLogicalAndExpression; + try + If (CurrentToken<>tjsOROR) then + exit; + GetNextToken; + L:=TJSLogicalOrExpression(CreateElement(TJSLogicalOrExpression)); + L.A:=Result; + Result:=L; + L.B:=ParseLogicalOrExpression; + IsLHS:=False; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseConditionalExpression : TJSElement; + +Var + N : TJSConditionalExpression; + L : TJSElement; +begin + {$ifdef debugparser} Writeln('ParseConditionalExpression');{$endif debugparser} + Result:=Nil; + Result:=ParseLogicalORExpression; + try + If (CurrentToken=tjsConditional) then + begin + GetNextToken; + L:=Result; + N:=TJSConditionalExpression(CreateElement(TJSConditionalExpression)); + Result:=N; + N.A:=L; + L:=Nil; + N.B:=ParseAssignmentExpression; + Consume(tjsColon); + N.C:=ParseAssignmentExpression; + IsLHS:=False; + end; + except + FreeandNil(Result); + end; +end; + +Function TJSParser.ParseAssignmentExpression : TJSElement; + +Var + N : TJSElement; + C : TJSElementClass; + A : TJSAssignStatement; + +begin + {$ifdef debugparser} Writeln('ParseAssignmentExpression');{$endif debugparser} + Result:=Nil; + N:=ParseConditionalExpression; + If not isLHS then + Result:=N + else + Case CurrentToken of + tjsAssign : C:=TJSSimpleAssignStatement; + tjsMulEq : C:=TJSMulEqAssignStatement; + tjsDivEq : C:=TJSDivEqAssignStatement; + tjsModEq : C:=TJSModEqAssignStatement; + tjsPlusEq : C:=TJSAddEqAssignStatement; + tjsMinusEq : C:=TJSSubEqAssignStatement; + tjsLShiftEq : C:=TJSLShiftEqAssignStatement; + tjsRShiftEq : C:=TJSRShiftEqAssignStatement; + tjsURShiftEq : C:=TJSURShiftEqAssignStatement; + tjsANDEq : C:=TJSANDEqAssignStatement; + tjsOREq : C:=TJSOREqAssignStatement; + tjsXOREq : C:=TJSXOREqAssignStatement; + else +// writeln('Strange token',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString); + Result:=N + end; + If Result<>Nil then + Exit; + A:=TJSAssignStatement(CreateElement(C)); + try + Result:=A; + A.Lhs:=N; + GetNextToken; + N:=Self.ParseAssignmentExpression; + A.Expr:=N; + IsLhs:=False; + except + FreeAndNil(Result); + Raise; + end; +end; + +Function TJSParser.ParseVariableDeclaration : TJSElement; + +Var + V : TJSVarDeclaration; + +begin + V:=TJSVarDeclaration(CreateElement(TJSVarDeclaration));; + try + V.Name:=CurrenttokenString; + Consume(tjsIdentifier); + if (CurrentToken=tjsAssign) then + begin + GetNextToken; + V.Init:=ParseAssignmentExpression; + end; + Result:=V; + Writeln('Adding variable ',V.Name); + FCurrentVars.AddNode.Node:=Result; + Writeln('Current var count: ',FCurrentVars.Count); + except + FreeAndNil(V); + Raise; + end; +end; + +Function TJSParser.ParseVariableDeclarationList : TJSElement; + +Var + E,N : TJSElement; + L : TJSVariableDeclarationList; + +begin + Writeln('ParseVariableDeclarationList entry'); + E:=ParseVariableDeclaration; + If (CurrentToken<>tjsComma) then + Result:=E + else + begin + L:=TJSVariableDeclarationList(CreateElement(TJSVariableDeclarationList)); + Result:=L; + try + Consume(tjsComma); + N:=Self.ParseVariableDeclarationList; + L.A:=E; + L.B:=N; + except + FreeAndNil(Result); + Raise; + end; + end; + Writeln('ParseVariableDeclarationList exit'); +end; + +function TJSParser.ParseVariableStatement : TJSElement; + +Var + E : TJSElement; + V : TJSVariableStatement; + +begin + Writeln('ParseVariableStatement entry'); + Result:=Nil; + Consume(tjsVar); + Result:=ParseVariableDeclarationList; + try + Consume(tjsSemicolon); + V:=TJSVariableStatement(CreateElement(TJSVariableStatement)); + V.A:=Result; + Result:=V; + except + FreeAndNil(Result); + Raise; + end; + Writeln('ParseVariableStatement exit'); +end; + +function TJSParser.ParseEmptyStatement : TJSElement; + +begin + Consume(tjsSemiColon); + Result:=CreateElement(TJSEmptyStatement); +end; + +function TJSParser.ParseIfStatement : TJSElement; + +Var + C,BTrue,BFalse : TJSElement; + I : TJSIFstatement; + +begin + C:=Nil; + BTrue:=Nil; + BFalse:=Nil; + try + Consume(tjsIF); + Consume(tjsBraceOpen); + C:=ParseExpression; + Consume(tjsBraceClose); + BTrue:=ParseStatement; + If (CurrentToken=tjsElse) then + begin + Consume(tjsElse); + BFalse:=ParseStatement; + end; + I:=TJSIfStatement(CreateElement(TJSIfStatement)); + I.Cond:=C; + I.BTrue:=Btrue; + I.bfalse:=BFalse; + Result:=I; + except + FreeAndNil(C); + FreeAndNil(BTrue); + FreeAndNil(BFalse); + Raise; + end; +end; + +function TJSParser.ParseIterationStatement : TJSElement; + +Var + F : TJSForStatement; + FI : TJSForInStatement; + W : TJSWhileStatement; + N : TJSElement; + +begin + Result:=Nil; + N:=Nil; + CurrentLabelSet.Continuable:=True; + EnterLabel(SEmptyLabel); + try + try + Case CurrentToken of + tjsDo : + begin + GetNextToken; + W:=TJSWhileStatement(CreateElement(TJSWhileStatement)); + Result:=W; + W.Body:=ParseStatement; + Consume(tjsWhile); + Consume(tjsBraceOpen); + W.Cond:=ParseExpression; + Consume(tjsBraceClose); + Consume(tjsSemicolon); + end; + tjsWhile : + begin + GetNextToken; + W:=TJSWhileStatement(CreateElement(TJSWhileStatement)); + Result:=W; + Consume(tjsBraceOpen); + W.Cond:=ParseExpression; + Consume(tjsBraceClose); + W.Body:=ParseStatement; + Result:=W; + end; + else + // For ? + GetNextToken; + Consume(tjsBraceopen); + If (CurrentToken=tjsVar) then + begin + GetNextToken; + N:=ParseVariableDeclarationList; + // for (var in + If (CurrentToken=tjsIn) and (N is tJSVarDeclaration) then + begin + Fi:=TJSForInStatement(CreateElement(TJSForInStatement)); + Result:=Fi; + Fi.LHS:=N; + GetNextToken; + Fi.List:=ParseExpression; + Consume(tjsBraceClose); + Fi.Body:=ParseStatement; + end; + // for (var ; + If (CurrentToken<>tjsSemicolon) then + If (N is tJSVarDeclaration) then + Error(SErrSemicolonOrInExpected,[CurrentTokenString]) + else + Error(SErrSemicolonExpected,[CurrentTokenString]); + GetNextToken; + F:=TJSForStatement(CreateElement(TJSForStatement)); + Result:=F; + If (CurrentToken<>tjsSemicolon) then + F.Cond:=ParseExpression; + Consume(tjsSemicolon); + If (CurrentToken<>tjsBraceClose) then + F.Incr:=ParseExpression; + Consume(tjsBraceClose); + F.Body:=ParseStatement; + end + else + begin + If (CurrentToken<>tjsSemicolon) then + begin + N:=ParseExpression; + If (CurrentToken=tjsIn) then + begin + Fi:=TJSForInStatement(CreateElement(TJSForInStatement)); + Result:=Fi; + Fi.LHS:=N; + N:=Nil; // prevent freeing a second time in case of an exception. + GetNextToken; + Fi.List:=ParseExpression; + Consume(tjsBraceClose); + Fi.Body:=ParseStatement; + Exit; // We must jump out here + end + end + else + N:=Nil; + // For ( Init; Cond; incr) + F:=TJSForStatement(CreateElement(TJSForStatement)); + Result:=F; + F.Init:=N; + N:=Nil; // prevent freeing a second time in case of an exception. + Consume(tjsSemicolon); + if (CurrentToken<>tjsSemicolon) then + F.Cond:=ParseExpression; + Consume(tjsSemicolon); + If (CurrentToken<>tjsBraceClose) Then + F.Incr:=ParseExpression; + Consume(tjsBraceClose); + F.Body:=ParseStatement; + end; + end; // Case + Finally + LeaveLabel; + end; + except + FreeAndNil(N); + FreeAndNil(Result); + Raise; + end; +end; + +function TJSParser.ParseContinueStatement : TJSElement; + +Var + L : TJSLabel; + C : TJSContinueStatement; + +begin + C:=TJSContinueStatement(CreateElement(TJSContinueStatement)); + try + Result:=C; + Consume(tjsContinue); + If (CurrentToken=tjsSemicolon) then + L:=LookupLabel(SEmptyLabel,tjsContinue) + else + begin + if (CurrentToken=tjsIdentifier) then + L:=LookupLabel(CurrentTokenString,tjsContinue); + Consume(tjsIdentifier); + end; + Consume(tjsSemicolon); + C.Target:=L.Labelset.Target; + except + FreeAndNil(C); + Raise; + end; +end; + +function TJSParser.ParseBreakStatement : TJSElement; + +Var + L : TJSLabel; + B : TJSBreakStatement; + +begin + B:=TJSBreakStatement(CreateElement(TJSBreakStatement)); + try + Result:=B; + Consume(tjsBreak); + If (CurrentToken=tjsSemicolon) then + L:=LookupLabel(SEmptyLabel,tjsBreak) + else + begin + if (CurrentToken=tjsIdentifier) then + L:=LookupLabel(CurrentTokenString,tjsBreak); + Consume(tjsIdentifier); + end; + Consume(tjsSemicolon); + B.Target:=L.Labelset.Target; + except + FreeAndNil(B); + Raise; + end; +end; + +function TJSParser.ParseReturnStatement : TJSElement; + +Var + R : TJSreturnStatement; + +begin + R:=TJSReturnStatement(CreateElement(TJSReturnStatement)); + try + Result:=R; + Consume(tjsReturn); + If (FunctionDepth=0) then + Error(SErrReturnNotInFunction); + If Not (CurrentToken=tjsSemicolon) then + R.Expr:=ParseExpression; + Consume(tjsSemicolon); + except + FreeAndNil(R); + Raise; + end; +end; + +function TJSParser.ParseWithStatement : TJSElement; + +Var + W : TJSWithStatement; + N : TJSElement; + +begin + W:=TJSWithStatement(CreateElement(TJSWithStatement)); + try + Consume(tjsWith); + Consume(tjsBraceOpen); + W.A:=ParseExpression; + Consume(tjsBraceClose); + W.B:=ParseStatement; + except + FreeAndNil(W); + Raise; + end; +end; + +function TJSParser.ParseSwitchStatement : TJSElement; + + +Var + N : TJSSwitchStatement; + C : TJSElement; + Ca : TJSCaseElement; + +begin + N:=TJSSwitchStatement(CreateElement(TJSSwitchStatement)); + try + N.Target:=CurrentLabelset.Target; + EnterLabel(SEmptyLabel); + try + Consume(tjsSwitch); + Consume(tjsBraceOpen); + N.Cond:=ParseExpression; + Consume(tjsBraceClose); + Consume(tjsCurlyBraceOpen); + While (CurrentToken<>tjsCurlyBraceClose) do + begin + If (CurrentToken=tjsCase) then + begin + GetNextToken; + Ca:=N.Cases.AddCase; + Ca.Expr:=ParseExpression; + end + else if (CurrentToken=tjsDefault) then + begin + If (N.TheDefault<>Nil) then + Error(SerrDuplicateSwitchDefault); + Ca:=N.Cases.AddCase; + N.TheDefault:=Ca; + GetNextToken; + end + else + Error(SerrCaseEndExpected); + Consume(tjsColon); + If Not (CurrentToken in [tjsCurlyBraceClose,tjsCase,tjsDefault]) then + Ca.Body:=ParseStatementList; + end; + Consume(tjsCurlyBraceClose); + finally + LeaveLabel; + end; + except + FreeAndNil(N); + Raise; + end; +end; + +function TJSParser.ParseThrowStatement : TJSElement; + +Var + TS : TJSThrowStatement; + +begin + TS:=TJSThrowStatement(CreateElement(TJSThrowStatement)); + try + Result:=TS; + Consume(tjsThrow); + If IsEndOfLine then + Error(SErrNewlineAfterThrow); + TS.A:=ParseExpression; + Consume(tjsSemicolon); + except + FreeAndNil(TS); + Raise; + end; +end; + +function TJSParser.ParseTryStatement : TJSElement; + +Var + BO,BC,BF : TJSElement; + Id : TJSString; + T : TJSTryStatement; + +begin + BO:=Nil; + BC:=Nil; + BF:=Nil; + Result:=Nil; + Consume(tjsTry); + try + Bo:=ParseBlock; + if (CurrentToken=tjscatch) then + begin + Consume(tjsCatch); + Consume(tjsBraceOpen); + if (CurrentToken=tjsIdentifier) then + id:=CurrentTokenString; + Consume(tjsIdentifier); + Consume(tjsBraceClose); + BC:=ParseBlock; + end; + if (CurrentToken=tjsFinally) then + begin + consume(tjsFinally); + BF:=ParseBlock; + end; + If (BF=Nil) and (BC=Nil) then + Error(SErrCatchFinallyExpected); + If Assigned(BC) AND Assigned(BF) then + T:=TJSTryStatement(CreateElement(TJSTryCatchFinallyStatement)) + else if Assigned(BC) then + T:=TJSTryStatement(CreateElement(TJSTryCatchStatement)) + else + T:=TJSTryStatement(CreateElement(TJSTryFinallyStatement)); + Result:=T; + T.Block:=Bo; + Bo:=Nil; + T.BCatch:=BC; + BC:=Nil; + T.BFinally:=BF; + BF:=Nil; + T.Ident:=ID; + except + FreeAndNil(Bo); + FreeAndNil(BC); + FreeAndNil(BF); + FreeAndNil(Result); + Raise; + end; + +end; + +function TJSParser.ParseFunctionExpression : TJSFunctionDeclarationStatement; + +Var + Oni,olhs: Boolean; + F : TJSFunctionDeclarationStatement; + N : String; + Args : TStrings; + +begin + {$ifdef debugparser} Writeln('>>> ParseFunctionExpression');{$endif} + oni:=NoIn; + olhs:=IsLHS; + F:=Nil; + Args:=Nil; + try + NoIn:=False; + IsLHS:=False; + F:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement)); + try + Consume(tjsFunction); + if (CurrentToken=tjsIdentifier) then + begin + n:=CurrentTokenstring; + GetNextToken; + end + else + n:=''; + Consume(tjsBraceOpen); + F.AFunction:= TJSFuncDef.Create; + Args:=ParseFormalParameterList; + try + If Assigned(Args) then + F.AFunction.Params.Assign(Args); + finally + FreeAndNil(Args); + end; + Consume(tjsBraceClose); + Consume(tjsCurlyBraceOpen); + Inc(FFunctionDepth); + try + F.AFunction.Body:=ParseFunctionBody; + Finally + Dec(FFunctionDepth); + end; + Consume(tjsCurlyBraceClose); + Result:=F; + except + FreeAndNil(F); + Raise; + end; + finally + NoIn := oni; + IsLHS := olhs; + end; + {$ifdef debugparser} Writeln('<<< ParseFunctionExpression');{$endif} +end; + +function TJSParser.ParseFunctionStatement : TJSElement; + +Var + F : TJSFunctionDeclarationStatement; + I : TJSPrimaryExpressionIdent; + A : TJSAssignStatement; + E : TJSExpressionStatement; + +begin + {$ifdef debugparser} Writeln('>>> ParseFunctionStatement');{$endif} + F:=Nil; + I:=Nil; + A:=Nil; + try + F:=ParseFunctionExpression; + I:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent)); + I.AString:=F.AFunction.Name; + A:=TJSAssignStatement(CreateElement(TJSAssignStatement)); + A.LHS:=I; + I:=Nil; + A.Expr:=F; + F:=Nil; + E:=TJSExpressionStatement(CreateElement(TJSExpressionStatement)); + E.A:=A; + A:=Nil; + Result:=E; + except + FreeAndNil(F); + FreeAndNil(I); + FreeAndNil(A); + Raise; + end; + {$ifdef debugparser} Writeln('<<< ParseFunctionStatement');{$endif} +end; + +function TJSParser.ParseLabeledStatement : TJSElement; + +Var + OL : TJSLabelSet; + LS : TJSLabeledStatement; + LN : String; + +begin + LS:=TJSLabeledStatement(CreateElement(TJSLabeledStatement)); + try + Result:=LS; + OL:=FCurrentLabelSet; + try + FCurrentLabelSet:=Nil; + LS.target:=CurrentLabelSet.Target; + Repeat + EnterLabel(CurrentTokenString); + Consume(tjsIdentifier); + Consume(tjsColon); + Until (CurrentToken<>tjsIdentifier) or (PeekNextToken<>tjsColon); + Case CurrentToken of + tjsDo,tjsWhile,tjsFor : LS.A:=ParseIterationStatement; + tjsswitch : LS.A:=ParseSwitchStatement; + else + LS.A:=ParseStatement; + end; + finally + FreeCurrentLabelSet; + FCurrentLabelSet:=Ol; + end; + except + FreeAndNil(LS); + Raise; + end; +end; + +procedure TJSParser.FreeCurrentLabelSet; + +Var + L : TJSLabelSet; + +begin + While Assigned(FCurrentLabelSet) do + begin + L:=FCurrentLabelset.Next; + FCurrentLabelSet.Free; + FCurrentLabelSet:=L; + end; +end; + +function TJSParser.ParseExpressionStatement : TJSElement; + +Var + E : TJSElement; + R : TJSExpressionStatement; +begin + E:=ParseExpression; + Consume(tjsSemicolon); + R:=TJSExpressionStatement(CreateElement(TJSExpressionStatement)); + R.A:=E; + Result:=R; +end; + +function TJSParser.ParseExpression : TJSElement; + +Var + C : TJSCommaExpression; + +begin + Result:=ParseAssignmentExpression; + try + If (CurrentToken=tjsComma) then + begin + C:=TJSCommaExpression(CreateElement(TJSCommaExpression)); + C.A:=Result; + Result:=C; + GetNextToken; + C.B:=ParseExpression; + end; + except + FreeAndNil(Result); + Raise; + end; + +end; + +function TJSParser.ParseStatement : TJSElement; + +begin + {$ifdef debugparser} Writeln('>>> Parsestatement');{$endif} + Result:=Nil; + Case CurrentToken of + tjsCurlyBraceOpen : + Result:=ParseBlock; + tjsVar: + Result:=ParseVariableStatement; + tjsSemicolon: + Result:=ParseEmptyStatement; + tjsIf: + Result:=ParseIfStatement; + tjsDo,tjsWhile,tjsFor: + Result:=ParseIterationStatement; + tjsContinue: + Result:=ParseContinueStatement; + tjsBreak: + Result:=ParseBreakStatement; + tjsReturn: + Result:=ParseReturnStatement; + tjsWith: + Result:=ParseWithStatement; + tjsSwitch: + Result:=ParseSwitchStatement; + tjsThrow: + Result:=ParseThrowStatement; + tjsTry: + Result:=ParseTryStatement; + tjsFunction: + begin + If (PeekNextToken<>tjsBraceOpen) then + Result:=ParseFunctionStatement; + Error(SErrFunctionNotAllowedHere); + end; + tjsIdentifier: + If (PeekNextToken=tjsColon) then + Result:=ParseLabeledStatement + else + Result:=ParseExpressionStatement; + else + Result:=ParseExpressionStatement; + end; + {$ifdef debugparser} Writeln('<<< Parsestatement ',Result.ClassName);{$endif} +end; + +function TJSParser.ParseSourceElements : TJSSourceElements; + +Const + StatementTokens = [tjsNULL, tjsTRUE, tjsFALSE, + tjsTHIS, tjsIdentifier,jsscanner.tjsSTRING,tjsNUMBER, + tjsBraceOpen,tjsCurlyBraceOpen,tjsSquaredBraceOpen, + tjsNew,tjsDelete,tjsVoid,tjsTypeOf, + tjsPlusPlus,tjsMinusMinus, + tjsPlus,tjsMinus,tjsNot,tjsNE,tjsSNE,tjsSemicolon, + tjsVAR,tjsIF,tjsDO,tjsWHILE,tjsFOR,jsscanner.tjsCONTINUE,jsscanner.tjsBREAK,jsscanner.tjsReturn, + tjsWith,jsscanner.tjsSWITCH,tjsThrow,TjsTry,tjsDIV,tjsDIVEQ]; + +Var + F : TJSFunctionDeclarationStatement; + E : TJSElement; + Done : Boolean; + VS : TJSElementNodes; +begin + {$ifdef debugparser} Writeln('>>> Entering source elements');{$endif} + Result:=TJSSourceElements(CreateElement(TJSSourceElements)); + try + Done:=False; + VS:=FCurrentVars; + Try + FCurrentVars:=Result.Vars; + Repeat + {$ifdef debugparser} Writeln('Sourceelements start:',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser} + If (CurrentToken=jsscanner.tjsFunction) then + begin + If (PeekNextToken<>tjsBraceOpen) then + begin + F:=Self.ParseFunctionDeclaration; + Result.functions.AddNode.Node:=F; + end + else + begin + {$ifdef debugparser} Writeln('Function expression detected');{$endif} + E:=Self.ParseStatement; + Result.Statements.AddNode.Node:=E; + end; + end + else if CurrentToken in StatementTokens then + begin + E:=Self.ParseStatement; + Result.Statements.AddNode.Node:=E; + end + else + Done:=True; + {$ifdef debugparser} Writeln('Sourceelements Done : ',Done);{$endif} + Until Done; + Finally + FCurrentVars:=VS; + end; + except + FreeAndNil(Result); + Raise; + end; + {$ifdef debugparser} Writeln('<<< Exiting source elements');{$endif} +end; + +function TJSParser.ParseFunctionBody : TJSFunctionBody; + +Var + E : TJSElement; + +begin + {$ifdef debugparser} Writeln('>>> Entering FunctionBody');{$endif} + Result:=TJSFunctionBody(CreateElement(TJSFunctionBody)); + try + E:=Self.ParseSourceElements; + Result.A:=E; + except + FreeAndNil(Result); + Raise; + end; + {$ifdef debugparser} Writeln('<<< Exiting FunctionBody');{$endif} +end; + +function TJSParser.ParseProgram : TJSFunctionDeclarationStatement; + +Var + F : TJSFunctionDeclarationStatement; + FD : TJSFuncDef; + B : TJSElement; +begin + {$ifdef debugparser} Writeln('>>> Entering FunctionDeclarationStatement');{$endif} + B:=Parse; + If Not (B is TJSFunctionBody) then + Error('Parse did not result in functionbody'); + Result:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement)); + Result.AFunction:=TJSFuncDef.Create; + Result.AFunction.Body:=TJSFunctionBody(B); + {$ifdef debugparser} Writeln('<<< Exiting FunctionDeclarationStatement');{$endif} +end; + +function TJSParser.Parse: TJSElement; + +Var + Body : TJSElement; + +begin + {$ifdef debugparser} Writeln('>>> Parse');{$endif} + Result:=Nil; + CheckParser; + GetNextToken; + Body:=ParseFunctionBody; + Result:=Body; + try + if (CurrentToken<>tjsEOF) then + begin + if (CurrentToken=tjsCurlyBraceClose) then + Error(SErrUnmatchedCurlyBrace) + else if (CurrentToken=tjsBraceClose) then + Error(SerrUnmatchedBrace) + else if (CurrentToken=tjsSquaredBraceClose) then + Error(SerrUnmatchedSquareBrace); + Error(SErrUnexpectedToken,[CurrentTokenString]); + end; + If (Body is TJSFunctionBody) then + TJSFunctionBody(Body).isProgram:=True; + except + FreeAndNil(Result); + Raise; + end; + {$ifdef debugparser} Writeln('<<< Parse');{$endif} +end; + + +end. + diff --git a/packages/fcl-js/src/jsscanner.pp b/packages/fcl-js/src/jsscanner.pp new file mode 100644 index 0000000000..d30b2b0e47 --- /dev/null +++ b/packages/fcl-js/src/jsscanner.pp @@ -0,0 +1,909 @@ +{ + This file is part of the Free Component Library + + ECMAScript (JavaScript) source lexical scanner + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. + + 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. + + **********************************************************************} + +{$mode objfpc} +{$h+} + +unit JSScanner; + +interface + +uses SysUtils, Classes; + +resourcestring + SErrInvalidCharacter = 'Invalid character ''%s'''; + SErrOpenString = 'string exceeds end of line'; + SErrIncludeFileNotFound = 'Could not find include file ''%s'''; + SErrIfXXXNestingLimitReached = 'Nesting of $IFxxx too deep'; + SErrInvalidPPElse = '$ELSE without matching $IFxxx'; + SErrInvalidPPEndif = '$ENDIF without matching $IFxxx'; + SInvalidHexadecimalNumber = 'Invalid decimal number'; + SErrInvalidNonEqual = 'SyntaxError: != or !== expected'; + +type + + TJSToken = (tjsUnknown, + // Specials + tjsEOF,tjsWhiteSpace,tjsChar,tjsString, tjsIdentifier,tjsNumber, tjsComment,tjsREGEX, tjsRESERVED, + tjsANDAND, tjsANDEQ, + tjsBraceOpen,tjsBraceClose,tjsSQuaredBraceOpen,tjsSQuaredBraceClose,tjsCurlyBraceOpen,tjsCurlyBraceClose, + tjsCOMMA,tjsCOLON, tjsDOT,tjsSEMICOLON, tjsASSIGN,tjsGT,tjsLT, tjsConditional, + tjsPLUS,tjsMINUS,tjsMUL,tjsDIV,tjsAnd,tjsOR, tjsInv, tjsMod, tjsXOR, tjsNot, + tjsEQ, + tjsGE, + tjsLE, tjsLSHIFT, tjsLSHIFTEQ, + tjsMINUSEQ, tjsMINUSMINUS, tjsMODEQ,tjsDIVEQ,tjsXOREq, + tjsNE, + tjsOREQ, tjsOROR, + tjsPLUSEQ, tjsPLUSPLUS, + tjsURSHIFT, tjsURSHIFTEQ, + tjsRSHIFT, tjsRSHIFTEQ, + tjsSEQ, tjsSNE, tjsMULEQ, + { Reserved words start here. They must be last } + tjsBREAK,tjsCASE, tjsCATCH, tjsCONTINUE, + tjsDEFAULT, tjsDELETE, tjsDO, + tjsELSE, + tjsFalse, tjsFINALLY, tjsFOR, tjsFUNCTION, + tjsIF, tjsIN, tjsINSTANCEOF, + tjsNEW,tjsNULL, + tjsRETURN, + tjsSWITCH, + tjsTHIS, tjsTHROW, tjsTrue, tjsTRY, tjsTYPEOF, + tjsVAR, tjsVOID, + tjsWHILE, tjsWITH + ); + +const + FirstKeyword = tjsBreak; + LastKeyWord = tJSWith; + + TokenInfos: array[TJSToken] of string = ('unknown', + // Specials + 'EOF','whitespace','Char','String', 'identifier','number','comment','regular expression', 'reserved word', + '&&','&=', + '(',')','[',']','{','}', + ',',':','.',';','=','>','<','?', + '+','-','*','/','&','|','~','%','^','!', + '==', + '>=', + '<=', '<<', '<<=', + '-=', '--', '%=', '/=','^=', + '!=', + '|=', '||', + '+=', '++', + '>>>', '>>>=', + '>>', '>>=', + '===', '!==', '*=', + // Identifiers last + 'break','case','catch', 'continue', + 'default','delete', 'do', + 'else', + 'false','finally', 'for', 'function', + 'if', 'in', 'instanceof', + 'new','null', + 'return', + 'switch', + 'this', 'throw', 'true', 'try', 'typeof', + 'var', 'void', + 'while', 'with' + ); + +Type + TLineReader = class + public + function IsEOF: Boolean; virtual; abstract; + function ReadLine: string; virtual; abstract; + end; + + { TStreamLineReader } + + TStreamLineReader = class(TLineReader) + private + FStream : TStream; + Buffer : Array[0..1024] of Byte; + FBufPos, + FBufLen : Integer; + procedure FillBuffer; + public + Constructor Create(AStream : TStream); + function IsEOF: Boolean; override; + function ReadLine: string; override; + end; + + TFileLineReader = class(TLineReader) + private + FTextFile: Text; + FileOpened: Boolean; + public + constructor Create(const AFilename: string); + destructor Destroy; override; + function IsEOF: Boolean; override; + function ReadLine: string; override; + end; + + EJSScannerError = class(Exception); + + { TJSScanner } + + TJSScanner = class + private + FReturnComments: Boolean; + FReturnWhiteSpace: Boolean; + FSourceFile: TLineReader; + FSourceFilename: string; + FCurRow: Integer; + FCurToken: TJSToken; + FCurTokenString: string; + FCurLine: string; + FDefines: TStrings; + TokenStr: PChar; + FSourceStream : TStream; + FOwnSourceFile : Boolean; + function CommentDiv: TJSToken; + function DoIdentifier : TJSToken; + function DoMultiLineComment: TJSToken; + function DoNumericLiteral: TJSToken; + function DoSingleLineComment: TJSToken; + function DoStringLiteral: TJSToken; + function DoWhiteSpace: TJSToken; + function FetchLine: Boolean; + function GetCurColumn: Integer; + function ReadUnicodeEscape: WideChar; + protected + procedure Error(const Msg: string);overload; + procedure Error(const Msg: string; Args: array of Const);overload; + public + constructor Create(ALineReader: TLineReader); + constructor Create(AStream : TStream); + destructor Destroy; override; + procedure OpenFile(const AFilename: string); + Function FetchToken: TJSToken; + Function IsEndOfLine : Boolean; + Property ReturnComments : Boolean Read FReturnComments Write FReturnComments; + Property ReturnWhiteSpace : Boolean Read FReturnWhiteSpace Write FReturnWhiteSpace; + property SourceFile: TLineReader read FSourceFile; + property CurFilename: string read FSourceFilename; + property CurLine: string read FCurLine; + property CurRow: Integer read FCurRow; + property CurColumn: Integer read GetCurColumn; + property CurToken: TJSToken read FCurToken; + property CurTokenString: string read FCurTokenString; + end; + + +implementation + + +constructor TFileLineReader.Create(const AFilename: string); +begin + inherited Create; + Assign(FTextFile, AFilename); + Reset(FTextFile); + FileOpened := true; +end; + +destructor TFileLineReader.Destroy; +begin + if FileOpened then + Close(FTextFile); + inherited Destroy; +end; + +function TFileLineReader.IsEOF: Boolean; +begin + Result := EOF(FTextFile); +end; + +function TFileLineReader.ReadLine: string; +begin + ReadLn(FTextFile, Result); +end; + +constructor TJSScanner.Create(ALineReader: TLineReader); +begin + inherited Create; + FSourceFile := ALineReader; +end; + +constructor TJSScanner.Create(AStream: TStream); +begin + FSourceStream:=ASTream; + FOwnSourceFile:=True; + Create(TStreamLineReader.Create(AStream)); +end; + +destructor TJSScanner.Destroy; +begin + If FOwnSourceFile then + FSourceFile.Free; + inherited Destroy; +end; + +procedure TJSScanner.OpenFile(const AFilename: string); +begin + FSourceFile := TFileLineReader.Create(AFilename); + FSourceFilename := AFilename; +end; + + +procedure TJSScanner.Error(const Msg: string); +begin + raise EJSScannerError.Create(Msg); +end; + +procedure TJSScanner.Error(const Msg: string; Args: array of Const); +begin + raise EJSScannerError.CreateFmt(Msg, Args); +end; + +function TJSScanner.FetchLine: Boolean; +begin + if FSourceFile.IsEOF then + begin + FCurLine := ''; + TokenStr := nil; + Result := false; + end else + begin + FCurLine := FSourceFile.ReadLine; + TokenStr := PChar(CurLine); + Result := true; + Inc(FCurRow); + end; +end; + +function TJSScanner.DoWhiteSpace : TJSToken; + +begin + Result:=tjsWhitespace; + repeat + Inc(TokenStr); + if TokenStr[0] = #0 then + if not FetchLine then + begin + FCurToken := Result; + exit; + end; + until not (TokenStr[0] in [#9, ' ']); +end; + +function TJSScanner.DoSingleLineComment : TJSToken; + +Var + TokenStart : PChar; + Len : Integer; + +begin + Inc(TokenStr); + TokenStart := TokenStr; + while TokenStr[0] <> #0 do + Inc(TokenStr); + Len:=TokenStr-TokenStart; + SetLength(FCurTokenString, Len); + if (Len>0) then + Move(TokenStart^,FCurTokenString[1],Len); + Result := tjsComment; +end; + +function TJSScanner.DoMultiLineComment : TJSToken; + +Var + TokenStart : PChar; + Len,OLen : Integer; + PrevToken : Char; + +begin + Inc(TokenStr); + TokenStart := TokenStr; + FCurTokenString := ''; + OLen:= 0; + PrevToken:=#0; + while Not ((TokenStr[0]='/') and (PrevToken='*')) do + begin + if (TokenStr[0]=#0) then + begin + Len:=TokenStr-TokenStart+1; + SetLength(FCurTokenString,OLen+Len); + if Len>1 then + Move(TokenStart^,FCurTokenString[OLen+1],Len-1); + Inc(OLen,Len); + FCurTokenString[OLen]:=#10; + if not FetchLine then + begin + Result := tjsEOF; + FCurToken := Result; + exit; + end; + TokenStart := TokenStr; + PrevToken:=#0; + end + else + begin + PrevToken:=TokenStr[0]; + Inc(TokenStr); + end; + end; + Len:=TokenStr-TokenStart-1; // -1 for * + SetLength(FCurTokenString, Olen+Len); + if (Len>0) then + Move(TokenStart^, FCurTokenString[Olen + 1], Len); + Inc(TokenStr); + Result := tjsComment; +end; + +function TJSScanner.CommentDiv : TJSToken; + +begin + FCurTokenString := ''; + Inc(TokenStr); + if (TokenStr[0] = '/') then // Single-line comment + Result:=DoSingleLineComment + else if (TokenStr[0]='*') then + Result:=DoMultiLineComment + else if (TokenStr[0] = '=') then // Single-line comment + begin + Result:=tjsDiveQ; + Inc(TokenStr) + end + else + Result:=tjsDiv; +end; + +Function TJSScanner.ReadUnicodeEscape : WideChar; + +Var + S : String; + I : Integer; + +begin + S:='0000'; + For I:=1 to 4 do + begin + Inc(TokenStr); + Case TokenStr[0] of + '0'..'9','A'..'F','a'..'f' : + S[i]:=Upcase(TokenStr[0]); + else + Error(SErrInvalidCharacter, [TokenStr[0]]); + end; + end; + // Takes care of conversion... This needs improvement !! + Result:=WideChar(StrToInt('$'+S)); +end; + +Function TJSScanner.DoStringLiteral : TJSToken; + +Var + Delim : Char; + TokenStart : PChar; + Len,OLen,I : Integer; + S : String; + +begin + Delim:=TokenStr[0]; + Inc(TokenStr); + TokenStart := TokenStr; + OLen := 0; + FCurTokenString := ''; + while not (TokenStr[0] in [#0,Delim]) do + begin + if (TokenStr[0]='\') then + begin + // Save length + Len := TokenStr - TokenStart; + Inc(TokenStr); + // Read escaped token + Case TokenStr[0] of + '"' : S:='"'; + 't' : S:=#9; + 'b' : S:=#8; + 'n' : S:=#10; + 'r' : S:=#13; + 'f' : S:=#12; + '\' : S:='\'; + '/' : S:='/'; + 'u' : begin + S:=ReadUniCodeEscape; + end; + #0 : Error(SErrOpenString); + else + Error(SErrInvalidCharacter, [TokenStr[0]]); + end; + SetLength(FCurTokenString, OLen + Len+1+Length(S)); + if Len > 0 then + Move(TokenStart^, FCurTokenString[OLen + 1], Len); + Move(S[1],FCurTokenString[OLen + Len+1],Length(S)); + Inc(OLen, Len+Length(S)); + // Next char + // Inc(TokenStr); + TokenStart := TokenStr+1; + end; + if TokenStr[0] = #0 then + Error(SErrOpenString); + Inc(TokenStr); + end; + if TokenStr[0] = #0 then + Error(SErrOpenString); + Len := TokenStr - TokenStart; + SetLength(FCurTokenString, OLen + Len); + if Len > 0 then + Move(TokenStart^, FCurTokenString[OLen+1], Len); + Inc(TokenStr); + Result := tjsString; +end; + +function TJSScanner.DoNumericLiteral :TJSToken; + +Var + TokenStart : PChar; + Len : Integer; + +begin + TokenStart := TokenStr; + while true do + begin + Inc(TokenStr); + case TokenStr[0] of + 'x': + If (TokenStart[0]='0') and ((TokenStr-TokenStart)=1) then + begin + Inc(TokenStr); + while Upcase(TokenStr[0]) in ['0'..'9','A'..'F'] do + Inc(TokenStr); + end + else + Error(SInvalidHexadecimalNumber); + '.': + begin + if TokenStr[1] in ['0'..'9', 'e', 'E'] then + begin + Inc(TokenStr); + repeat + Inc(TokenStr); + until not (TokenStr[0] in ['0'..'9', 'e', 'E','-','+']); + end; + break; + end; + '0'..'9': ; + 'e', 'E': + begin + Inc(TokenStr); + if TokenStr[0] in ['-','+'] then + Inc(TokenStr); + while TokenStr[0] in ['0'..'9'] do + Inc(TokenStr); + break; + end; + else + break; + end; + end; + Len:=TokenStr-TokenStart; + Setlength(FCurTokenString, Len); + if (Len>0) then + Move(TokenStart^,FCurTokenString[1],Len); + Result := tjsNumber; +end; + +function TJSScanner.DoIdentifier : TJSToken; + +Var + TokenStart:PChar; + Len : Integer; + I : TJSToken; + +begin + Result:=tjsIdentifier; + TokenStart := TokenStr; + repeat + Inc(TokenStr); + If (TokenStr[0]='\') and (TokenStr[1]='u') then + until not (TokenStr[0] in ['A'..'Z', 'a'..'z', '0'..'9', '_','$']); + Len:=(TokenStr-TokenStart); + SetLength(FCurTokenString,Len); + if Len > 0 then + Move(TokenStart^,FCurTokenString[1],Len); + // Check if this is a keyword or identifier + // !!!: Optimize this! + I:=FirstKeyword; + While (Result=tjsIdentifier) and (I<=Lastkeyword) do + begin + if (CurTokenString=TokenInfos[i]) then + begin + Result := i; + FCurToken := Result; + exit; + end; + I:=Succ(I); + end +end; + +function TJSScanner.FetchToken: TJSToken; + + +var + TokenStart, CurPos: PChar; + i: TJSToken; + OldLength, SectionLength, NestingLevel, Index: Integer; + +begin + + Repeat + if TokenStr = nil then + if not FetchLine then + begin + Result := tjsEOF; + FCurToken := Result; + exit; + end; + CurPos:=TokenStr; + FCurTokenString := ''; + case TokenStr[0] of + #0: // Empty line + begin + FetchLine; + Result := tjsWhitespace; + end; + '/' : + Result:=CommentDiv; + #9, ' ': + Result := DoWhiteSpace; + '''','"': + Result:=DoStringLiteral; + '0'..'9': + Result:=DoNumericLiteral; + '&': + begin + Inc(TokenStr); + If Tokenstr[0]='&' then + begin + Inc(TokenStr); + Result := tjsAndAnd; + end + else If Tokenstr[0]='=' then + begin + Inc(TokenStr); + Result := tjsAndEQ; + end + else + Result := tjsAnd; + end; + '%': + begin + Inc(TokenStr); + If Tokenstr[0]='=' then + begin + Inc(TokenStr); + Result := tjsModEq; + end + else + Result := tjsMod; + end; + '^': + begin + Inc(TokenStr); + If (TokenStr[0]='=') then + begin + Result:=tjsXorEq; + Inc(tokenStr) + end + else + result:=tjsXOR; + end; + '|': + begin + Inc(TokenStr); + If Tokenstr[0]='|' then + begin + Inc(TokenStr); + Result := tjsOROR; + end + else If Tokenstr[0]='=' then + begin + Inc(TokenStr); + Result := tjsOREQ; + end + else + Result := tjsOR; + end; + '(': + begin + Inc(TokenStr); + Result := tjsBraceOpen; + end; + ')': + begin + Inc(TokenStr); + Result := tjsBraceClose; + end; + '*': + begin + Inc(TokenStr); + If (TokenStr[0]='=') then + begin + Inc(TokenStr); + Result := tjsMulEq; + end + else + Result := tjsMul; + end; + '+': + begin + Inc(TokenStr); + If (TokenStr[0]='=') then + begin + Inc(TokenStr); + Result := tjsPlusEq; + end + else If (TokenStr[0]='+') then + begin + Inc(TokenStr); + Result := tjsPlusPlus; + end + else + Result := tjsPlus; + end; + ',': + begin + Inc(TokenStr); + Result := tjsComma; + end; + '-': + begin + Inc(TokenStr); + If (TokenStr[0]='=') then + begin + Inc(TokenStr); + Result:=tjsMinusEq + end + else If (TokenStr[0]='-') then + begin + Inc(TokenStr); + Result:=tjsMinusMinus + end + else if (TokenStr[0] in ['0'..'9']) then + begin + Result:=DoNumericLiteral; + If (Result=tjsNumber) then + FCurTokenString:='-'+FCurTokenString; + end + else + Result := tjsMinus; + end; + '.': + begin + Inc(TokenStr); + Result := tjsDot; + end; + ':': + begin + Inc(TokenStr); + Result := tjsColon; + end; + ';': + begin + Inc(TokenStr); + Result := tjsSemicolon; + end; + '<': + begin + Inc(TokenStr); + if TokenStr[0] = '=' then + begin + Inc(TokenStr); + Result := tjsLE; + end + else if TokenStr[0] = '<' then + begin + Inc(TokenStr); + if (TokenStr[0] = '=') then + begin + Inc(TokenStr); + Result := tjsLShiftEq; + end + else + Result := tjsLShift; + end + else + Result := tjsLT; + end; + '=': + begin + Inc(TokenStr); + if (TokenStr[0]='=') then + begin + Inc(TokenStr); + If (TokenStr[0]='=') then + begin + Inc(TokenStr); + Result:=tjsSEQ; + end + else + Result:=tjsEQ; + end + else + Result := tjsAssign; + end; + '!': + begin + Inc(TokenStr); + if (TokenStr[0]='=') then + begin + Inc(TokenStr); + If (TokenStr[0]='=') then + begin + Inc(TokenStr); + Result:=tjsSNE; + end + else + Result:=tjsNE; + end + else + Result:=tjsNot;// Error(SErrInvalidNonEqual); + end; + '~': + begin + Inc(TokenStr); + Result:=tjsInv; + end; + '>': + begin + Inc(TokenStr); + if TokenStr[0] = '=' then + begin + Inc(TokenStr); + Result:=tjsGE; + end + else if TokenStr[0] = '>' then + begin + Inc(TokenStr); + if (TokenStr[0] = '>') then + begin + Inc(TokenStr); + if (TokenStr[0] = '=') then + begin + Inc(TokenStr); + Result:=tjsURSHIFTEQ; + end + else + Result:=tjsURSHIFT; + end + else if (TokenStr[0] = '=') then + begin + Inc(TokenStr); + Result:=tjsRSHIFTEq; + end + else + Result:=tjsRSHIFT; + end + else + Result := tjsGT; + end; + '[': + begin + Inc(TokenStr); + Result := tJSSquaredBraceOpen; + end; + ']': + begin + Inc(TokenStr); + Result := tJSSquaredBraceClose; + end; + '{': + begin + Inc(TokenStr); + Result := tJSCurlyBraceOpen; + end; + '}': + begin + Inc(TokenStr); + Result := tJSCurlyBraceClose; + end; + else + Result:=DoIdentifier; + end; // Case + Until (Not (Result in [tjsComment,tjsWhitespace])) or + ((Result=tjsComment) and ReturnComments) or + ((Result=tjsWhiteSpace) and ReturnWhiteSpace); + FCurToken:=Result; + +end; + +function TJSScanner.IsEndOfLine: Boolean; +begin + Result:=(TokenStr=Nil) or (TokenStr[0] in [#0,#10,#13]); +end; + +function TJSScanner.GetCurColumn: Integer; +begin + Result := TokenStr - PChar(CurLine); +end; + +{ TStreamLineReader } + +constructor TStreamLineReader.Create(AStream: TStream); +begin + FStream:=AStream; + FBufPos:=0; + FBufLen:=0; +end; + +function TStreamLineReader.IsEOF: Boolean; +begin + Result:=(FBufPos>=FBufLen); + If Result then + begin + FillBuffer; + Result:=(FBufLen=0); + end; +end; + +procedure TStreamLineReader.FillBuffer; + +begin + FBufLen:=FStream.Read(Buffer,SizeOf(Buffer)-1); + Buffer[FBufLen]:=0; + FBufPos:=0; +end; + +function TStreamLineReader.ReadLine: string; + +Var + FPos,OLen,Len: Integer; + PRun : PByte; + +begin + FPos:=FBufPos; + SetLength(Result,0); + Repeat + PRun:=@Buffer[FBufPos]; + While (FBufPos<FBufLen) and Not (PRun^ in [10,13]) do + begin + Inc(PRun); + Inc(FBufPos); + end; + If (FBufPos=FBufLen) then + begin + Len:=FBufPos-FPos; + If (Len>0) then + begin + Olen:=Length(Result); + SetLength(Result,OLen+Len); + Move(Buffer[FPos],Result[OLen+1],Len) + end; + FillBuffer; + end; + until (FBufPos=FBufLen) or (PRun^ in [10,13]); + Len:=FBufPos-FPos; + If (Len>0) then + begin + Olen:=Length(Result); + SetLength(Result,OLen+Len); + Move(Buffer[FPos],Result[OLen+1],Len) + end; + If (PRun^ in [10,13]) and (FBufPos<FBufLen) then + begin + Inc(FBufPos); + // Check #13#10 + If (PRun^=13) then + begin + If (FBufPos=FBufLen) then + FillBuffer; + If (FBufPos<FBufLen) and (Buffer[FBufpos]=10) then + Inc(FBufPos); + end; + end; +end; + +end. diff --git a/packages/fcl-js/src/jstree.pp b/packages/fcl-js/src/jstree.pp new file mode 100644 index 0000000000..546d74a39f --- /dev/null +++ b/packages/fcl-js/src/jstree.pp @@ -0,0 +1,963 @@ +unit jstree; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, jsbase; + +Type + TJSElementFlag = (elIsConst,elIsConstValid); + TJSElementFlags = set of TJSElementFlag; + + TJSFunctionBody = Class; + + { TJSElement } + + TJSObject = Class(TObject); + + { TJSFuncDef } + + TJSFuncDef = Class(TJSObject) + private + FBody: TJSFunctionBody; + FCache: TJSObject; + FCommon: TJSObject; + FIsEmpty: Boolean; + FName: String; + FNext: TJSFuncDef; + FParams: TStrings; + FSec: TObject; + procedure SetParams(const AValue: TStrings); + Public + Constructor Create; + Destructor Destroy; override; + Property Params : TStrings Read FParams Write SetParams; + Property Body : TJSFunctionBody Read FBody Write FBody; + Property Name : String Read FName Write FName; + Property Common : TJSObject Read FCommon Write FCommon; + Property Cache : TJSObject Read FCache write FCache; + Property Next : TJSFuncDef Read FNext Write FNext; + Property IsEmpty : Boolean Read FIsEmpty Write FIsEmpty; + Property SecurityDomain : TObject Read FSec Write FSec; + end; + + TJSString = WideString; + + TJSElement = Class (TJSObject) + private + FFlags: TJSElementFlags; + FLine: Integer; + FRow: Integer; + FSource: String; + Public + Constructor Create(ALine,ARow : Integer; Const ASource : String = ''); virtual; + Property Source : String Read FSource Write FSource; + Property Row : Integer Read FRow Write FRow; + Property Line : Integer Read FLine Write FLine; + Property Flags : TJSElementFlags Read FFlags Write FFlags; + end; + TJSElementClass = Class of TJSElement; + + { TJSEmptyBlockStatement } + + TJSEmptyBlockStatement = Class(TJSElement); + TJSEmptyStatement = Class(TJSElement); + + { TJSLiteral } + + TJSLiteral = Class(TJSElement) + private + FValue: TJSValue; + Public + Constructor Create(ALine,ARow : Integer; Const ASource : String = ''); override; + Destructor Destroy; override; + Property Value : TJSValue Read FValue Write FValue; + end; + + { TJSStringLiteral } + + TJSStringLiteral = Class(TJSElement) + private + FValue: TJSString; + Public + Property Value : TJSString Read FValue Write FValue; + end; + + { TJSRegularExpressionLiteral } + + TJSRegularExpressionLiteral = Class(TJSElement) + private + FPattern: TJSValue; + FPatternFlags: TJSValue; + FArgv : Array[0..1] of TJSValue; + function GetA(AIndex : integer): TJSValue; + procedure SetA(AIndex : integer; const AValue: TJSValue); + Public + Constructor Create(ALine,ARow : Integer; Const ASource : String = ''); override; + Destructor Destroy; override; + Property Pattern : TJSValue Read FPattern Write FPattern; + Property PatternFlags : TJSValue Read FPatternFlags Write FPatternFlags; + Property Argv[AIndex : integer] : TJSValue Read GetA Write SetA; + end; + + { TJSPrimaryExpressionIdent } + + TJSPrimaryExpressionIdent = Class(TJSElement) + private + FString: TJSString; + Public + Property AString : TJSString Read FString Write FString; + end; + TJSPrimaryExpressionThis = Class(TJSElement); + + { TJSArrayLiteralElement } + + TJSArrayLiteralElement = Class(TCollectionItem) + private + FExpr: TJSelement; + FFindex: Integer; + Public + Destructor Destroy; override; + Property Expr : TJSelement Read FExpr Write FExpr; + Property ElementIndex : Integer Read FFindex Write FFIndex; + end; + + { TJSArrayLiteralElements } + + TJSArrayLiteralElements = Class(TCollection) + private + function GetE(AIndex : Integer): TJSArrayLiteralElement; + procedure SetE(AIndex : Integer; const AValue: TJSArrayLiteralElement); + Public + Function AddElement : TJSArrayLiteralElement; + Property Elements[AIndex : Integer] : TJSArrayLiteralElement Read GetE Write SetE; default; + end; + + { TJSArrayLiteral } + + TJSArrayLiteral = Class(TJSElement) + private + FElements: TJSArrayLiteralElements; + Public + Constructor Create(ALine,ARow : Integer; const ASource : String = ''); override; + Destructor Destroy; override; + Property Elements : TJSArrayLiteralElements Read FElements; + end; + + { TJSObjectLiteralElement } + + TJSObjectLiteralElement = Class(TCollectionItem) + private + FExpr: TJSelement; + FName: TJSString; + Public + Destructor Destroy; override; + Property Expr : TJSelement Read FExpr Write FExpr; + Property Name : TJSString Read FName Write FName; + end; + + { TJSObjectLiteralElements } + + TJSObjectLiteralElements = Class(TCollection) + private + function GetE(AIndex : Integer): TJSObjectLiteralElement; + procedure SetE(AIndex : Integer; const AValue: TJSObjectLiteralElement); + Public + Function AddElement : TJSObjectLiteralElement; + Property Elements[AIndex : Integer] : TJSObjectLiteralElement Read GetE Write SetE; default; + end; + + { TJSObjectLiteral } + + TJSObjectLiteral = Class(TJSElement) + private + FElements: TJSObjectLiteralElements; + Public + Constructor Create(ALine,ARow : Integer; const ASource : String = ''); override; + Destructor Destroy; override; + Property Elements : TJSObjectLiteralElements Read FElements; + end; + + { TJSArguments } + + TJSArguments = Class(TJSArrayLiteral); + + { TJSMemberExpression } + + TJSMemberExpression = Class(TJSElement) + private + FMexpr: TJSElement; + Public + Destructor Destroy; override; + Property Mexpr : TJSElement Read FMexpr Write FMexpr; + end; + + { TJSNewMemberExpression } + + TJSNewMemberExpression = Class(TJSMemberExpression) + private + FArgs: TJSArguments; + Public + Destructor Destroy; override; + Property Args : TJSArguments Read FArgs Write FArgs; + end; + + { TJSDotMemberExpression } + + TJSDotMemberExpression = Class(TJSMemberExpression) + private + FName: TJSString; + Public + Property Name : TJSString Read FName Write FName; + end; + + { TJSBracketMemberExpression } + + TJSBracketMemberExpression = Class(TJSMemberExpression) + private + FName: TJSElement; + Public + Destructor Destroy; override; + Property Name : TJSElement Read FName Write FName; + end; + + { TJSCallExpression } + + TJSCallExpression = Class(TJSElement) + private + FArgs: TJSArguments; + FExpr: TJSElement; + Public + Destructor Destroy; override; + Property Expr : TJSElement Read FExpr Write FExpr; + Property Args : TJSArguments Read FArgs Write FArgs; + end; + + { TJSUnary } + + TJSUnary = Class(TJSElement) + private + FA: TJSElement; + Public + Destructor Destroy; override; + Property A : TJSElement Read FA Write FA; + end; + + { TJSVariableStatement } + TJSVariableStatement = Class(TJSUnary); + TJSExpressionStatement = Class(TJSUnary); + TJSThrowStatement = Class(TJSUnary); + TJSUnaryExpression = Class(TJSUnary); + TJSUnaryDeleteExpression = Class(TJSUnaryExpression); + TJSUnaryVoidExpression = Class(TJSUnaryExpression); + TJSUnaryTypeOfExpression = Class(TJSUnaryExpression); + TJSUnaryPrePlusPlusExpression = Class(TJSUnaryExpression); + TJSUnaryPreMinusMinusExpression = Class(TJSUnaryExpression); + TJSUnaryPlusExpression = Class(TJSUnaryExpression); + TJSUnaryMinusExpression = Class(TJSUnaryExpression); + TJSUnaryInvExpression = Class(TJSUnaryExpression); + TJSUnaryNotExpression = Class(TJSUnaryExpression); + TJSUnaryPostPlusPlusExpression = Class(TJSUnaryExpression); + TJSUnaryPostMinusMinusExpression = Class(TJSUnaryExpression); + + + + { TJSBinary } + + TJSBinary = Class(TJSElement) + private + FA: TJSElement; + FB: TJSElement; + Public + Destructor Destroy; override; + Property A : TJSElement Read FA Write FA; + Property B : TJSElement Read FB Write FB; + end; + + { TJSStatementList } + + TJSStatementList = Class(TJSBinary); // A->first statement, B->next in list, chained. + TJSVariableDeclarationList = Class(TJSBinary); + TJSWithStatement = Class(TJSBinary); // A-> with expression, B->statement(s) + TJSLogicalOrExpression = Class (TJSBinary); + TJSLogicalAndExpression = Class (TJSBinary); + TJSBitwiseAndExpression = Class (TJSBinary); + TJSBitwiseOrExpression = Class (TJSBinary); + TJSBitwiseXOrExpression = Class (TJSBinary); + TJSEqualityExpression = Class (TJSBinary); + TJSEqualityExpressionEQ = Class(TJSEqualityExpression); + TJSEqualityExpressionNE = Class(TJSEqualityExpression); + TJSEqualityExpressionSEQ = Class(TJSEqualityExpression); + TJSEqualityExpressionSNE = Class(TJSEqualityExpression); + TJSRelationalExpression = Class(TJSBinary); + TJSRelationalExpressionLT = Class(TJSRelationalExpression); + TJSRelationalExpressionGT = Class(TJSRelationalExpression); + TJSRelationalExpressionLE = Class(TJSRelationalExpression); + TJSRelationalExpressionGE = Class(TJSRelationalExpression); + TJSRelationalExpressionIn = Class(TJSRelationalExpression); + TJSRelationalExpressionInstanceOf = Class(TJSRelationalExpression); + TJSShiftExpression = Class(TJSBinary); + TJSLShiftExpression = Class(TJSShiftExpression); + TJSRShiftExpression = Class(TJSShiftExpression); + TJSURShiftExpression = Class(TJSShiftExpression); + TJSAdditiveExpression = Class(TJSBinary); + TJSAdditiveExpressionPlus = Class(TJSAdditiveExpression); + TJSAdditiveExpressionMinus = Class(TJSAdditiveExpression); + TJSMultiplicativeExpression = Class(TJSBinary); + TJSMultiplicativeExpressionMul = Class(TJSMultiplicativeExpression); + TJSMultiplicativeExpressionDiv = Class(TJSMultiplicativeExpression); + TJSMultiplicativeExpressionMod = Class(TJSMultiplicativeExpression); + TJSCommaExpression = Class(TJSBinary); + + { TJSConditionalExpression } + + TJSConditionalExpression = Class(TJSElement) + private + FA: TJSElement; + FB: TJSElement; + FC: TJSElement; + Public + Destructor Destroy; override; + Property A : TJSElement Read FA Write FA; + Property B : TJSElement Read FB Write FB; + Property C : TJSElement Read FC Write FC; + end; + + { TJSAssignStatement } + + TJSAssignStatement = Class(TJSElement) + private + FExpr: TJSElement; + FLHS: TJSElement; + Public + Destructor Destroy; override; + Property Expr : TJSElement Read FExpr Write FExpr; + Property LHS : TJSElement Read FLHS Write FLHS; + end; + + TJSSimpleAssignStatement = Class(TJSAssignStatement); + TJSMulEqAssignStatement = Class(TJSAssignStatement); + TJSDivEqAssignStatement = Class(TJSAssignStatement); + TJSModEqAssignStatement = Class(TJSAssignStatement); + TJSAddEqAssignStatement = Class(TJSAssignStatement); + TJSSubEqAssignStatement = Class(TJSAssignStatement); + TJSLShiftEqAssignStatement = Class(TJSAssignStatement); + TJSRShiftEqAssignStatement = Class(TJSAssignStatement); + TJSURShiftEqAssignStatement = Class(TJSAssignStatement); + TJSANDEqAssignStatement = Class(TJSAssignStatement); + TJSOREqAssignStatement = Class(TJSAssignStatement); + TJSXOREqAssignStatement = Class(TJSAssignStatement); + + { TJSVarDeclaration } + + TJSVarDeclaration = Class(TJSElement) + private + FInit: TJSElement; + FName: String; + Public + Destructor Destroy; override; + Property Name : String Read FName Write FName; + Property Init : TJSElement Read FInit Write FInit; + end; + + { TJSIfStatement } + + TJSIfStatement = Class(TJSElement) + private + FBFalse: TJSElement; + FBTrue: TJSElement; + FCond: TJSElement; + Public + Destructor Destroy; override; + Property Cond : TJSElement Read FCond Write FCond; + Property btrue : TJSElement Read FBTrue Write FBTrue; + Property bfalse : TJSElement Read FBFalse Write FBFalse; + end; + + { TJSWhileStatement } + + { TJSTargetStatement } + + TJSTargetStatement = Class(TJSElement) + private + FTarget: Cardinal; + Public + Property Target : Cardinal Read FTarget Write FTarget; + end; + + { TJSBodyStatement } + + TJSBodyStatement = Class(TJSTargetStatement) + private + FBody: TJSElement; + Public + Destructor Destroy; override; + Property body : TJSElement Read FBody Write FBody; + end; + + { TJSCondLoopStatement } + + TJSCondLoopStatement = Class(TJSBodyStatement) + private + FCond: TJSElement; + Public + Destructor Destroy; override; + Property Cond : TJSElement Read FCond Write FCond; + end; + + TJSWhileStatement = Class(TJSCondLoopStatement) + end; + + { TJSForStatement } + + TJSForStatement = Class(TJSCondLoopStatement) + private + FIncr: TJSElement; + FInit: TJSElement; + Public + Destructor Destroy; override; + Property Incr : TJSElement Read FIncr Write FIncr; + Property Init : TJSElement Read FInit Write FInit; + end; + + { TJSForInStatement } + + TJSForInStatement = Class(TJSBodyStatement) + private + FLhs: TJSElement; + FList: TJSElement; + Public + Destructor Destroy; override; + Property LHS : TJSElement Read FLHS Write FLHS; + Property List : TJSElement Read FList Write FList; + end; + + TJSContinueStatement = Class(TJSTargetStatement); + + TJSBreakStatement = Class(TJSTargetStatement); + + { TJSReturn } + + TJSReturnStatement = Class(TJSElement) + private + FExpr: TJSElement; + Public + Destructor Destroy; override; + Property Expr : TJSElement Read FExpr Write FExpr; + end; + + { TJSCaseElement } + + TJSCaseElement = Class(TCollectionItem) + private + FBody: TJSElement; + FExpr: TJSelement; + Public + Destructor Destroy; override; + Property Expr : TJSelement Read FExpr Write FExpr; + Property Body : TJSElement Read FBody Write FBody; + end; + + { TJSCaseElements } + + TJSCaseElements = Class(TCollection) + private + function GetC(AIndex : Integer): TJSCaseElement; + procedure SetC(AIndex : Integer; const AValue: TJSCaseElement); + Public + Function AddCase : TJSCaseElement; + Property Cases[AIndex : Integer] : TJSCaseElement Read GetC Write SetC; + end; + + { TJSSwitch } + + TJSSwitchStatement = Class(TJSTargetStatement) + private + FCases: TJSCaseElements; + FCond: TJSelement; + FDefault: TJSCaseElement; + Public + Constructor Create(ALine,ARow : Integer; const ASource : String = ''); override; + Destructor Destroy; override; + Property Cond : TJSelement Read FCond Write FCond; + Property Cases : TJSCaseElements Read FCases; + Property TheDefault : TJSCaseelement Read FDefault Write FDefault; + end; + + { TJSLabeledStatement } + + TJSLabeledStatement = Class(TJSUnary) + private + FTarget: Integer; + Public + Property target: Integer Read FTarget Write FTarget; + end; + + { TJSTryStatement } + + TJSTryStatement = Class(TJSElement) + private + FBCatch: TJSElement; + FBFinally: TJSElement; + FBlock: TJSElement; + FIdent: TJSString; + Public + Destructor Destroy; override; + Property Block : TJSElement Read FBlock Write FBlock; + Property BCatch : TJSElement Read FBCatch Write FBCatch; + Property BFinally : TJSElement Read FBFinally Write FBFinally; + Property Ident : TJSString Read FIdent Write FIDent; + end; + + TJSTryCatchFinallyStatement = Class(TJSTryStatement); + TJSTryCatchStatement = Class(TJSTryStatement); + TJSTryFinallyStatement = Class(TJSTryStatement); + + + { TJSFunction } + + TJSFunctionDeclarationStatement = Class(TJSelement) + private + FFuncDef: TJSFuncDef; + Public + Destructor Destroy; override; + Property AFunction : TJSFuncDef Read FFuncDef Write FFuncDef; + end; + + { TJSFunctionBody } + + TJSFunctionBody = Class(TJSUnary) + private + FisProgram: Boolean; + Public + Property isProgram : Boolean Read FisProgram Write FIsProgram; + end; + + { TJSElementNode } + + TJSElementNode = Class(TCollectionItem) + private + FNode: TJSElement; + Public + Destructor Destroy; override; + Property Node : TJSElement Read FNode Write FNode; + end; + + { TJSElementNodes } + + TJSElementNodes = Class(TCollection) + private + function GetN(AIndex : Integer): TJSElementNode; + procedure SetN(AIndex : Integer; const AValue: TJSElementNode); + Public + Function AddNode : TJSElementNode; + Property Nodes[AIndex : Integer] : TJSElementNode Read GetN Write SetN; default; + end; + + { TJSSourceElements } + TJSSourceElements = Class(TJSElement) + private + FFunctions: TJSElementNodes; + FStatements: TJSElementNodes; + FVars: TJSElementNodes; + Public + Constructor Create(ALine,ARow : Integer; const ASource : String = ''); override; + Destructor Destroy; override; + Property Statements : TJSElementNodes Read FStatements; + Property functions : TJSElementNodes Read FFunctions; + Property Vars : TJSElementNodes Read FVars; + end; + + +implementation + +{ TJSElement } + +constructor TJSElement.Create(ALine, ARow: Integer; Const ASource: String = ''); +begin + FLine:=ALine; + FRow:=ARow; + FSource:=ASource; +end; + +{ TJSRegularExpressionLiteral } + +function TJSRegularExpressionLiteral.GetA(AIndex : integer): TJSValue; +begin + Result:=FArgv[AIndex]; +end; + +procedure TJSRegularExpressionLiteral.SetA(AIndex : integer; + const AValue: TJSValue); +begin + FArgv[AIndex]:=Avalue; +end; + +constructor TJSRegularExpressionLiteral.Create(ALine, ARow: Integer; + const ASource: String); +begin + inherited Create(ALine, ARow, ASource); + FPattern:=TJSValue.Create; + FPatternFlags:=TJSValue.Create; +end; + +destructor TJSRegularExpressionLiteral.Destroy; +begin + FreeAndNil(FPattern); + FreeAndNil(FPatternFlags); + Inherited Destroy; +end; + +{ TJSArrayLiteralElements } + +function TJSArrayLiteralElements.GetE(AIndex : Integer): TJSArrayLiteralElement; +begin + Result:=TJSArrayLiteralElement(Items[AIndex]); +end; + +procedure TJSArrayLiteralElements.SetE(AIndex : Integer; + const AValue: TJSArrayLiteralElement); +begin + Items[AIndex]:=AValue; +end; + +function TJSArrayLiteralElements.AddElement: TJSArrayLiteralElement; +begin + Result:=TJSArrayLiteralElement(Add); +end; + +{ TJSArrayLiteral } + +constructor TJSArrayLiteral.Create(ALine, ARow: Integer; Const ASource: String = ''); +begin + inherited Create(ALine, ARow, ASource); + FElements:=TJSArrayLiteralElements.Create(TJSArrayLiteralElement); +end; + +destructor TJSArrayLiteral.Destroy; +begin + FreeAndNil(FElements); + inherited Destroy; +end; + +{ TJSObjectLiteralElements } + +function TJSObjectLiteralElements.GetE(AIndex : Integer + ): TJSObjectLiteralElement; +begin + Result:=TJSObjectLiteralElement(Items[AIndex]); +end; + +procedure TJSObjectLiteralElements.SetE(AIndex : Integer; + const AValue: TJSObjectLiteralElement); +begin + Items[AIndex]:=AValue; +end; + +function TJSObjectLiteralElements.AddElement: TJSObjectLiteralElement; +begin + Result:=TJSObjectLiteralElement(Add); +end; + +{ TJSObjectLiteral } + +constructor TJSObjectLiteral.Create(ALine, ARow: Integer; const ASource: String = ''); +begin + inherited Create(ALine, ARow, ASource); + FElements:=TJSObjectLiteralElements.Create(TJSObjectLiteralElement); +end; + +destructor TJSObjectLiteral.Destroy; +begin + FreeAndNil(FElements); + inherited Destroy; +end; + +{ TJSObjectLiteralElement } + +destructor TJSObjectLiteralElement.Destroy; +begin + FreeAndNil(Fexpr); + inherited Destroy; +end; + +{ TJSArrayLiteralElement } + +destructor TJSArrayLiteralElement.Destroy; +begin + FreeAndNil(Fexpr); + inherited Destroy; +end; + +{ TJSNewMemberExpression } + +destructor TJSNewMemberExpression.Destroy; +begin + FreeAndNil(FArgs); + inherited Destroy; +end; + +{ TJSMemberExpression } + +destructor TJSMemberExpression.Destroy; +begin + FreeAndNil(FMExpr); + inherited Destroy; +end; + +{ TJSCallExpression } + +destructor TJSCallExpression.Destroy; +begin + FreeAndNil(FExpr); + FreeAndNil(FArgs); + inherited Destroy; +end; + +{ TJSUnary } + +destructor TJSUnary.Destroy; +begin + FreeAndNil(FA); + inherited Destroy; +end; + +{ TJSBinary } + +destructor TJSBinary.Destroy; +begin + FreeAndNil(FB); + FreeAndNil(FA); + inherited Destroy; +end; + +{ TJSConditionalExpression } + +destructor TJSConditionalExpression.Destroy; +begin + FreeAndNil(FB); + FreeAndNil(FA); + FreeAndNil(FC); + inherited Destroy; +end; + +{ TJSAssign } + +destructor TJSAssignStatement.Destroy; +begin + FreeAndNil(FLHS); + FreeAndNil(FExpr); + inherited Destroy; +end; + +{ TJSVarDeclaration } + + +destructor TJSVarDeclaration.Destroy; +begin + FreeAndNil(FInit); + inherited Destroy; +end; + +{ TJSIfStatement } + +destructor TJSIfStatement.Destroy; +begin + FreeAndNil(FCond); + FreeAndNil(FBTrue); + FreeAndNil(FBFalse); + inherited Destroy; +end; + +{ TJSBodyStatement } + +destructor TJSBodyStatement.Destroy; +begin + FreeAndNil(FBody); + inherited Destroy; +end; + +{ TJSCondLoopStatement } + +destructor TJSCondLoopStatement.Destroy; +begin + FreeAndNil(FCond); + inherited Destroy; +end; + +{ TJSForStatement } + +destructor TJSForStatement.Destroy; +begin + FreeAndNil(FIncr); + FreeAndNil(FInit); + inherited Destroy; +end; + +{ TJSForInStatement } + +destructor TJSForInStatement.Destroy; +begin + FreeAndNil(FList); + FreeAndNil(FLHS); + inherited Destroy; +end; + + +{ TJSReturn } + +destructor TJSReturnStatement.Destroy; +begin + FreeAndNil(FExpr); + inherited Destroy; +end; + +{ TJSCaseElement } + +destructor TJSCaseElement.Destroy; +begin + FreeAndNil(FExpr); + FreeAndNil(FBody); + inherited Destroy; +end; + +{ TJSSwitch } + +constructor TJSSwitchStatement.Create(ALine, ARow: Integer; const ASource: String); +begin + inherited Create(ALine, ARow, ASource); + FCases:=TJSCaseElements.Create(TJSCaseElement); +end; + +destructor TJSSwitchStatement.Destroy; +begin + FreeAndNil(FCases); + FreeAndNil(FDefault); + FreeAndNil(FCond); + inherited Destroy; +end; + +{ TJSCaseElements } + +function TJSCaseElements.GetC(AIndex : Integer): TJSCaseElement; +begin + Result:=TJSCaseElement(Items[AIndex]); +end; + +procedure TJSCaseElements.SetC(AIndex : Integer; const AValue: TJSCaseElement); +begin + Items[AIndex]:=AValue; +end; + +function TJSCaseElements.AddCase: TJSCaseElement; +begin + Result:=TJSCaseElement(Add); +end; + +{ TJSTryStatement } + +destructor TJSTryStatement.Destroy; +begin + FreeAndNil(FBlock); + FreeAndNil(FBCatch); + FreeAndNil(FBFinally); + inherited Destroy; +end; + +{ TJSSourceElements } + +constructor TJSSourceElements.Create(ALine, ARow: Integer; const ASource: String + ); +begin + inherited Create(ALine, ARow, ASource); + FStatements:=TJSElementNodes.Create(TJSElementNode); + FFunctions:=TJSElementNodes.Create(TJSElementNode); + FVars:=TJSElementNodes.Create(TJSElementNode); +end; + +destructor TJSSourceElements.Destroy; +begin + FreeAndNil(FStatements); + FreeAndNil(FFunctions); + FreeAndNil(FVars); + inherited Destroy; +end; + +{ TJSElementNodes } + +function TJSElementNodes.GetN(AIndex : Integer): TJSElementNode; +begin + Result:=TJSElementNode(Items[Aindex]) +end; + +procedure TJSElementNodes.SetN(AIndex : Integer; const AValue: TJSElementNode); +begin + Items[AIndex]:=Avalue; +end; + +function TJSElementNodes.AddNode: TJSElementNode; +begin + Result:=TJSElementNode(Add); +end; + +{ TJSFunction } + +destructor TJSFunctionDeclarationStatement.Destroy; +begin + FreeAndNil(FFuncDef); + inherited Destroy; +end; + +{ TJSElementNode } + +destructor TJSElementNode.Destroy; +begin + //FreeAndNil(FNode); + inherited Destroy; +end; + +{ TJSFuncDef } + +procedure TJSFuncDef.SetParams(const AValue: TStrings); +begin + if FParams=AValue then exit; + FParams.Assign(AValue); +end; + +constructor TJSFuncDef.Create; +begin + FParams:=TStringList.Create; +end; + +destructor TJSFuncDef.Destroy; +begin + FreeAndNil(FParams); + inherited Destroy; +end; + +{ TJSBracketMemberExpression } + +destructor TJSBracketMemberExpression.Destroy; +begin + FreeAndNil(FName); + inherited Destroy; +end; + +{ TJSLiteral } + +constructor TJSLiteral.Create(ALine, ARow: Integer; const ASource: String); +begin + FValue:=TJSValue.Create; + inherited Create(ALine, ARow, ASource); +end; + +destructor TJSLiteral.Destroy; +begin + FreeAndNil(FValue); + Inherited; +end; + +end. + diff --git a/packages/fcl-js/tests/tcparser.pp b/packages/fcl-js/tests/tcparser.pp new file mode 100644 index 0000000000..dfca6990f1 --- /dev/null +++ b/packages/fcl-js/tests/tcparser.pp @@ -0,0 +1,2311 @@ +unit tcparser; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, fpcunit, testutils, testregistry, jsParser, jstree, jsbase; + +type + + { TTestJSParser } + + TTestJSParser= class(TTestCase) + Private + FSource : TStringStream; + FParser : TJSParser; + FSE : TJSSourceElements; + FToFree: TJSElement; + protected + procedure SetUp; override; + procedure TearDown; override; + Procedure CreateParser(Const ASource : string); + Procedure CheckClass(E : TJSElement; C : TJSElementClass); + Procedure AssertEquals(Const AMessage : String; Expected, Actual : TJSType); overload; + Function GetSourceElements : TJSSourceElements; + Function GetVars : TJSElementNodes; + Function GetStatements : TJSElementNodes; + Function GetFunctions : TJSElementNodes; + Function GetFirstStatement : TJSElement; + Function GetFirstVar : TJSElement; + Function GetExpressionStatement : TJSExpressionStatement; + published + procedure TestEmpty; + procedure TestSimple; + procedure TestSimpleExpressionNumericalLiteral; + procedure TestSimpleExpressionStringLiteral; + procedure TestSimpleExpressionBooleanLiteralFalse; + procedure TestSimpleExpressionBooleanLiteralTrue; + procedure TestSimpleExpressionIdentifier; + procedure TestSimpleExpressionNull; + procedure TestAssignExpressionNumerical; + procedure TestAssignExpressionNull; + procedure TestAssignExpressionString; + procedure TestAssignExpressionBooleanFalse; + procedure TestAssignExpressionBooleanTrue; + procedure TestAssignExpressionIdent; + procedure TestAssignExpressionPlus; + procedure TestAssignExpressionMinus; + procedure TestAssignExpressionDiv; + procedure TestAssignExpressionMul; + procedure TestAssignExpressionMod; + procedure TestAssignExpressionAnd; + procedure TestAssignExpressionOr; + procedure TestAssignExpressionXOr; + procedure TestAssignExpressionLShift; + procedure TestAssignExpressionRShift; + procedure TestAssignExpressionURShift; + procedure TestExpressionPlus; + procedure TestExpressionSub; + procedure TestExpressionMul; + procedure TestExpressionDiv; + procedure TestExpressionMod; + procedure TestExpressionLShift; + procedure TestExpressionRShift; + procedure TestExpressionURShift; + procedure TestExpressionPostPlusPlus; + procedure TestExpressionPostMinusMinus; + procedure TestExpressionPreMinusMinus; + procedure TestExpressionPrePlusPlus; + procedure TestExpressionPrecedenceMulPlus; + procedure TestExpressionPrecedencePlusMul; + procedure TestExpressionPrecedenceMulMinus; + procedure TestExpressionPrecedenceMinusMul; + procedure TestExpressionPrecedenceDivPlus; + procedure TestExpressionPrecedencePlusDiv; + procedure TestExpressionPrecedenceModPlus; + procedure TestExpressionPrecedencePlusMod; + procedure TestExpressionPrecedencePlusPostPlusPlus; + procedure TestExpressionPrecedencePlusPostMinusMinus; + procedure TestExpressionPrecedenceMulPostMinusMinus; + procedure TestExpressionPrecedenceMulPostPlusPlus; + procedure TestExpressionPrecedenceMulPreMinusMinus; + procedure TestExpressionPrecedenceMulPrePlusPlus; + procedure TestExpressionPrecedencePlusPreMinusMinus; + procedure TestExpressionPrecedencePlusPrePlusPlus; + procedure TestExpressionPrecedencePlusInv; + procedure TestExpressionPrecedenceMulInv; + procedure TestExpressionPrecedenceMulNot; + procedure TestExpressionPrecedencePlusNot; + procedure TestExpressionPrecedenceBraceMulPlus; + procedure TestExpressionPrecedenceBracePlusMul; + procedure TestExpressionFunction; + procedure TestFunctionCallNoArgs; + procedure TestFunctionCallOneArg; + procedure TestFunctionCallTwoArgs; + procedure TestArrayExpressionNumericalArgs; + procedure TestArrayExpressionStringArgs; + procedure TestArrayExpressionIdentArgs; + Procedure TestVarDeclarationSimple; + procedure TestVarDeclarationDouble; + procedure TestVarDeclarationSimpleInit; + procedure TestVarDeclarationDoubleInit; + procedure TestBlockEmpty; + procedure TestBlockEmptyStatement; + procedure TestBlockSimpleStatement; + procedure TestFunctionDeclarationEmpty; + procedure TestFunctionDeclarationWithArgs; + procedure TestFunctionDeclarationWithBody; + procedure TestIfSimple; + procedure TestIfElseSimple; + procedure TestIfEmptyBlock; + procedure TestIfEmptyBlockElse; + procedure TestWhileSimple; + procedure TestWhileBlock; + procedure TestDoWhileSimple; + procedure TestDoWhileBlock; + procedure TestForEmpty; + procedure TestForEmptyBody; + procedure TestForSimpleBody; + procedure TestTryCatch; + procedure TestTryCatchFinally; + procedure TestTryFinally; + procedure TestThrow; + procedure TestReturn; + end; + +implementation + +uses typinfo; + +procedure TTestJSParser.AssertEquals(const AMessage: String; Expected, + Actual: TJSType); + +Var + NE,NA : String; + +begin + NE:=GetEnumName(TypeInfo(TJSType),Ord(Expected)); + NA:=GetEnumName(TypeInfo(TJSType),Ord(Actual)); + AssertEquals(AMessage,NE,NA); +end; + +function TTestJSParser.GetFirstStatement: TJSElement; + +Var + E : TJSElementNodes; + N : TJSElement; + X : TJSExpressionStatement; + +begin + E:=GetStatements; + AssertNotNull('Have statements',E); + AssertEquals('1 statement',1,E.Count); + Result:=E.Nodes[0].Node; + AssertNotNull('First statement assigned',Result); +end; + +function TTestJSParser.GetFirstVar: TJSElement; +Var + E : TJSElementNodes; + N : TJSElement; + X : TJSExpressionStatement; +begin + E:=GetVars; + AssertNotNull('Have statements',E); + Writeln('Count : ',E.Count); + If (E.Count=0) then + Fail('Zero variables defined'); + Result:=E.Nodes[0].Node; + AssertNotNull('First variable declaration',Result); +end; + +function TTestJSParser.GetExpressionStatement: TJSExpressionStatement; + +Var + N : TJSElement; + X : TJSExpressionStatement; + +begin + N:=GetFirstStatement; + CheckClass(N,TJSExpressionStatement); + Result:=TJSExpressionStatement(N); +end; + + +procedure TTestJSParser.TestSimple; + +Var + E : TJSElementNodes; + N : TJSElement; + X : TJSExpressionStatement; + +begin + CreateParser('1;'); + E:=GetStatements; + AssertNotNull('Have statements',E); + AssertEquals('1 statement',1,E.Count); + N:=E.Nodes[0].Node; + AssertNotNull('First statement assigned',N); + AssertNotNull('First statement assigned',N); + CheckClass(N,TJSExpressionStatement); + X:=TJSExpressionStatement(N); + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSLiteral); +end; + +procedure TTestJSParser.TestSimpleExpressionNumericalLiteral; +Var + X : TJSExpressionStatement; + +begin + CreateParser('1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSLiteral); + AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(X.A).Value.ValueType); + AssertEquals('Expression value correct', 1.0,TJSLiteral(X.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestSimpleExpressionStringLiteral; + +Var + X : TJSExpressionStatement; + +begin + CreateParser('"string";'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSLiteral); + AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value); + AssertEquals('Expression value type correct', jstString,TJSLiteral(X.A).Value.ValueType); + AssertEquals('Expression value correct', 'string',TJSLiteral(X.A).Value.AsString); +end; + +procedure TTestJSParser.TestSimpleExpressionBooleanLiteralFalse; + +Var + X : TJSExpressionStatement; + +begin + CreateParser('false;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSLiteral); + AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value); + AssertEquals('Expression value type correct', jstBoolean,TJSLiteral(X.A).Value.ValueType); + AssertEquals('Expression value correct', False, TJSLiteral(X.A).Value.AsBoolean); +end; + +procedure TTestJSParser.TestSimpleExpressionIdentifier; + +Var + X : TJSExpressionStatement; + +begin + CreateParser('Something;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSPrimaryExpressionIdent); + AssertEquals('Expression value assigned','Something',TJSPrimaryExpressionIdent(X.A).AString); +end; + +procedure TTestJSParser.TestSimpleExpressionNull; + +Var + X : TJSExpressionStatement; +begin + CreateParser('null;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSLiteral); + AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value); + AssertEquals('Expression value type correct', jstNull,TJSLiteral(X.A).Value.ValueType); + AssertEquals('Expression value correct', True, TJSLiteral(X.A).Value.IsNull); +end; + +procedure TTestJSParser.TestAssignExpressionNumerical; + +Var + X : TJSExpressionStatement; + SA : TJSSimpleAssignStatement; +begin + CreateParser('a=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSSimpleAssignStatement); + SA:=TJSSimpleAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionString; + +Var + X : TJSExpressionStatement; + SA : TJSSimpleAssignStatement; +begin + CreateParser('a="string";'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSSimpleAssignStatement); + SA:=TJSSimpleAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstString,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 'string', TJSLiteral(SA.Expr).Value.AsString); +end; + +procedure TTestJSParser.TestAssignExpressionBooleanFalse; + +Var + X : TJSExpressionStatement; + SA : TJSSimpleAssignStatement; +begin + CreateParser('a=false;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSSimpleAssignStatement); + SA:=TJSSimpleAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstBoolean,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', False, TJSLiteral(SA.Expr).Value.AsBoolean); +end; + +procedure TTestJSParser.TestAssignExpressionBooleanTrue; +Var + X : TJSExpressionStatement; + SA : TJSSimpleAssignStatement; +begin + CreateParser('a=true;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSSimpleAssignStatement); + SA:=TJSSimpleAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstBoolean,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', True, TJSLiteral(SA.Expr).Value.AsBoolean); +end; + +procedure TTestJSParser.TestAssignExpressionNull; + +Var + X : TJSExpressionStatement; + SA : TJSSimpleAssignStatement; +begin + CreateParser('a=null;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSSimpleAssignStatement); + SA:=TJSSimpleAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNull,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', True, TJSLiteral(SA.Expr).Value.IsNull); +end; + +procedure TTestJSParser.TestAssignExpressionIdent; +Var + X : TJSExpressionStatement; + SA : TJSSimpleAssignStatement; +begin + CreateParser('a=b;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSSimpleAssignStatement); + SA:=TJSSimpleAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSPrimaryExpressionIdent); + AssertEquals('Expression value type correct', 'b',TJSPrimaryExpressionIdent(SA.Expr).AString); +end; + +procedure TTestJSParser.TestAssignExpressionPlus; + +Var + X : TJSExpressionStatement; + SA : TJSAddEqAssignStatement; + +begin + CreateParser('a+=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAddEqAssignStatement); + SA:=TJSAddEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionMinus; + +Var + X : TJSExpressionStatement; + SA : TJSSubEqAssignStatement; + +begin + CreateParser('a-=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSSubEqAssignStatement); + SA:=TJSSubEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionMul; + +Var + X : TJSExpressionStatement; + SA : TJSMulEqAssignStatement; + +begin + CreateParser('a*=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMulEqAssignStatement); + SA:=TJSMulEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionDiv; + +Var + X : TJSExpressionStatement; + SA : TJSDivEqAssignStatement; + +begin + CreateParser('a/=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSDivEqAssignStatement); + SA:=TJSDivEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionMod; + +Var + X : TJSExpressionStatement; + SA : TJSModEqAssignStatement; + +begin + CreateParser('a%=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSModEqAssignStatement); + SA:=TJSModEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionAnd; + +Var + X : TJSExpressionStatement; + SA : TJSAndEqAssignStatement; + +begin + CreateParser('a&=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAndEqAssignStatement); + SA:=TJSAndEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionOr; + +Var + X : TJSExpressionStatement; + SA : TJSOrEqAssignStatement; + +begin + CreateParser('a|=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSOrEqAssignStatement); + SA:=TJSOrEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionXOr; + +Var + X : TJSExpressionStatement; + SA : TJSXOrEqAssignStatement; + +begin + CreateParser('a^=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSXOrEqAssignStatement); + SA:=TJSXOrEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionLShift; + +Var + X : TJSExpressionStatement; + SA : TJSLShiftEqAssignStatement; + +begin + CreateParser('a<<=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSLShiftEqAssignStatement); + SA:=TJSLShiftEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionRShift; + +Var + X : TJSExpressionStatement; + SA : TJSRShiftEqAssignStatement; + +begin + CreateParser('a>>=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSRShiftEqAssignStatement); + SA:=TJSRShiftEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestAssignExpressionURShift; + +Var + X : TJSExpressionStatement; + SA : TJSURShiftEqAssignStatement; + +begin + CreateParser('a>>>=1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSURShiftEqAssignStatement); + SA:=TJSURShiftEqAssignStatement(X.A); + AssertNotNull('Assignment LHS assigned',SA.LHS); + CheckClass(SA.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).AString); + AssertNotNull('Assignment Expression assigned',SA.Expr); + CheckClass(SA.EXPR,TJSLiteral); + AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType); + AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPlus; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionPlus; + +begin + CreateParser('1+2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSLiteral); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); + AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionSub; +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionMinus; + +begin + CreateParser('1 - 2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionMinus); + E:=TJSAdditiveExpressionMinus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSLiteral); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); + AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionMul; + +Var + X : TJSExpressionStatement; + E : TJSMultiplicativeExpressionMul; + +begin + CreateParser('1*2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSLiteral); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); + AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionDiv; +Var + X : TJSExpressionStatement; + E : TJSMultiplicativeExpressionDiv; + +begin + CreateParser('1/2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionDiv); + E:=TJSMultiplicativeExpressionDiv(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSLiteral); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); + AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionMod; +Var + X : TJSExpressionStatement; + E : TJSMultiplicativeExpressionMod; + +begin + CreateParser('1%2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMod); + E:=TJSMultiplicativeExpressionMod(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSLiteral); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); + AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionLShift; +Var + X : TJSExpressionStatement; + E : TJSLShiftExpression; + +begin + CreateParser('1 << 2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSLShiftExpression); + E:=TJSLShiftExpression(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSLiteral); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); + AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionRShift; +Var + X : TJSExpressionStatement; + E : TJSRShiftExpression; + +begin + CreateParser('1 >> 2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSRShiftExpression); + E:=TJSRShiftExpression(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSLiteral); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); + AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionURShift; +Var + X : TJSExpressionStatement; + E : TJSURShiftExpression; + +begin + CreateParser('1 >>> 2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSURShiftExpression); + E:=TJSURShiftExpression(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSLiteral); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); + AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPostPlusPlus; +Var + X : TJSExpressionStatement; + E : TJSUnaryPostPlusPlusExpression; + +begin + CreateParser('1++;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSUnaryPostPlusPlusExpression); + E:=TJSUnaryPostPlusPlusExpression(X.A); + AssertNotNull('Expression left operand assigned',E.A); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Expression operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPostMinusMinus; +Var + X : TJSExpressionStatement; + E : TJSUnaryPostMinusMinusExpression; + +begin + CreateParser('1--;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSUnaryPostMinusMinusExpression); + E:=TJSUnaryPostMinusMinusExpression(X.A); + AssertNotNull('Expression left operand assigned',E.A); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Expression operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrePlusPlus; + +Var + X : TJSExpressionStatement; + E : TJSUnaryPrePlusPlusExpression; + +begin + CreateParser('++1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSUnaryPrePlusPlusExpression); + E:=TJSUnaryPrePlusPlusExpression(X.A); + AssertNotNull('Expression left operand assigned',E.A); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Expression operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); +end; + + +procedure TTestJSParser.TestExpressionPreMinusMinus; + +Var + X : TJSExpressionStatement; + E : TJSUnaryPreMinusMinusExpression; + +begin + CreateParser('--1;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSUnaryPreMinusMinusExpression); + E:=TJSUnaryPreMinusMinusExpression(X.A); + AssertNotNull('Expression left operand assigned',E.A); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Expression operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Expression operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceMulPlus; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionPlus; + R : TJSMultiplicativeExpressionMul; +begin + CreateParser('2 * 3 + 4;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSMultiplicativeExpressionMul); + R:=TJSMultiplicativeExpressionMul(E.A); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + AssertNotNull('Multiplication right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertEquals('Multiplication right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Expression right operand value correct', 4.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceBraceMulPlus; + +Var + X : TJSExpressionStatement; + E : TJSMultiplicativeExpressionMul; + R : TJSAdditiveExpressionPlus; + +begin + CreateParser('2 * (3 + 4);'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSAdditiveExpressionPlus); + R:=TJSAdditiveExpressionPlus(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + AssertNotNull('Multiplication right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(E.A).Value.AsNumber); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(R.B).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Addition right operand value correct', 4.0,TJSLiteral(R.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceBracePlusMul; + +Var + X : TJSExpressionStatement; + E : TJSMultiplicativeExpressionMul; + R : TJSAdditiveExpressionPlus; + +begin + CreateParser('(3 + 4)*2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSAdditiveExpressionPlus); + R:=TJSAdditiveExpressionPlus(E.A); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + AssertNotNull('Multiplication right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(E.B).Value.AsNumber); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(R.B).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Addition right operand value correct', 4.0,TJSLiteral(R.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionFunction; +Var + X : TJSExpressionStatement; + A : TJSSimpleAssignStatement; +begin + CreateParser('a = function () {};'); + X:=GetExpressionStatement; + CheckClass(X.A,TJSSimpleAssignStatement); + A:=TJSSimpleAssignStatement(X.A); + AssertNotNull('Have left operand',A.LHS); + CheckClass(A.LHS,TJSPrimaryExpressionIdent); + AssertEquals('Correct name for assignment LHS ','a',TJSPrimaryExpressionIdent(A.LHS).AString); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusMul; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionPlus; + R : TJSMultiplicativeExpressionMul; +begin + CreateParser('4 + 2 * 3;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSMultiplicativeExpressionMul); + R:=TJSMultiplicativeExpressionMul(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + AssertNotNull('Multiplication right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertEquals('Multiplication right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber); + AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceMulMinus; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionMinus; + R : TJSMultiplicativeExpressionMul; + +begin + CreateParser('2 * 3 - 4;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionMinus); + E:=TJSAdditiveExpressionMinus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSMultiplicativeExpressionMul); + R:=TJSMultiplicativeExpressionMul(E.A); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + AssertNotNull('Multiplication right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertEquals('Multiplication right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber); + AssertNotNull('subtraction right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('subtraction right operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('subtraction right operand value correct', 4.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceMinusMul; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionMinus; + R : TJSMultiplicativeExpressionMul; +begin + CreateParser('4 - 2 * 3;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionMinus); + E:=TJSAdditiveExpressionMinus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSMultiplicativeExpressionMul); + R:=TJSMultiplicativeExpressionMul(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + AssertNotNull('Multiplication right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertEquals('Multiplication right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber); + AssertNotNull('Subtraction left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Subtraction left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Subtraction left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceDivPlus; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionPlus; + R : TJSMultiplicativeExpressionDiv; +begin + CreateParser('2 / 3 + 4;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSMultiplicativeExpressionDiv); + R:=TJSMultiplicativeExpressionDiv(E.A); + CheckClass(E.B,TJSLiteral); + AssertNotNull('Div left operand assigned',R.A); + AssertNotNull('Div right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Div left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Div left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertEquals('Div right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Div right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Addition right operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Addition right operand value correct', 4.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusDiv; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionPlus; + R : TJSMultiplicativeExpressionDiv; + +begin + CreateParser('4 + 2 / 3;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSMultiplicativeExpressionDiv); + R:=TJSMultiplicativeExpressionDiv(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Div left operand assigned',R.A); + AssertNotNull('Div right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Div left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Div left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertEquals('Div right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Div right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber); + AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceModPlus; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionPlus; + R : TJSMultiplicativeExpressionMod; +begin + CreateParser('2 % 3 + 4;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.A,TJSMultiplicativeExpressionMod); + R:=TJSMultiplicativeExpressionMod(E.A); + CheckClass(E.B,TJSLiteral); + AssertNotNull('mod left operand assigned',R.A); + AssertNotNull('mod right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('mod left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('mod left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertEquals('mod right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('mod right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(E.B).Value); + AssertEquals('Addition right operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType); + AssertEquals('Addition right operand value correct', 4.0,TJSLiteral(E.B).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusMod; + +Var + X : TJSExpressionStatement; + E : TJSAdditiveExpressionPlus; + R : TJSMultiplicativeExpressionMod; + +begin + CreateParser('4 + 2 % 3;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSMultiplicativeExpressionMod); + R:=TJSMultiplicativeExpressionMod(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Mod left operand assigned',R.A); + AssertNotNull('Mod right operand assigned',R.B); + CheckClass(R.A,TJSLiteral); + CheckClass(R.B,TJSLiteral); + AssertEquals('Mod left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Mod left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertEquals('Mod right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType); + AssertEquals('Mod right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusPostPlusPlus; + +Var + X : TJSExpressionStatement; + R : TJSUnaryPostPlusPlusExpression; + E : TJSAdditiveExpressionPlus; + +begin + CreateParser('4 + 2++;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryPostPlusPlusExpression); + R:=TJSUnaryPostPlusPlusExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('++ operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('++ operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('++ operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusPostMinusMinus; +Var + X : TJSExpressionStatement; + R : TJSUnaryPostMinusMinusExpression; + E : TJSAdditiveExpressionPlus; + +begin + CreateParser('4 + 2--;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryPostMinusMinusExpression); + R:=TJSUnaryPostMinusMinusExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('-- operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('-- operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('-- operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceMulPostPlusPlus; + +Var + X : TJSExpressionStatement; + R : TJSUnaryPostPlusPlusExpression; + E : TJSMultiplicativeExpressionMul; + +begin + CreateParser('4 * 2++;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryPostPlusPlusExpression); + R:=TJSUnaryPostPlusPlusExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('++operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('++ operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('++ operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Multiplication left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceMulPostMinusMinus; +Var + X : TJSExpressionStatement; + R : TJSUnaryPostMinusMinusExpression; + E : TJSMultiplicativeExpressionMul; + +begin + CreateParser('4 * 2--;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryPostMinusMinusExpression); + R:=TJSUnaryPostMinusMinusExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('-- operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('-- operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('-- operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Multiplication left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusPrePlusPlus; + +Var + X : TJSExpressionStatement; + R : TJSUnaryPrePlusPlusExpression; + E : TJSAdditiveExpressionPlus; + +begin + CreateParser('4 + ++2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryPrePlusPlusExpression); + R:=TJSUnaryPrePlusPlusExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('++ operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('++ operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusInv; + +Var + X : TJSExpressionStatement; + R : TJSUnaryInvExpression; + E : TJSAdditiveExpressionPlus; + +begin + CreateParser('4 + ~2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryInvExpression); + R:=TJSUnaryInvExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('inv operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('inv operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceMulInv; + +Var + X : TJSExpressionStatement; + R : TJSUnaryInvExpression; + E : TJSMultiplicativeExpressionMul; + +begin + CreateParser('4 * ~2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryInvExpression); + R:=TJSUnaryInvExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('Inv operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Inv operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Multiplication left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusNot; + +Var + X : TJSExpressionStatement; + R : TJSUnaryNotExpression; + E : TJSAdditiveExpressionPlus; + +begin + CreateParser('4 + !2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryNotExpression); + R:=TJSUnaryNotExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('Not operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Not operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestFunctionCallNoArgs; + +Var + X : TJSExpressionStatement; + C : TJSCallExpression; + +begin + CreateParser('abc();'); + X:=GetExpressionStatement; + CheckClass(X.A,TJSCallExpression); + C:=TJSCallExpression(X.A); + AssertEquals('No arguments',0,C.Args.Elements.Count); + AssertNotNull('Call function expression',C.Expr); + CheckClass(C.Expr,TJSPrimaryExpressionIdent); + AssertEquals('Function name correct','abc',TJSPrimaryExpressionIdent(C.Expr).AString); +end; + +procedure TTestJSParser.TestFunctionCallOneArg; + +Var + X : TJSExpressionStatement; + C : TJSCallExpression; + E : TJSelement; + +begin + CreateParser('abc(d);'); + X:=GetExpressionStatement; + CheckClass(X.A,TJSCallExpression); + C:=TJSCallExpression(X.A); + AssertNotNull('Call function expression',C.Expr); + CheckClass(C.Expr,TJSPrimaryExpressionIdent); + AssertEquals('Function name correct','abc',TJSPrimaryExpressionIdent(C.Expr).AString); + AssertEquals('1 argument',1,C.Args.Elements.Count); + E:=C.Args.Elements[0].Expr; + AssertNotNull('First argument expression',E); + CheckClass(E,TJSPrimaryExpressionIdent); + AssertEquals('First argument name correct','d',TJSPrimaryExpressionIdent(E).AString); +end; + +procedure TTestJSParser.TestFunctionCallTwoArgs; + +Var + X : TJSExpressionStatement; + C : TJSCallExpression; + E : TJSelement; + +begin + CreateParser('abc(d,e);'); + X:=GetExpressionStatement; + CheckClass(X.A,TJSCallExpression); + C:=TJSCallExpression(X.A); + AssertNotNull('Call function expression',C.Expr); + CheckClass(C.Expr,TJSPrimaryExpressionIdent); + AssertEquals('Function name correct','abc',TJSPrimaryExpressionIdent(C.Expr).AString); + AssertEquals('2 arguments',2,C.Args.Elements.Count); + E:=C.Args.Elements[0].Expr; + AssertNotNull('First argument expression',E); + CheckClass(E,TJSPrimaryExpressionIdent); + AssertEquals('First argument name correct','d',TJSPrimaryExpressionIdent(E).AString); + E:=C.Args.Elements[1].Expr; + AssertNotNull('Second argument expression',E); + CheckClass(E,TJSPrimaryExpressionIdent); + AssertEquals('Second argument name correct','e',TJSPrimaryExpressionIdent(E).AString); +end; + +procedure TTestJSParser.TestArrayExpressionNumericalArgs; +Var + X : TJSExpressionStatement; + B : TJSBracketMemberExpression; + +begin + CreateParser('A[1];'); + X:=GetExpressionStatement; + CheckClass(X.A,TJSBracketMemberExpression); + B:=TJSBracketMemberExpression(X.A); + CheckClass(B.Name,TJSLiteral); + AssertEquals('Member name operand type correct', jstNumber, TJSLiteral(B.Name).Value.ValueType); + AssertEquals('Member name operand value correct', 1.0, TJSLiteral(B.Name).Value.AsNumber); + CheckClass(B.Mexpr,TJSPrimaryExpressionIdent); + AssertEquals('Array name correct','A',TJSPrimaryExpressionIdent(B.Mexpr).AString); +end; + +procedure TTestJSParser.TestArrayExpressionStringArgs; +Var + X : TJSExpressionStatement; + B : TJSBracketMemberExpression; + +begin + CreateParser('A["propname"];'); + X:=GetExpressionStatement; + CheckClass(X.A,TJSBracketMemberExpression); + B:=TJSBracketMemberExpression(X.A); + CheckClass(B.Name,TJSLiteral); + AssertEquals('Member name operand type correct', jstString, TJSLiteral(B.Name).Value.ValueType); + AssertEquals('Member name operand value correct', 'propname', TJSLiteral(B.Name).Value.AsString); + CheckClass(B.Mexpr,TJSPrimaryExpressionIdent); + AssertEquals('Array name correct','A',TJSPrimaryExpressionIdent(B.Mexpr).AString); +end; + +procedure TTestJSParser.TestArrayExpressionIdentArgs; + +Var + X : TJSExpressionStatement; + B : TJSBracketMemberExpression; + +begin + CreateParser('A[B];'); + X:=GetExpressionStatement; + CheckClass(X.A,TJSBracketMemberExpression); + B:=TJSBracketMemberExpression(X.A); + CheckClass(B.Name,TJSPrimaryExpressionIdent); + AssertEquals('Member name identifier correct', 'B', TJSPrimaryExpressionIdent(B.Name).AString); + CheckClass(B.Mexpr,TJSPrimaryExpressionIdent); + AssertEquals('Array name correct','A',TJSPrimaryExpressionIdent(B.Mexpr).AString); +end; + +procedure TTestJSParser.TestVarDeclarationSimple; + +Var + X : TJSELement; + V : TJSVarDeclaration; +begin + CreateParser('var a;'); + X:=GetFirstVar; + CheckClass(X,TJSVarDeclaration); + V:=TJSVarDeclaration(X); +// AssertNotNull('Variable statement assigned',(X)); + AssertEquals('variable name correct registered', 'a', V.Name); + AssertNull('No initialization expression', V.Init); +end; + +procedure TTestJSParser.TestVarDeclarationDouble; + +Var + X : TJSELement; + V : TJSVarDeclaration; + +begin + CreateParser('var a, b ;'); + AssertEquals('2 variables declared',2,GetVars.Count); + X:=GetFirstVar; + CheckClass(X,TJSVarDeclaration); + V:=TJSVarDeclaration(X); +// AssertNotNull('Variable statement assigned',(X)); + AssertEquals('variable name correct registered', 'a', V.name); + X:=GetVars.Nodes[1].Node; + CheckClass(X,TJSVarDeclaration); + V:=TJSVarDeclaration(X); + AssertEquals('variable name correct registered', 'b', V.Name); + AssertNull('No initialization expression', V.Init); +end; + +procedure TTestJSParser.TestVarDeclarationSimpleInit; + +Var + X : TJSELement; + V : TJSVarDeclaration; +begin + CreateParser('var a = b;'); + X:=GetFirstVar; + CheckClass(X,TJSVarDeclaration); + V:=TJSVarDeclaration(X); +// AssertNotNull('Variable statement assigned',(X)); + AssertEquals('variable name correct registered', 'a', V.Name); + AssertNotNull('Initialization expression present', V.Init); + CheckClass(V.Init,TJSPrimaryExpressionIdent); + AssertEquals('Member name identifier correct', 'b', TJSPrimaryExpressionIdent(V.init).AString); +end; + +procedure TTestJSParser.TestVarDeclarationDoubleInit; + +Var + X : TJSELement; + V : TJSVarDeclaration; +begin + CreateParser('var a, c = b;'); + AssertEquals('2 variables declared',2,GetVars.Count); + X:=GetFirstVar; + CheckClass(X,TJSVarDeclaration); + V:=TJSVarDeclaration(X); +// AssertNotNull('Variable statement assigned',(X)); + AssertEquals('variable name correct registered', 'a', V.Name); + AssertNull('No initialization expression', V.Init); + X:=GetVars.Nodes[1].Node; + CheckClass(X,TJSVarDeclaration); + V:=TJSVarDeclaration(X); + AssertEquals('variable name correct registered', 'c', V.Name); + AssertNotNull('No initialization expression', V.Init); + CheckClass(V.Init,TJSPrimaryExpressionIdent); + AssertEquals('Member name identifier correct', 'b', TJSPrimaryExpressionIdent(V.init).AString); +end; + +procedure TTestJSParser.TestBlockEmpty; + +Var + E : TJSSourceElements; + X : TJSElement; + +begin + CreateParser('{}'); + E:=GetSourceElements; + AssertEquals('1 statement in block',1,E.Statements.Count); + X:=E.Statements.Nodes[0].Node; + CheckClass(X,TJSEmptyBlockStatement); +end; + +procedure TTestJSParser.TestBlockEmptyStatement; + +Var + E : TJSSourceElements; + X : TJSElement; + +begin + CreateParser('{;}'); + E:=GetSourceElements; + AssertEquals('1 statement in block',1,E.Statements.Count); + X:=E.Statements.Nodes[0].Node; + CheckClass(X,TJSEmptyStatement); +end; + +procedure TTestJSParser.TestBlockSimpleStatement; + +Var + E : TJSSourceElements; + X : TJSElement; + +begin + CreateParser('{a;}'); + E:=GetSourceElements; + AssertEquals('1 statement in block',1,E.Statements.Count); + X:=E.Statements.Nodes[0].Node; + CheckClass(X,TJSExpressionStatement); + CheckNotNull(TJSExpressionStatement(X).A); + CheckClass(TJSExpressionStatement(X).A,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(TJSExpressionStatement(X).A).AString) +end; + +procedure TTestJSParser.TestFunctionDeclarationEmpty; + +Var + E : TJSSourceElements; + N : TJSElement; + FD : TJSFunctionDeclarationStatement; + +begin + CreateParser('function a () {}'); + E:=GetSourceElements; + AssertEquals('1 function defined',1,E.functions.Count); + N:=E.Functions.Nodes[0].Node; + AssertNotNull('Function element defined ',N); + CheckClass(N,TJSFunctionDeclarationStatement); + FD:=TJSFunctionDeclarationStatement(N); + AssertNotNull('Function definition assigned',FD.AFunction); + AssertEquals('Function name OK','a',FD.AFunction.Name); + AssertNotNull('Function body assigned', FD.AFunction.Body); + AssertEquals('No parameters',0,FD.AFunction.Params.Count); + N:=FD.AFunction.Body; + CheckClass(N,TJSFunctionBody); + AssertNotNull('Function body has element',TJSFunctionBody(N).A); + CheckClass(TJSFunctionBody(N).A, TJSSourceElements); + E:=TJSSourceElements(TJSFunctionBody(N).A); + AssertEquals('0 statement in functionbody elements',0,E.Statements.Count); +// TJSEmptyBlockStatement +end; + +procedure TTestJSParser.TestFunctionDeclarationWithArgs; + +Var + E : TJSSourceElements; + N : TJSElement; + FD : TJSFunctionDeclarationStatement; + +begin + CreateParser('function a (b,c) {}'); + E:=GetSourceElements; + AssertEquals('1 function defined',1,E.functions.Count); + N:=E.Functions.Nodes[0].Node; + AssertNotNull('Function element defined ',N); + CheckClass(N,TJSFunctionDeclarationStatement); + FD:=TJSFunctionDeclarationStatement(N); + AssertNotNull('Function definition assigned',FD.AFunction); + AssertEquals('Function name OK','a',FD.AFunction.Name); + AssertNotNull('Function body assigned', FD.AFunction.Body); + AssertEquals('2 parameters',2,FD.AFunction.Params.Count); + AssertEquals('1st parameter','b',FD.AFunction.Params[0]); + AssertEquals('2nd parameter','c',FD.AFunction.Params[1]); + N:=FD.AFunction.Body; + CheckClass(N,TJSFunctionBody); + AssertNotNull('Function body has element',TJSFunctionBody(N).A); + CheckClass(TJSFunctionBody(N).A, TJSSourceElements); + E:=TJSSourceElements(TJSFunctionBody(N).A); + AssertEquals('0 statement in functionbody elements',0,E.Statements.Count); +// TJSEmptyBlockStatement +end; + +procedure TTestJSParser.TestFunctionDeclarationWithBody; + +Var + E : TJSSourceElements; + N : TJSElement; + FD : TJSFunctionDeclarationStatement; + +begin + CreateParser('function a () { b; }'); + E:=GetSourceElements; + AssertEquals('1 function defined',1,E.functions.Count); + N:=E.Functions.Nodes[0].Node; + AssertNotNull('Function element defined ',N); + CheckClass(N,TJSFunctionDeclarationStatement); + FD:=TJSFunctionDeclarationStatement(N); + AssertNotNull('Function definition assigned',FD.AFunction); + AssertEquals('Function name OK','a',FD.AFunction.Name); + AssertNotNull('Function body assigned', FD.AFunction.Body); + AssertEquals('2 parameters',0,FD.AFunction.Params.Count); + N:=FD.AFunction.Body; + CheckClass(N,TJSFunctionBody); + AssertNotNull('Function body has element',TJSFunctionBody(N).A); + CheckClass(TJSFunctionBody(N).A, TJSSourceElements); + E:=TJSSourceElements(TJSFunctionBody(N).A); + AssertEquals('1 statement in functionbody elements',1,E.Statements.Count); + N:=E.Statements.Nodes[0].Node; + CheckClass(N,TJSExpressionStatement); + CheckNotNull(TJSExpressionStatement(N).A); + CheckClass(TJSExpressionStatement(N).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(N).A).AString); +// TJSEmptyBlockStatement +end; + +procedure TTestJSParser.TestIfSimple; + +Var + E : TJSElement; + I : TJSIfStatement; + +begin + CreateParser('if (a) b;'); + E:=GetFirstStatement; + CheckClass(E,TJSIfStatement); + I:=TJSIfStatement(E); + AssertNotNull('Statement condition assigned',I.Cond); + CheckClass(I.Cond,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(I.Cond).AString); + AssertNull('Statement false branch assigned',I.BFalse); + AssertNotNull('Statement true branch assigned',I.Btrue); + CheckClass(I.Btrue,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(I.BTrue).A); + CheckClass(TJSExpressionStatement(I.BTrue).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(I.Btrue).A).AString); +end; + +procedure TTestJSParser.TestIfEmptyBlock; + +Var + E : TJSElement; + I : TJSIfStatement; + +begin + CreateParser('if (a) {}'); + E:=GetFirstStatement; + CheckClass(E,TJSIfStatement); + I:=TJSIfStatement(E); + AssertNotNull('Statement condition assigned',I.Cond); + CheckClass(I.Cond,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(I.Cond).AString); + AssertNull('Statement false branch assigned',I.BFalse); + AssertNotNull('Statement true branch assigned',I.Btrue); + CheckClass(I.Btrue,TJSEmptyBlockStatement); +end; + +procedure TTestJSParser.TestIfEmptyBlockElse; + +Var + E : TJSElement; + I : TJSIfStatement; + +begin + CreateParser('if (a) {} else b;'); + E:=GetFirstStatement; + CheckClass(E,TJSIfStatement); + I:=TJSIfStatement(E); + AssertNotNull('Statement condition assigned',I.Cond); + CheckClass(I.Cond,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(I.Cond).AString); + AssertNotNull('Statement false branch assigned',I.BFalse); + AssertNotNull('Statement true branch assigned',I.Btrue); + CheckClass(I.Btrue,TJSEmptyBlockStatement); +end; + +procedure TTestJSParser.TestWhileSimple; +Var + E : TJSElement; + W : TJSWhileStatement; + +begin + CreateParser('while (a) b;'); + E:=GetFirstStatement; + CheckClass(E,TJSWhileStatement); + W:=TJSWhileStatement(E); + AssertNotNull('Statement condition assigned',W.Cond); + CheckClass(W.Cond,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(W.Cond).AString); + AssertNotNull('Statement condition assigned',W.body); + CheckClass(W.Body,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(W.Body).A); + CheckClass(TJSExpressionStatement(W.Body).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(W.Body).A).AString); +end; + +procedure TTestJSParser.TestWhileBlock; + +Var + E : TJSElement; + W : TJSWhileStatement; +// B : TJSBlockStatement; + +begin + CreateParser('while (a) {b;}'); + E:=GetFirstStatement; + CheckClass(E,TJSWhileStatement); + W:=TJSWhileStatement(E); + AssertNotNull('Statement condition assigned',W.Cond); + CheckClass(W.Cond,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(W.Cond).AString); + AssertNotNull('Statement condition assigned',W.body); + CheckClass(W.Body,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(W.Body).A); + CheckClass(TJSExpressionStatement(W.Body).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(W.Body).A).AString); +end; + +procedure TTestJSParser.TestDoWhileSimple; + +Var + E : TJSElement; + W : TJSWhileStatement; +// B : TJSBlockStatement; + +begin + CreateParser('do b; while (a);'); + E:=GetFirstStatement; + CheckClass(E,TJSWhileStatement); + W:=TJSWhileStatement(E); + AssertNotNull('Statement condition assigned',W.Cond); + CheckClass(W.Cond,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(W.Cond).AString); + AssertNotNull('Statement condition assigned',W.body); + CheckClass(W.Body,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(W.Body).A); + CheckClass(TJSExpressionStatement(W.Body).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(W.Body).A).AString); +end; + +procedure TTestJSParser.TestDoWhileBlock; + +Var + E : TJSElement; + W : TJSWhileStatement; +// B : TJSBlockStatement; + +begin + CreateParser('do {b;} while (a);'); + E:=GetFirstStatement; + CheckClass(E,TJSWhileStatement); + W:=TJSWhileStatement(E); + AssertNotNull('Statement condition assigned',W.Cond); + CheckClass(W.Cond,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(W.Cond).AString); + AssertNotNull('Statement condition assigned',W.body); + CheckClass(W.Body,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(W.Body).A); + CheckClass(TJSExpressionStatement(W.Body).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(W.Body).A).AString); +end; + +procedure TTestJSParser.TestForEmpty; + +Var + E : TJSElement; + F : TJSForStatement; + +begin + CreateParser('for (;;) a;'); + E:=GetFirstStatement; + CheckClass(E,TJSForStatement); + F:=TJSForStatement(E); + AssertNull('Statement condition not assigned',F.Cond); + AssertNull('Statement init not assigned',F.Init); + AssertNull('Statement step not assigned',F.Incr); + CheckClass(F.Body,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(F.Body).A); + CheckClass(TJSExpressionStatement(F.Body).A,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(TJSExpressionStatement(F.Body).A).AString); +end; + +procedure TTestJSParser.TestForEmptyBody; + +Var + E : TJSElement; + F : TJSForStatement; + +begin + CreateParser('for (;;) {a;}'); + E:=GetFirstStatement; + CheckClass(E,TJSForStatement); + F:=TJSForStatement(E); + AssertNull('Statement condition not assigned',F.Cond); + AssertNull('Statement init not assigned',F.Init); + AssertNull('Statement step not assigned',F.Incr); + CheckClass(F.Body,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(F.Body).A); + CheckClass(TJSExpressionStatement(F.Body).A,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(TJSExpressionStatement(F.Body).A).AString); +end; + +procedure TTestJSParser.TestForSimpleBody; + +Var + E : TJSElement; + F : TJSForStatement; + +begin + CreateParser('for (a;b;c) {d;}'); + E:=GetFirstStatement; + CheckClass(E,TJSForStatement); + F:=TJSForStatement(E); + AssertNotNull('Statement condition not assigned',F.Cond); + AssertNotNull('Statement init not assigned',F.Init); + AssertNotNull('Statement step not assigned',F.Incr); + CheckClass(F.Init,TJSPrimaryExpressionIdent); + AssertNotNull('Expression statement expression',TJSPrimaryExpressionIdent(F.Init)); + AssertEquals('a',TJSPrimaryExpressionIdent(F.Init).AString); + CheckClass(F.Incr,TJSPrimaryExpressionIdent); + AssertNotNull('Expression statement expression',TJSPrimaryExpressionIdent(F.Incr)); + AssertEquals('c',TJSPrimaryExpressionIdent(F.Incr).AString); + CheckClass(F.Cond,TJSPrimaryExpressionIdent); + AssertNotNull('Expression statement expression',TJSPrimaryExpressionIdent(F.Cond)); + AssertEquals('b',TJSPrimaryExpressionIdent(F.cond).AString); + CheckClass(F.Body,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(F.Body).A); + CheckClass(TJSExpressionStatement(F.Body).A,TJSPrimaryExpressionIdent); + AssertEquals('d',TJSPrimaryExpressionIdent(TJSExpressionStatement(F.Body).A).AString); +end; + +procedure TTestJSParser.TestTryCatch; + +Var + E : TJSElement; + T : TJSTryCatchStatement; + +begin + CreateParser('try {a;} catch (e) {b;}'); + E:=GetFirstStatement; + CheckClass(E,TJSTryCatchStatement); + T:=TJSTryCatchStatement(E); + CheckClass(T.Block,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(T.Block).A); + CheckClass(TJSExpressionStatement(T.Block).A,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.Block).A).AString); + CheckClass(T.BCatch,TJSExpressionStatement); + AssertEquals('Except object identifier name','e',T.Ident); + AssertNotNull('Expression statement expression',TJSExpressionStatement(T.BCatch).A); + CheckClass(TJSExpressionStatement(T.BCatch).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.BCatch).A).AString); + AssertNull('No Finally expression',T.BFinally); +end; + +procedure TTestJSParser.TestTryCatchFinally; + +Var + E : TJSElement; + T : TJSTryCatchFinallyStatement; + +begin + CreateParser('try {a;} catch (e) {b;} finally {c;}'); + E:=GetFirstStatement; + CheckClass(E,TJSTryCatchFinallyStatement); + T:=TJSTryCatchFinallyStatement(E); + CheckClass(T.Block,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(T.Block).A); + CheckClass(TJSExpressionStatement(T.Block).A,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.Block).A).AString); + AssertEquals('Except object identifier name','e',T.Ident); + CheckClass(T.BCatch,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(T.BCatch).A); + CheckClass(TJSExpressionStatement(T.BCatch).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.BCatch).A).AString); + AssertNotNull('Finally expression',T.BFinally); + CheckClass(T.BFinally,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(T.BFinally).A); + CheckClass(TJSExpressionStatement(T.BFinally).A,TJSPrimaryExpressionIdent); + AssertEquals('c',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.BFinally).A).AString); +end; + +procedure TTestJSParser.TestTryFinally; + +Var + E : TJSElement; + T : TJSTryFinallyStatement; + +begin + CreateParser('try {a;} finally {c;}'); + E:=GetFirstStatement; + CheckClass(E,TJSTryFinallyStatement); + T:=TJSTryFinallyStatement(E); + CheckClass(T.Block,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(T.Block).A); + CheckClass(TJSExpressionStatement(T.Block).A,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.Block).A).AString); + AssertNull('No catch',T.BCatch); + AssertNotNull('Finally expression',T.BFinally); + AssertNotNull('Finally expression',TJSExpressionStatement(T.BFinally).A); + CheckClass(TJSExpressionStatement(T.BFinally).A,TJSPrimaryExpressionIdent); + AssertEquals('c',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.BFinally).A).AString); +end; + +procedure TTestJSParser.TestThrow; +Var + E : TJSElement; + T : TJSThrowStatement; + +begin + CreateParser('throw a;'); + E:=GetFirstStatement; + CheckClass(E,TJSThrowStatement); + T:=TJSThrowStatement(E); + AssertNotNull('Have throw object',T.A); + CheckClass(T.A,TJSPrimaryExpressionIdent); + AssertEquals('Correct identifier','a',TJSPrimaryExpressionIdent(T.A).AsTring); +end; + +procedure TTestJSParser.TestReturn; + +Var + E : TJSSourceElements; + N : TJSElement; + FD : TJSFunctionDeclarationStatement; + +begin + CreateParser('function a () { return b; }'); + E:=GetSourceElements; + AssertEquals('1 function defined',1,E.functions.Count); + N:=E.Functions.Nodes[0].Node; + AssertNotNull('Function element defined ',N); + CheckClass(N,TJSFunctionDeclarationStatement); + FD:=TJSFunctionDeclarationStatement(N); + AssertNotNull('Function definition assigned',FD.AFunction); + AssertEquals('Function name OK','a',FD.AFunction.Name); + AssertNotNull('Function body assigned', FD.AFunction.Body); + AssertEquals('No parameters',0,FD.AFunction.Params.Count); + N:=FD.AFunction.Body; + CheckClass(N,TJSFunctionBody); + AssertNotNull('Function body has element',TJSFunctionBody(N).A); + CheckClass(TJSFunctionBody(N).A, TJSSourceElements); + E:=TJSSourceElements(TJSFunctionBody(N).A); + AssertEquals('1 statement in functionbody elements',1,E.Statements.Count); +end; + +procedure TTestJSParser.TestIfElseSimple; + +Var + E : TJSElement; + I : TJSIfStatement; + +begin + CreateParser('if (a) b; else c;'); + E:=GetFirstStatement; + CheckClass(E,TJSIfStatement); + I:=TJSIfStatement(E); + AssertNotNull('Statement condition assigned',I.Cond); + CheckClass(I.Cond,TJSPrimaryExpressionIdent); + AssertEquals('a',TJSPrimaryExpressionIdent(I.Cond).AString); + AssertNotNull('Statement condition assigned',I.Btrue); + CheckClass(I.Btrue,TJSExpressionStatement); + AssertNotNull('Expression statement expression',TJSExpressionStatement(I.BTrue).A); + CheckClass(TJSExpressionStatement(I.BTrue).A,TJSPrimaryExpressionIdent); + AssertEquals('b',TJSPrimaryExpressionIdent(TJSExpressionStatement(I.Btrue).A).AString); + AssertNotNull('Else Statement condition assigned',I.BFalse); + CheckClass(I.BFalse,TJSExpressionStatement); + AssertNotNull('Else statement expression',TJSExpressionStatement(I.BFalse).A); + CheckClass(TJSExpressionStatement(I.BFalse).A,TJSPrimaryExpressionIdent); + AssertEquals('c',TJSPrimaryExpressionIdent(TJSExpressionStatement(I.BFalse).A).AString); +end; + + +procedure TTestJSParser.TestExpressionPrecedenceMulNot; + +Var + X : TJSExpressionStatement; + R : TJSUnaryNotExpression; + E : TJSMultiplicativeExpressionMul; + +begin + CreateParser('4 * !2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryNotExpression); + R:=TJSUnaryNotExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('Not operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Not operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Multiplication left operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedencePlusPreMinusMinus; +Var + X : TJSExpressionStatement; + R : TJSUnaryPreMinusMinusExpression; + E : TJSAdditiveExpressionPlus; + +begin + CreateParser('4 + --2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSAdditiveExpressionPlus); + E:=TJSAdditiveExpressionPlus(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryPreMinusMinusExpression); + R:=TJSUnaryPreMinusMinusExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression right operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceMulPrePlusPlus; + +Var + X : TJSExpressionStatement; + R : TJSUnaryPrePlusPlusExpression; + E : TJSMultiplicativeExpressionMul; + +begin + CreateParser('4 * ++2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryPrePlusPlusExpression); + R:=TJSUnaryPrePlusPlusExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression right operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestExpressionPrecedenceMulPreMinusMinus; +Var + X : TJSExpressionStatement; + R : TJSUnaryPreMinusMinusExpression; + E : TJSMultiplicativeExpressionMul; + +begin + CreateParser('4 * --2;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSMultiplicativeExpressionMul); + E:=TJSMultiplicativeExpressionMul(X.A); + AssertNotNull('Expression left operand assigned',E.A); + AssertNotNull('Expression right operand assigned',E.B); + CheckClass(E.B,TJSUnaryPreMinusMinusExpression); + R:=TJSUnaryPreMinusMinusExpression(E.B); + CheckClass(E.A,TJSLiteral); + AssertNotNull('Multiplication left operand assigned',R.A); + CheckClass(R.A,TJSLiteral); + AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType); + AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber); + AssertNotNull('Addition right operand value assigned',TJSLiteral(E.A).Value); + AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType); + AssertEquals('Expression right operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber); +end; + +procedure TTestJSParser.TestSimpleExpressionBooleanLiteralTrue; + +Var + X : TJSExpressionStatement; + +begin + CreateParser('true;'); + X:=GetExpressionStatement; + AssertNotNull('Expression statement assigned',X.A); + CheckClass(X.A,TJSLiteral); + AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value); + AssertEquals('Expression value type correct', jstBoolean,TJSLiteral(X.A).Value.ValueType); + AssertEquals('Expression value correct', True, TJSLiteral(X.A).Value.AsBoolean); +end; + + +procedure TTestJSParser.TestEmpty; + +Var + E : TJSElement; + FB : TJSFunctionBody; + SE : TJSSourceElements; + +begin + CreateParser('var a;'); + E:=FParser.Parse; + CheckClass(E,TJSFunctionBody); + FB:=TJSFunctionBody(E); + AssertNotNull(FB.A); + CheckClass(FB.A,TJSSourceElements); + SE:=TJSSourceElements(FB.A); + AssertEquals('1 variable declaration ',1,SE.Vars.Count); + CheckClass(FB.A,TJSSourceElements); +end; + +procedure TTestJSParser.SetUp; +begin + FParser:=Nil; + FSource:=Nil; +end; + +procedure TTestJSParser.TearDown; +begin +// FreeAndNil(FToFree); + FreeAndNil(FParser); + FReeAndNil(FSource); +end; + +procedure TTestJSParser.CreateParser(const ASource: string); +begin + FSource:=TStringStream.Create(ASource); + FParser:=TJSParser.Create(FSource); +end; + +procedure TTestJSParser.CheckClass(E: TJSElement; C: TJSElementClass); +begin + AssertEquals(C,E.ClassType); +end; + +function TTestJSParser.GetSourceElements: TJSSourceElements; + +Var + E : TJSElement; + FB : TJSFunctionBody; + +begin + If Not Assigned(FSE) then + begin + AssertNotNull('Parser assigned',FParser); + E:=FParser.Parse; + CheckClass(E,TJSFunctionBody); + FB:=TJSFunctionBody(E); + AssertNotNull(FB.A); + CheckClass(FB.A,TJSSourceElements); + FSE:=TJSSourceElements(FB.A); + end; + Result:=FSE; + FToFree:=E; +end; + +function TTestJSParser.GetVars: TJSElementNodes; +begin + Result:=GetSourceElements.Vars; +end; + +function TTestJSParser.GetStatements: TJSElementNodes; +begin + Result:=GetSourceElements.Statements; +end; + +function TTestJSParser.GetFunctions: TJSElementNodes; +begin + Result:=GetSourceElements.Functions; +end; + + +initialization + + RegisterTest(TTestJSParser); +end. + diff --git a/packages/fcl-js/tests/tcscanner.pp b/packages/fcl-js/tests/tcscanner.pp new file mode 100644 index 0000000000..8eb1c716d1 --- /dev/null +++ b/packages/fcl-js/tests/tcscanner.pp @@ -0,0 +1,983 @@ +unit tcscanner; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Typinfo, fpcunit, testutils, testregistry, jsscanner; + +type + + { TTestLineReader } + + TTestLineReader = Class(TTestCase) + Private + FData: TStringStream; + FReader : TStreamLineReader; + protected + Procedure CreateReader(AInput : String); + procedure TearDown; override; + published + Procedure TestEmpty; + Procedure TestReadLine; + Procedure TestReadLines13; + Procedure TestReadLines10; + Procedure TestReadLines1310; + procedure TestReadLinesEOF13; + procedure TestReadLinesEOF10; + procedure TestReadLinesEOF1310; + procedure TestReadEmptyLines101010; + end; + + { TTestJSScanner } + + TTestJSScanner = class(TTestCase) + Private + FStream : TStream; + FLineReader : TLineReader; + FScanner : TJSScanner; + FErrorSource : String; + procedure AssertEquals(AMessage: String; AExpected, AActual : TJSToken); overload; + procedure CheckToken(AToken: TJSToken; ASource: String); + procedure CheckTokens(ASource: String; ATokens: array of TJSToken); + procedure DoTestFloat(F: Double); + procedure DoTestFloat(F: Double; S: String); + procedure DoTestString(S: String); + procedure TestErrorSource; + protected + Function CreateScanner(AInput : String) : TJSScanner; + procedure FreeScanner; + procedure SetUp; override; + procedure TearDown; override; + + Property Scanner : TJSScanner Read FScanner; + published + Procedure TestEmpty; + procedure TestAndAnd; + procedure TestAndEq; + procedure TestAssign; + procedure TestBraceClose; + procedure TestBraceOpen; + procedure TestColon; + procedure TestComma; + procedure TestCurlyBraceClose; + procedure TestCurlyBraceOpen; + procedure TestDiv; + procedure TestDiveq; + procedure TestXor; + procedure TestXoreq; + procedure TestDot; + procedure TestEq; + procedure TestGE; + procedure TestFalse; + procedure TestInv; + procedure TestNot; + procedure TestString; + procedure TestTrue; + procedure TestGreaterThan; + procedure TestLE; + procedure TestLessThan; + procedure TestLSHIFT; + procedure TestLSHIFTEQ; + procedure TestMinus; + procedure TestMinusEQ; + procedure TestMinusMinus; + procedure TestModeq; + procedure TestMul; + procedure TestNE; + procedure TestNSE; + procedure TestOREQ; + procedure TestOROR; + procedure TestPlus; + procedure TestPlusEq; + procedure TestPlusPlus; + procedure TestRShift; + procedure TestRShiftEq; + procedure TestSemicolon; + procedure TestSEq; + procedure TestSquaredBraceClose; + procedure TestSquaredBraceOpen; + procedure TestStarEq; + procedure TestURShift; + procedure TestURShiftEq; + procedure TestBreak; + procedure TestCase; + procedure TestCatch; + procedure TestContinue; + procedure TestDefault; + procedure TestDelete; + procedure TestDO; + procedure TestElse; + procedure TestFinally; + procedure TestFor; + procedure TestFunction; + procedure TestIf; + procedure TestIn; + procedure TestInstanceOf; + procedure TestNew; + procedure TestReturn; + procedure TestSwitch; + procedure TestThis; + procedure TestThrow; + procedure TestTry; + procedure TestTypeOf; + procedure TestVar; + procedure TestVoid; + procedure TestWhile; + procedure TestWith; + Procedure Test2Words; + procedure Test3Words; + procedure TestIdentifier; + procedure TestIdentifier2; + procedure TestIdentifier3; + procedure TestIdentifier4; + procedure TestIdentifier5; + procedure TestIdentifierDotIdentifier; + procedure TestEOLN; + procedure TestEOLN2; + procedure TestEOLN3; + procedure TestEOLN4; + procedure TestComment1; + procedure TestComment2; + procedure TestComment3; + procedure TestComment4; + procedure TestComment5; + procedure TestComment6; + procedure TestFloat; + procedure TestStringError; + procedure TestFloatError; + end; + + +implementation + +Function TTestJSScanner.CreateScanner(AInput : String) : TJSScanner; + +begin + FStream:=TStringStream.Create(AInput); + FLineReader:=TStreamLineReader.Create(Fstream); + FScanner:=TJSScanner.Create(FLineReader); +end; + +procedure TTestJSScanner.FreeScanner; +begin + FreeAndNil(FScanner); + FreeAndNil(FLineReader); + FreeAndNil(FStream); +end; + +procedure TTestJSScanner.SetUp; +begin + inherited SetUp; +end; + + + +procedure TTestJSScanner.TestEmpty; + +Var + J : TJSToken; + +begin + CreateScanner(''); + J:=Scanner.FetchToken; + If (J<>tjsEOF) then + Fail('Empty returns EOF'); +end; + +procedure TTestJSScanner.AssertEquals(AMessage : String; AExpected, AActual: TJSToken); + +Var + J : TJSToken; + S,EN1,EN2 : String; + +begin + If (AActual<>AExpected) then + begin + EN1:=GetEnumName(TypeINfo(TJSToken),Ord(AExpected)); + EN2:=GetEnumName(TypeINfo(TJSToken),Ord(AActual)); + S:=Format('%s : %s <> %s',[AMessage,EN1,EN2]); + Fail(S); + end; +end; + +procedure TTestJSScanner.CheckToken(AToken : TJSToken; ASource : String); + +Var + J : TJSToken; + EN2 : String; + +begin + CreateScanner(ASource); + J:=Scanner.FetchToken; + EN2:=GetEnumName(TypeINfo(TJSToken),Ord(AToken)); + AssertEquals(Format('Source %s should result in %s.',[ASource,EN2]),AToken,J); +end; + + +procedure TTestJSScanner.TestAndAnd; + +begin + CheckToken(tjsAndAnd,'&&'); +end; + +procedure TTestJSScanner.TestAndEq; + +begin + CheckToken(tjsAndEq,'&='); +end; + +procedure TTestJSScanner.TestBraceOpen; + +begin + CheckToken(tjsBraceOpen,'('); +end; + +procedure TTestJSScanner.TestBraceClose; + +begin + CheckToken(tjsBraceClose,')'); +end; + +procedure TTestJSScanner.TestSquaredBraceClose; + +begin + CheckToken(tjsSquaredBraceClose,']'); +end; + +procedure TTestJSScanner.TestSquaredBraceOpen; + +begin + CheckToken(tjssQuaredBraceOpen,'['); +end; + +procedure TTestJSScanner.TestCurlyBraceOpen; + +begin + CheckToken(tjsCurlyBraceOpen,'{'); +end; + +procedure TTestJSScanner.TestCurlyBraceClose; + +begin + CheckToken(tjsCurlyBraceClose,'}'); +end; + +procedure TTestJSScanner.TestComma; + +begin + CheckToken(tjsComma,','); +end; + +procedure TTestJSScanner.TestColon; + +begin + CheckToken(tjsColon,':'); +end; + +procedure TTestJSScanner.TestDot; + +begin + CheckToken(tjsDot,'.'); +end; + +procedure TTestJSScanner.TestSemicolon; + +begin + CheckToken(tjsSemicolon,';'); +end; + +procedure TTestJSScanner.TestAssign; + +begin + CheckToken(tjsAssign,'='); +end; + +procedure TTestJSScanner.TestGreaterThan; + +begin + CheckToken(tjsGT,'>'); +end; + +procedure TTestJSScanner.TestLessThan; + +begin + CheckToken(tjsLT,'<'); +end; + +procedure TTestJSScanner.TestPlus; + +begin + CheckToken(tjsPlus,'+'); +end; + +procedure TTestJSScanner.TestMinus; + +begin + CheckToken(tjsMinus,'-'); +end; + +procedure TTestJSScanner.TestMul; + +begin + CheckToken(tjsMul,'*'); +end; + +procedure TTestJSScanner.TestDiv; + +begin + CheckToken(tjsDiv,'/'); +end; + +procedure TTestJSScanner.TestEq; + +begin + CheckToken(tjsEq,'=='); +end; + +procedure TTestJSScanner.TestGE; + +begin + CheckToken(tjsGE,'>='); +end; + +procedure TTestJSScanner.TestLE; + +begin + CheckToken(tjsLE,'<='); +end; + +procedure TTestJSScanner.TestLSHIFT; + +begin + CheckToken(tjsLShift,'<<'); +end; + +procedure TTestJSScanner.TestLSHIFTEQ; + +begin + CheckToken(tjsLShiftEq,'<<='); +end; + +procedure TTestJSScanner.TestMinusEQ; + +begin + CheckToken(tjsMinusEq,'-='); +end; + +procedure TTestJSScanner.TestMinusMinus; + +begin + CheckToken(tjsMinusMinus,'--'); +end; + +procedure TTestJSScanner.TestModeq; + +begin + CheckToken(tjsModeq,'%='); +end; + + +procedure TTestJSScanner.TestDiveq; + +begin + CheckToken(tjsDiveq,'/='); +end; + +procedure TTestJSScanner.TestXor; +begin + CheckToken(tjsXOR,'^'); +end; + +procedure TTestJSScanner.TestXoreq; +begin + CheckToken(tjsXOREQ,'^='); +end; + +procedure TTestJSScanner.TestNE; + +begin + CheckToken(tjsNE,'!='); +end; + +procedure TTestJSScanner.TestInv; + +begin + CheckToken(tjsInv,'~'); +end; + +procedure TTestJSScanner.TestNot; + +begin + CheckToken(tjsNot,'!'); +end; + +procedure TTestJSScanner.TestTrue; + +begin + CheckToken(tjsTrue,'true'); +end; + +procedure TTestJSScanner.TestFalse; + +begin + CheckToken(tjsFalse,'false'); +end; + +procedure TTestJSScanner.TestOREQ; + +begin + CheckToken(tjsOREQ,'|='); +end; + +procedure TTestJSScanner.TestOROR; + +begin + CheckToken(tjsOROR,'||'); +end; + +procedure TTestJSScanner.TestPlusEq; + +begin + CheckToken(tjsPlusEq,'+='); +end; + +procedure TTestJSScanner.TestPlusPlus; + +begin + CheckToken(tjsPlusPlus,'++'); +end; + +procedure TTestJSScanner.TestURShift; + +begin + CheckToken(tjsURSHIFT,'>>>'); +end; + +procedure TTestJSScanner.TestURShiftEq; + +begin + CheckToken(tjsURSHIFTEQ,'>>>='); +end; + +procedure TTestJSScanner.TestRShift; + +begin + CheckToken(tjsRSHIFT,'>>'); +end; + +procedure TTestJSScanner.TestRShiftEq; + +begin + CheckToken(tjsRSHIFTEQ,'>>='); +end; + +procedure TTestJSScanner.TestSEq; + +begin + CheckToken(tjsSEQ,'==='); +end; + +procedure TTestJSScanner.TestNSE; + +begin + CheckToken(tjsSNE,'!=='); +end; + +procedure TTestJSScanner.TestStarEq; + +begin + CheckToken(tjsMulEq,'*='); +end; + +procedure TTestJSScanner.TestBreak; + +begin + CheckToken(tjsBreak,'break'); +end; + +procedure TTestJSScanner.TestCase; + +begin + CheckToken(tjscase,'case'); +end; + +procedure TTestJSScanner.TestCatch; + +begin + CheckToken(tjscatch,'catch'); +end; + +procedure TTestJSScanner.TestContinue; + +begin + CheckToken(tjscontinue,'continue'); +end; + +procedure TTestJSScanner.TestDefault; + +begin + CheckToken(tjsdefault,'default'); +end; + +procedure TTestJSScanner.TestDelete; + +begin + CheckToken(tjsdelete,'delete'); +end; + +procedure TTestJSScanner.TestDO; + +begin + CheckToken(tjsdo,'do'); +end; + +procedure TTestJSScanner.TestElse; + +begin + CheckToken(tjselse,'else'); +end; + +procedure TTestJSScanner.TestFinally; + +begin + CheckToken(tjsfinally,'finally'); +end; + +procedure TTestJSScanner.TestFor; + +begin + CheckToken(tjsfor,'for'); +end; + +procedure TTestJSScanner.TestFunction; + +begin + CheckToken(tjsfunction,'function'); +end; + +procedure TTestJSScanner.TestIf; + +begin + CheckToken(tjsif,'if'); +end; + +procedure TTestJSScanner.TestIn; + +begin + CheckToken(tjsin,'in'); +end; + +procedure TTestJSScanner.TestInstanceOf; + +begin + CheckToken(tjsinstanceof,'instanceof'); +end; + +procedure TTestJSScanner.TestNew; + +begin + CheckToken(tjsnew,'new'); +end; + +procedure TTestJSScanner.TestReturn; + +begin + CheckToken(tjsreturn,'return'); +end; + +procedure TTestJSScanner.TestSwitch; + +begin + CheckToken(tjsswitch,'switch'); +end; + +procedure TTestJSScanner.TestThis; + +begin + CheckToken(tjsThis,'this'); +end; + +procedure TTestJSScanner.TestThrow; + +begin + CheckToken(tjsThrow,'throw'); +end; + +procedure TTestJSScanner.TestTry; + +begin + CheckToken(tjsTry,'try'); +end; + +procedure TTestJSScanner.TestTypeOf; + +begin + CheckToken(tjstypeof,'typeof'); +end; + +procedure TTestJSScanner.TestVar; + +begin + CheckToken(tjsvar,'var'); +end; + +procedure TTestJSScanner.TestVoid; + +begin + CheckToken(tjsvoid,'void'); +end; + +procedure TTestJSScanner.TestWhile; + +begin + CheckToken(tjswhile,'while'); +end; + +procedure TTestJSScanner.TestWith; + +begin + CheckToken(tjswith,'with'); +end; + +procedure TTestJSScanner.CheckTokens(ASource : String; ATokens : Array of TJSToken); + +Var + I : Integer; + J : TJSToken; + S : String; + +begin + CreateScanner(ASource); + For I:=Low(ATokens) to High(ATokens) do + begin + J:=FScanner.FetchToken; + S:=GetEnumName(TypeINfo(TJSToken),Ord(ATokens[i])); + S:=Format('Source "%s", token %d (%s): expected %s',[ASource,I,FScanner.CurTokenString,S]); + AssertEquals(S,ATokens[i],J); + end; +end; + +procedure TTestJSScanner.Test2Words; +begin + CheckTokens('with do',[tjsWith,tjsDo]); +end; + +procedure TTestJSScanner.Test3Words; +begin + CheckTokens('with do for',[tjsWith,tjsDo,tjsFor]); +end; + +procedure TTestJSScanner.TestIdentifier; +begin + CheckToken(tjsIdentifier,'something'); + AssertEquals('Correct identifier','something',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestIdentifier2; +begin + CheckToken(tjsIdentifier,'_something'); + AssertEquals('Correct identifier','_something',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestIdentifier3; +begin + CheckToken(tjsIdentifier,'$'); + AssertEquals('Correct identifier','$',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestIdentifier4; +begin + CheckToken(tjsIdentifier,'_0'); + AssertEquals('Correct identifier','_0',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestIdentifier5; +begin + CheckToken(tjsIdentifier,'$0'); + AssertEquals('Correct identifier','$0',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestIdentifierDotIdentifier; +begin + CheckTokens('something.different',[tjsIdentifier,tjsdot,tjsIdentifier]); +// AssertEquals('Correct identifier','something',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestEOLN; +begin + CreateScanner('something'); + FScanner.FetchToken; + AssertEquals('Got to end of line after reading single token at EOF',True,FScanner.IsEndOfLine); +// AssertEquals('Correct identifier','something',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestEOLN2; +begin + CreateScanner('something different'); + FScanner.FetchToken; + AssertEquals('Not yet end of line after reading single token at EOF',False,FScanner.IsEndOfLine); +end; + +procedure TTestJSScanner.TestEOLN3; +begin + CreateScanner('something'#13#10'different'); + FScanner.FetchToken; + AssertEquals('End of line after reading single token',True,FScanner.IsEndOfLine); +end; + +procedure TTestJSScanner.TestEOLN4; +begin + CreateScanner('something'#10'different'); + FScanner.FetchToken; + AssertEquals('End of line after reading first token',True,FScanner.IsEndOfLine); + FScanner.FetchToken; + AssertEquals('End of line after reading second token',True,FScanner.IsEndOfLine); +end; + +procedure TTestJSScanner.TestComment1; +begin + CreateScanner('// some comment string'); + AssertEquals('Comment line is skipped',tjsEOF,FScanner.FetchToken); +end; + +procedure TTestJSScanner.TestComment2; +begin + CreateScanner('// some comment string'); + FScanner.ReturnComments:=True; + AssertEquals('Comment line is returned',tjsComment,FScanner.FetchToken); + AssertEquals('Comment contents is returned',' some comment string',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestComment3; +begin + CreateScanner('/* some comment string */'); + AssertEquals('Comment line is skipped',tjsEOF,FScanner.FetchToken); +end; + +procedure TTestJSScanner.TestComment4; +begin + CreateScanner('/* some comment string */'); + FScanner.ReturnComments:=True; + AssertEquals('Comment line is returned',tjsComment,FScanner.FetchToken); + AssertEquals('Comment contents is returned',' some comment string ',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestComment5; +begin + CreateScanner('/* some nested comment // string */'); + FScanner.ReturnComments:=True; + AssertEquals('Comment line is returned',tjsComment,FScanner.FetchToken); + AssertEquals('Comment contents is returned',' some nested comment // string ',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestComment6; +begin + CreateScanner('// /* some nested comment string */'); + FScanner.ReturnComments:=True; + AssertEquals('Comment line is returned',tjsComment,FScanner.FetchToken); + AssertEquals('Comment contents is returned',' /* some nested comment string */',FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TearDown; +begin + FreeScanner; +end; + +procedure TTestJSScanner.DoTestFloat(F : Double); + +Var + S : String; + +begin + Str(F,S); + DoTestFloat(F,S); +end; + +procedure TTestJSScanner.DoTestFloat(F : Double; S : String); + +Var + J : TJSToken; + C : Double; + I : integer; + V : String; + +begin + CreateScanner(S); + J:=FScanner.FetchToken; + AssertEquals(S+' is a number',tjsNumber,J); + V:=FScanner.CurTokenString; + If (Copy(V,1,2)='0x') then + begin + Flush(output); + V:='$'+Copy(V,3,Length(V)-2); + C:=StrToInt(V); + end + else + begin + Val(V,C,I); + If (I<>0) then + Fail(FScanner.CurTokenString+' does not contain a float value'); + end; + AssertEquals('Parsed float equals original float',F,C); +end; + +procedure TTestJSScanner.TestFloat; + + +begin + DoTestFloat(1.2); + DoTestFloat(-1.2); + DoTestFloat(0); + DoTestFloat(1.2e1); + DoTestFloat(-1.2e1); + DoTestFloat(0); + DoTestFloat(1.2,'1.2'); + DoTestFloat(-1.2,'-1.2'); + DoTestFloat(0,'0.0'); + DoTestFloat(255,'0xff') +end; + +procedure TTestJSScanner.TestFloatError; + +begin + FErrorSource:='1xz'; + AssertException('Wrong float',EJSScannerError,@TestErrorSource); +end; + + +procedure TTestJSScanner.DoTestString(S: String); + +Var + J : TJSToken; + T : String; +begin + CreateScanner(S); + J:=FScanner.FetchToken; + AssertEquals(S+' is a string',tjsString,J); + If (Length(S)>0) and (S[1] in ['"','''']) then + S:=Copy(S,2,Length(S)-2); + AssertEquals('Correct string is returned',S,FScanner.CurTokenString); +end; + +procedure TTestJSScanner.TestString; + +begin + DoTestString('"A string"'); + DoTestString('""'); + DoTestString(''''''); + DoTestString('''A string'''); +end; + +procedure TTestJSScanner.TestErrorSource; + +begin + CreateScanner(FErrorSource); + While (FScanner.FetchToken<>tjsEOF) do ; +end; + +procedure TTestJSScanner.TestStringError; + +begin + FErrorSource:='"A string'; + AssertException('Unterminated string',EJSScannerError,@TestErrorSource); + FErrorSource:='''A string'; + AssertException('Unterminated string',EJSScannerError,@TestErrorSource); +end; + + +{ TTestLineReader } + +procedure TTestLineReader.CreateReader(AInput: String); +begin + FData:=TStringStream.Create(AInput); + FReader:=TStreamLineReader.Create(FData); +end; + + +procedure TTestLineReader.TearDown; +begin + FreeAndNil(FReader); + FreeAndNil(FData); +end; + +procedure TTestLineReader.TestEmpty; +begin + CreateReader(''); + AssertEquals('Empty reader returns EOF',True,FReader.IsEOF); + AssertEquals('Empty reader returns empty string','',FReader.ReadLine); +end; + +procedure TTestLineReader.TestReadLine; +begin + CreateReader('Something'); + AssertEquals('Reader with 1 line returns 1 line','Something',FReader.ReadLine); + AssertEquals('EOF true after reading line',True,FReader.IsEOF); +end; + +procedure TTestLineReader.TestReadLines13; +begin + CreateReader('Something'#13'else'); + AssertEquals('Reader with 2 lines returns 1st line','Something',FReader.ReadLine); + AssertEquals('Reader with 2 lines returns 2nd line','else',FReader.ReadLine); + AssertEquals('EOF true after reading lines',True,FReader.IsEOF); +end; + +procedure TTestLineReader.TestReadLines10; +begin + CreateReader('Something'#10'else'); + AssertEquals('Reader with 2 lines returns 1st line','Something',FReader.ReadLine); + AssertEquals('Reader with 2 lines returns 2nd line','else',FReader.ReadLine); + AssertEquals('EOF true after reading lines',True,FReader.IsEOF); +end; + +procedure TTestLineReader.TestReadLines1310; +begin + CreateReader('Something'#13#10'else'); + AssertEquals('Reader with 2 lines returns 1st line','Something',FReader.ReadLine); + AssertEquals('Reader with 2 lines returns 2nd line','else',FReader.ReadLine); + AssertEquals('EOF true after reading lines',True,FReader.IsEOF); +end; + +procedure TTestLineReader.TestReadLinesEOF13; +begin + CreateReader('Something'#13); + AssertEquals('Reader with 2 lines + CR returns 1st line','Something',FReader.ReadLine); + AssertEquals('Reader with 1 lines + CR returns empty 2nd line','',FReader.ReadLine); + AssertEquals('EOF true after reading lines',True,FReader.IsEOF); +end; + +procedure TTestLineReader.TestReadLinesEOF10; +begin + CreateReader('Something'#10); + AssertEquals('Reader with 2 lines + LF returns 1st line','Something',FReader.ReadLine); + AssertEquals('Reader with 1 lines + LF returns empty 2nd line','',FReader.ReadLine); + AssertEquals('EOF true after reading lines',True,FReader.IsEOF); +end; + +procedure TTestLineReader.TestReadLinesEOF1310; +begin + CreateReader('Something'#13#10); + AssertEquals('Reader with 2 lines + CRLF returns 1st line','Something',FReader.ReadLine); + AssertEquals('Reader with 1 lines + CRLF returns empty 2nd line','',FReader.ReadLine); + AssertEquals('EOF true after reading lines',True,FReader.IsEOF); +end; + +procedure TTestLineReader.TestReadEmptyLines101010; + +begin + CreateReader('Something'#10#10#10); + AssertEquals('Reader with 1 line + LFLFLF returns 1st line','Something',FReader.ReadLine); + AssertEquals('EOF false after reading line 1',False,FReader.IsEOF); + AssertEquals('Reader with 1 line + LFLFLF returns empty 2nd line','',FReader.ReadLine); + AssertEquals('EOF false after reading line 2',False,FReader.IsEOF); + AssertEquals('Reader with 1 line + LFLFLF returns empty 3nd line','',FReader.ReadLine); + AssertEquals('EOF true after reading lines',True,FReader.IsEOF); +end; + +initialization + + RegisterTests([TTestLineReader,TTestJSScanner]); +end. + diff --git a/packages/fcl-js/tests/testjs.ico b/packages/fcl-js/tests/testjs.ico Binary files differnew file mode 100644 index 0000000000..0341321b5d --- /dev/null +++ b/packages/fcl-js/tests/testjs.ico diff --git a/packages/fcl-js/tests/testjs.lpi b/packages/fcl-js/tests/testjs.lpi new file mode 100644 index 0000000000..89a707bd17 --- /dev/null +++ b/packages/fcl-js/tests/testjs.lpi @@ -0,0 +1,261 @@ +<?xml version="1.0"?> +<CONFIG> + <ProjectOptions> + <Version Value="7"/> + <General> + <MainUnit Value="0"/> + <TargetFileExt Value=""/> + <Icon Value="0"/> + <UseXPManifest Value="True"/> + <ActiveEditorIndexAtStart Value="1"/> + </General> + <VersionInfo> + <ProjectVersion Value=""/> + <Language Value=""/> + <CharSet Value=""/> + </VersionInfo> + <PublishOptions> + <Version Value="2"/> + <IgnoreBinaries Value="False"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> + <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + <CommandLineParams Value="-a --format=plain"/> + <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> + </local> + </RunParams> + <RequiredPackages Count="2"> + <Item1> + <PackageName Value="FPCUnitConsoleRunner"/> + </Item1> + <Item2> + <PackageName Value="FCL"/> + </Item2> + </RequiredPackages> + <Units Count="7"> + <Unit0> + <Filename Value="testjs.lpr"/> + <IsPartOfProject Value="True"/> + <UnitName Value="testjs"/> + <CursorPos X="11" Y="7"/> + <TopLine Value="1"/> + <EditorIndex Value="0"/> + <UsageCount Value="201"/> + <Loaded Value="True"/> + </Unit0> + <Unit1> + <Filename Value="tcscanner.pp"/> + <IsPartOfProject Value="True"/> + <UnitName Value="tcscanner"/> + <CursorPos X="27" Y="427"/> + <TopLine Value="416"/> + <EditorIndex Value="2"/> + <UsageCount Value="201"/> + <Loaded Value="True"/> + </Unit1> + <Unit2> + <Filename Value="../src/jsbase.pp"/> + <IsPartOfProject Value="True"/> + <UnitName Value="jsbase"/> + <CursorPos X="1" Y="153"/> + <TopLine Value="132"/> + <EditorIndex Value="1"/> + <UsageCount Value="196"/> + <Loaded Value="True"/> + </Unit2> + <Unit3> + <Filename Value="../src/jsparser.pp"/> + <IsPartOfProject Value="True"/> + <UnitName Value="jsparser"/> + <CursorPos X="1" Y="1"/> + <TopLine Value="1"/> + <UsageCount Value="201"/> + </Unit3> + <Unit4> + <Filename Value="../src/jsscanner.pp"/> + <IsPartOfProject Value="True"/> + <UnitName Value="JSScanner"/> + <CursorPos X="1" Y="1"/> + <TopLine Value="1"/> + <UsageCount Value="201"/> + </Unit4> + <Unit5> + <Filename Value="../src/jstree.pp"/> + <IsPartOfProject Value="True"/> + <UnitName Value="jstree"/> + <CursorPos X="1" Y="1"/> + <TopLine Value="1"/> + <UsageCount Value="200"/> + </Unit5> + <Unit6> + <Filename Value="tcparser.pp"/> + <IsPartOfProject Value="True"/> + <UnitName Value="tcparser"/> + <CursorPos X="3" Y="2059"/> + <TopLine Value="2051"/> + <EditorIndex Value="4"/> + <UsageCount Value="97"/> + <Loaded Value="True"/> + </Unit6> + </Units> + <JumpHistory Count="30" HistoryIndex="29"> + <Position1> + <Filename Value="tcparser.pp"/> + <Caret Line="1752" Column="1" TopLine="1730"/> + </Position1> + <Position2> + <Filename Value="tcparser.pp"/> + <Caret Line="1767" Column="32" TopLine="1733"/> + </Position2> + <Position3> + <Filename Value="tcparser.pp"/> + <Caret Line="1790" Column="30" TopLine="1766"/> + </Position3> + <Position4> + <Filename Value="tcparser.pp"/> + <Caret Line="1763" Column="26" TopLine="1736"/> + </Position4> + <Position5> + <Filename Value="tcparser.pp"/> + <Caret Line="1791" Column="1" TopLine="1758"/> + </Position5> + <Position6> + <Filename Value="tcparser.pp"/> + <Caret Line="114" Column="30" TopLine="93"/> + </Position6> + <Position7> + <Filename Value="tcparser.pp"/> + <Caret Line="1806" Column="23" TopLine="1798"/> + </Position7> + <Position8> + <Filename Value="tcparser.pp"/> + <Caret Line="1828" Column="3" TopLine="1819"/> + </Position8> + <Position9> + <Filename Value="../../../../source/fcl-js/jsparser.pp"/> + <Caret Line="515" Column="28" TopLine="507"/> + </Position9> + <Position10> + <Filename Value="tcparser.pp"/> + <Caret Line="1824" Column="24" TopLine="1803"/> + </Position10> + <Position11> + <Filename Value="tcparser.pp"/> + <Caret Line="1828" Column="17" TopLine="1803"/> + </Position11> + <Position12> + <Filename Value="tcparser.pp"/> + <Caret Line="1849" Column="34" TopLine="1820"/> + </Position12> + <Position13> + <Filename Value="tcparser.pp"/> + <Caret Line="118" Column="27" TopLine="96"/> + </Position13> + <Position14> + <Filename Value="tcparser.pp"/> + <Caret Line="1900" Column="29" TopLine="1888"/> + </Position14> + <Position15> + <Filename Value="tcparser.pp"/> + <Caret Line="1898" Column="12" TopLine="1877"/> + </Position15> + <Position16> + <Filename Value="tcparser.pp"/> + <Caret Line="1904" Column="80" TopLine="1883"/> + </Position16> + <Position17> + <Filename Value="tcparser.pp"/> + <Caret Line="1914" Column="29" TopLine="1883"/> + </Position17> + <Position18> + <Filename Value="tcparser.pp"/> + <Caret Line="1948" Column="18" TopLine="1914"/> + </Position18> + <Position19> + <Filename Value="tcparser.pp"/> + <Caret Line="20" Column="1" TopLine="1"/> + </Position19> + <Position20> + <Filename Value="tcparser.pp"/> + <Caret Line="2165" Column="1" TopLine="2124"/> + </Position20> + <Position21> + <Filename Value="tcparser.pp"/> + <Caret Line="121" Column="27" TopLine="99"/> + </Position21> + <Position22> + <Filename Value="tcparser.pp"/> + <Caret Line="1969" Column="3" TopLine="1960"/> + </Position22> + <Position23> + <Filename Value="tcparser.pp"/> + <Caret Line="1971" Column="46" TopLine="1950"/> + </Position23> + <Position24> + <Filename Value="tcparser.pp"/> + <Caret Line="1986" Column="14" TopLine="1961"/> + </Position24> + <Position25> + <Filename Value="tcparser.pp"/> + <Caret Line="1993" Column="33" TopLine="1960"/> + </Position25> + <Position26> + <Filename Value="../../../../source/fcl-js/jsparser.pp"/> + <Caret Line="1702" Column="24" TopLine="1685"/> + </Position26> + <Position27> + <Filename Value="tcparser.pp"/> + <Caret Line="124" Column="25" TopLine="100"/> + </Position27> + <Position28> + <Filename Value="tcparser.pp"/> + <Caret Line="2038" Column="10" TopLine="2035"/> + </Position28> + <Position29> + <Filename Value="tcparser.pp"/> + <Caret Line="2075" Column="56" TopLine="2051"/> + </Position29> + <Position30> + <Filename Value="../../../../source/fcl-js/jsparser.pp"/> + <Caret Line="1747" Column="29" TopLine="1740"/> + </Position30> + </JumpHistory> + </ProjectOptions> + <CompilerOptions> + <Version Value="8"/> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)/"/> + <OtherUnitFiles Value="/home/michael/source/fcl-js/;../"/> + </SearchPaths> + <CodeGeneration> + <Optimizations> + <OptimizationLevel Value="0"/> + </Optimizations> + </CodeGeneration> + <Other> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> + <Debugging> + <BreakPoints Count="1"> + <Item1> + <Source Value="../jsscanner.pp"/> + <Line Value="717"/> + </Item1> + </BreakPoints> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/packages/fcl-js/tests/testjs.lpr b/packages/fcl-js/tests/testjs.lpr new file mode 100644 index 0000000000..081d2af7ca --- /dev/null +++ b/packages/fcl-js/tests/testjs.lpr @@ -0,0 +1,29 @@ +program testjs; + +{$mode objfpc}{$H+} + +uses + Classes, consoletestrunner, tcscanner, jsparser, jsscanner, jstree, jsbase, + tcparser; + +type + + { TLazTestRunner } + + TMyTestRunner = class(TTestRunner) + protected + // override the protected methods of TTestRunner to customize its behavior + end; + +var + Application: TMyTestRunner; + +{$IFDEF WINDOWS}{$R testjs.rc}{$ENDIF} + +begin + Application := TMyTestRunner.Create(nil); + Application.Initialize; + Application.Title := 'FPCUnit Console test runner'; + Application.Run; + Application.Free; +end. diff --git a/packages/fcl-js/tests/testjs.manifest b/packages/fcl-js/tests/testjs.manifest new file mode 100644 index 0000000000..515fedeef9 --- /dev/null +++ b/packages/fcl-js/tests/testjs.manifest @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="CompanyName.ProductName.YourApp" type="win32"/> + <description>Your application description here.</description> + <dependency> + <dependentAssembly> + <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> + </dependentAssembly> + </dependency> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker" uiAccess="false"/> + </requestedPrivileges> + </security> + </trustInfo> +</assembly>
\ No newline at end of file diff --git a/packages/fcl-js/tests/testjs.rc b/packages/fcl-js/tests/testjs.rc new file mode 100644 index 0000000000..1c11b56326 --- /dev/null +++ b/packages/fcl-js/tests/testjs.rc @@ -0,0 +1 @@ +MAINICON ICON "testjs.ico" |
