SAScript






4.33/5 (6 votes)
Feb 28, 2000

77080

641
A simple stack-based language that you can easily add to your projects
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
// this gets everything #include "SAScrEval.h" // the one and only operator manager. // this handles operators, macros and variables. // // this should be declared at a global level! CSAScrOpManager g_varOperManager; //... the following should be done early in your program, before any // parsing occurs // *** first, set up global data // variables available to all CSAScriptEval objects CSAScrVariableMap globalVars; // variable "snoopy" has a value of "white beagle" // and is available in all contexts globalVars.Add("snoopy", "white beagle", CTXALL); // macros available to all CSAScriptEval objects // (don't define any for this example) CSAMacroMap globalMacros; // *** intialize our SAScript global operator/variable manager g_varOperManager.Initialize(globalMacros, globalVars); //... these are the general steps for creating and using a local // parsing object // *** create local variables // create a local variable map - these are variables that are // specific to this instance of CSAScriptEval. vars that are // common to all instances should be added when g_varOperManager // is initialized (above). CSAScrVariableMap userVars; // add some variables // userVars.Add("lucy", "bossy girl", CTXALL); userVars.Add("pigpen", "messy boy", CTXALL); // variable 'linus' will only be visible in 'eParseContext1' userVars.Add("linus", "blanket boy", CTX(eParseContext1)); // declare an evaluator . initialize it with our local variables CSAScriptEval eval(userVars); // *** evaluate the text - specify context "eParseCtx1". 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.