Click here to Skip to main content
15,881,856 members
Articles / Programming Languages / C++
Article

SAScript

Rate me:
Please Sign up or sign in to vote.
4.33/5 (6 votes)
28 Dec 2002 76.4K   641   40   8
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.

  1. Add SAScriptLib to your workspace
  2. Make sure you can #include "SAScrEval.h" (set the paths in your project settings)
  3. Make your project dependent on SAScriptLib
  4. Link to SAScriptLib.lib
Here's how you use it:
// 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
United States United States
Chris Losinger was the president of Smaller Animals Software, Inc. (which no longer exists).

Comments and Discussions

 
Generalwhy do you try the velocity project in Apache Pin
liaohaiwen12-Jun-11 16:36
liaohaiwen12-Jun-11 16:36 
Generalok - spill it Pin
Darren Schroeder19-Jan-02 16:10
Darren Schroeder19-Jan-02 16:10 
GeneralRe: ok - spill it Pin
Chris Losinger19-Jan-02 18:06
professionalChris Losinger19-Jan-02 18:06 
GeneralEmbedded functions Pin
Brad Bruce15-Jan-02 2:16
Brad Bruce15-Jan-02 2:16 
GeneralRe: Embedded functions Pin
Chris Losinger15-Jan-02 4:38
professionalChris Losinger15-Jan-02 4:38 
QuestionHow can I assign values to variables? Pin
toby3-Jul-00 11:04
toby3-Jul-00 11:04 
I want to use a global variable, lets say $Data, and
read a file. For every read record, I want to do something
like "$Data=ReadLine;" in my C++ application.Then I want run $Data through SAScipt. I also want the script to be able update the $Data variable.

How can I do this? (A sample would help
AnswerRe: How can I assign values to variables? Pin
Chris Losinger4-Jul-00 9:57
professionalChris Losinger4-Jul-00 9:57 
GeneralUpdate Pin
Chris Losinger15-Jan-02 4:57
professionalChris Losinger15-Jan-02 4:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.