summaryrefslogtreecommitdiff
path: root/packages/fcl-js
diff options
context:
space:
mode:
authormichael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-02-04 15:18:07 +0000
committermichael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-02-04 15:18:07 +0000
commite61c9c527aaa7f96e7235536853352e3ae32a278 (patch)
tree79f0f01cf692f65b13bc0ca16aa0df37c89ae7c3 /packages/fcl-js
parentbc50a91efee1513bcf226eef21aef06eb87d6ff8 (diff)
downloadfpc-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/Makefile2354
-rw-r--r--packages/fcl-js/Makefile.fpc26
-rw-r--r--packages/fcl-js/README.TXT23
-rw-r--r--packages/fcl-js/fpmake.pp37
-rw-r--r--packages/fcl-js/src/jsbase.pp175
-rw-r--r--packages/fcl-js/src/jsparser.pp2100
-rw-r--r--packages/fcl-js/src/jsscanner.pp909
-rw-r--r--packages/fcl-js/src/jstree.pp963
-rw-r--r--packages/fcl-js/tests/tcparser.pp2311
-rw-r--r--packages/fcl-js/tests/tcscanner.pp983
-rw-r--r--packages/fcl-js/tests/testjs.icobin0 -> 137040 bytes
-rw-r--r--packages/fcl-js/tests/testjs.lpi261
-rw-r--r--packages/fcl-js/tests/testjs.lpr29
-rw-r--r--packages/fcl-js/tests/testjs.manifest17
-rw-r--r--packages/fcl-js/tests/testjs.rc1
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
new file mode 100644
index 0000000000..0341321b5d
--- /dev/null
+++ b/packages/fcl-js/tests/testjs.ico
Binary files differ
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"