Introduction
SAScript is a stack-based scripting language. It was originally written to
allow users of our ThumbNailer product
to customize the HTML pages that ThumbNailer generates. We needed a scripting
language that allowed basic text manipulation and access to program-defined variables
that could be used by people who aren't programmers. In addition, the language had to
be able to be used in-line with HTML code. One of ThumbNailer's uses is to generate HTML
pages from a group of input images. These HTML pages are created based on user-defined
templates. To allow users to customize the pages, ThumbNailer lets them put custom HTML
and SAScript expressions on these HTML templates. This provides a lot of flexibility
for users with minimal headaches for us.
A simple SAScript expression looks like this:
&Upper("this is some text").
"&" signals the start of an expression. Upper
is an operator that converts its input to upper case. So, this
expression will output "THIS IS SOME TEXT".
Because SAScript is designed to be an in-line language, expressions can occur inside any text string.
The SAScript parser will evaluate this string:
Code Project is &Upper("too") cool! as "Code Project is TOO cool!"
Variables
One of SAScript's main design goals was to provide users with a way to access
program information as the program looped over its input data. When users are
adding expressions to their HTML templates, they often want to know the name of
the output folder that the current file is being written to. This allows them
to write HTML to access other files in that folder. This is accomplished in SAScript
through pre-defined variables: &Lower(curPath)
. This expression outputs
the current path, in lower case. ThumbNailer sets the value of "curPath" before evaluating
an HTML template.
Syntax
SAScript was designed to be as simple as possible, for users and programmers. So, to
keep parsing simple, it was designed as a stack-based language. This means that all
expressions consist of nested operators and parameters: &Mid(Upper("A little string"), 6, 2)
.
This outputs "LITTLE" - 6 characters starting at the second character of "A little string", upper case.
A simple definition of the language:
-
An SAScript expression is
&operator(zero or more parameters)
.
-
Each of the parameters can be a literal (quoted) text or a numeric value or it can be the result of another operator.
-
An expression starts at the "&" and extends to the first close parenthesis ")" that matches the
first open parenthesis "(" following the "&".
-
Input text that is not part of an expression is not parsed and is output
without modification.
Ex. 2 + 2 = &Add(2,2)
outputs "2 + 2 = 4".
-
An expression cannot start within quotes. Ex.
"This will not work &Len(curFile)"
.
Parameter Syntax
-
If literal text is used as a parameter to an operator, the text must be placed in double quotes.
-
Double quotes and backslashes in literal text must be preceded by a single backslash. This is just like C/C++ quoted string escapes.
-
Unquoted text is assumed to be a variable name. If a variable of that name doesn't exist for the given context, as error will occur.
-
If unquoted text contains whitespace, commas, parentheses or any other SAScript control characters, the parser will output an error string.
-
Variable names must not contain whitespace, commas, parentheses or any other SAScript control characters.
Variable Context
Because you might be parsing text streams from many different locations within your
program, some variables may not be applicable in all situations. To help with this,
SAScript variables can be associated with a particular "context". This tells the parser
that a variable is only available when the text being evaluated is in a certain section
of an HTML template, for example.
Variables can also be made local to a given instance of the parser. This allows even finer control of
the information that is available.
Macros
One of the more advanced features of SAScript is the ability to process user-defined
macro expressions. These allow users to write their own complex expressions and use
them wherever needed.
User-defined variables
Another advanced feature, the VarSet operator, allows users to create and modify their own variables (and any variables that your program creates,
too) at run-time. These variables last until the the evaluator goes away.&VarSet("varName", Upper("Hi There"))
- sets the variable 'varName' to the value "HI THERE".
VarSet is a powerful feature and you may want to disable it if you don't want your users messing around with the data you're providing.
Customization
-
Adding new operators to SAScript is very easy - four simple steps.
-
Adding and modifiying predefined variables is very easy - two simple steps.
-
Adding a macro is very easy - one function call.
-
You can easily change the parser to recognize different expression meta-characters; instead of
&operator(p1, p2)
, you can use:
-
$operator[p1 : p2]
-
%operator<p1 / p2>
-
#operator{p1 | p2}
- Or any other combination you can think of
-
The parser can use MFC's CString or you can use our own STL-based string class.
Integration
This is how you integrate SAScript into your application.
-
Add SAScriptLib to your workspace
-
Make sure you can #include "SAScrEval.h" (set the paths in your project settings)
-
Make your project dependent on SAScriptLib
-
Link to SAScriptLib.lib
Here's how you use it:
#include "SAScrEval.h"
CSAScrOpManager g_varOperManager;
CSAScrVariableMap globalVars;
globalVars.Add("snoopy", "white beagle", CTXALL);
CSAMacroMap globalMacros;
g_varOperManager.Initialize(globalMacros, globalVars);
CSAScrVariableMap userVars;
userVars.Add("lucy", "bossy girl", CTXALL);
userVars.Add("pigpen", "messy boy", CTXALL);
userVars.Add("linus", "blanket boy", CTX(eParseContext1));
CSAScriptEval eval(userVars);
csOutput = (const char *) eval.ParseString(csInput, eParseContext1);
Other Info.
SAScript was written with heavy use of the STL and no MFC or non-ANSI C functions.
This should make it fairly portable.
History
17 Jan 2002 - updated source and documentation
7 Aug 2002 - Incorporated Unicode changes made by James Twine
23 Dec 2002 - Fixed problem with single char string where string is a metacharacter.