diff tests/agcl/oldagsrc/asiwdp.syn @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/agcl/oldagsrc/asiwdp.syn	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,429 @@
+{
+/*
+ asiwdp.syn
+
+ ASI -- A Simple Interpreter
+ Copyright (c) 1999 Parsifal Software, All Rights Reserved.
+
+ This implementation of ASI uses C++ and was developed
+ as part of the ASI Windows Demonstration program to
+ illustrate the use of the "reentrant parser" switch
+ and the "extend pcb" statement to create a thread-safe
+ parser. The example program uses a Microsoft Foundation
+ Class program to demonstrate multiple instances of an
+ AnaGram parser running concurrently on separate threads.
+
+ The expression syntax is borrowed from C but with the
+ addition of the FORTRAN exponentiation operator (**).
+
+ The cast, increment, and decrement operators are not
+ implemented, nor are operations that are defined only
+ for integers:
+   Bitwise logical operators:   &, |, ^, ~, &=, |=, ^=
+   Remainder operators:         %, %=
+   Shift operators:             <<, >>, >>=, <<=
+
+ The supported operations are:
+   Assignment operators:        =, +=, -=, *=, /=
+   Conditional expressions:     ? :
+   Logical operators:           !, &&, ||
+   Comparison operators:        ==, !=, <, <=, >, >=
+   Binary arithmetic operators: +, -, *, /
+   Exponentiation:              **
+   Unary arithmetic operators:  +, -
+   Parentheses
+   Function calls
+
+ All arithmetic is double precision floating point.
+
+ Statements may include expression statements, blocks, if/else statements
+ or while statements, following the rules of C.
+
+ The statement syntax has been written to avoid the conventional
+ if/else ambiguity.
+
+ There are no declarations. All variables are presumed to be double.
+
+ Input strings may contain any number of statements. White space may be
+ used freely, including both C and C++ style comments.
+
+ asiwd uses the following classes, defined in asiwdef.h:
+	 CharStack                     // Used to accumulate variable names
+	 SymbolTable                   // Maintains variable names and values
+	 WhileStack                    // Maintains state of active while loops
+	 Location                      // Records location in source text
+
+ The AnaGram parser generator uses asiwdp.syn as a specification to
+ create a C++ parser file asiwdp.cpp and a companion header file,
+ asiwdp.h.
+
+ For information about AnaGram, visit http://www.parsifalsoft.com.
+*/
+
+#include "asiwdef.h"
+
+}
+// -- CONFIGURATION SECTION ----------------------------
+[
+  default token type = double
+  disregard white space                         // Skip over white space
+  lexeme {real, name}                           // No white space in reals or names
+  pointer input                                 // Take input from array in memory
+  parser name = asi                             // Name parser function
+  parser file name = "#.cpp"                    // Name parser file
+  line numbers                                  // Generate #line directives
+	reentrant parser                              // Make parser reentrant
+	extend pcb {                                  // Add declarations to parser control block
+    CharStack charStack;                        // Stack to accumulate variable names
+		WhileStack whileStack;                      // Stack of active while loops
+		SymbolTable *symbolTable;                   // Pointer to external symbol table
+
+		void pushChar(int c);                       // Add character to character stack
+		double *locateValue(int k);                 // Identify variable named on character stack
+		void stackLoop(const Location &c);          // Provide for nested while loops
+		Location location();                        // Capture current location of parse
+		void setLocation(const Location &l);        // Set location of parse
+		void loopContinue();                        // Set location to continue current while loop
+		void loopExit();                            // Set location to exit current while loop
+		double checkZero(double value);             // Check for zero divisor
+
+		// External interface to the parser
+    int interpret(char *text, SymbolTable *s);  // Parse instructions in text, using variables defined in s
+	}
+]
+
+(void) input string $                           // specify grammar token
+ -> statements?, eof
+
+(void) statements
+ -> statement
+ -> statements, statement
+
+/*
+  Syntax to skip over statements without executing them.
+	This syntax is required for if statements and while loops.
+
+  The skip logic is used to do a preliminary scan of while
+	statements to identify the location of the while condition and
+	the exit point. Then, by manipulating the pointer field of the
+	parser control block, the while loop can be scanned as
+	many times as is necessary.
+
+  This syntax also shows the bare bones of the technique for
+	handling the conventional if/else ambiguity correctly, without
+	recourse to methods of less than complete rigor.
+
+  To deal with the if/else problem, we classify statements into
+	two classes: those which contain a dangling if clause and those
+  thatdon't. We call the former "open statements" and the
+	latter "closed statements".
+
+  Note that one effect of this classification is that we must
+	implement the while statment twice: once controlling a
+	closed statement and once controlling an open	statement.
+*/
+
+(void) skip statement
+ -> skip open statement
+ -> skip closed statement
+
+(void) skip closed statement
+ -> statement text?, ';'
+ -> balanced braces
+ -> "if", balanced parens, skip closed statement, "else", skip closed statement
+ -> "while", balanced parens, skip closed statement
+
+skip open statement
+ -> "if", balanced parens, skip statement
+ -> "if", balanced parens, skip closed statement, "else", skip open statement
+ -> "while", balanced parens, skip open statement
+
+/*
+  The syntax for statements is essentially the same as for skipping
+  statements. The primary difference is that expressions are actually
+  evaluated, rather than skipped, and the conditions in if statements
+  are evaluated and acted upon.
+*/
+
+(void) statement
+ -> open statement
+ -> closed statement
+
+(void) closed statement
+ -> expression, ';'
+ -> ';'
+ -> '{', '}'
+ -> '{', statements, '}'
+ -> true if condition, closed statement, "else", skip closed statement
+ -> false if condition, skip closed statement, "else", closed statement
+ -> closed while, execute while
+
+/*
+  The following syntax uses a semantically determined production
+  to separate if conditions into true and false conditions.
+*/
+
+(void) open statement
+ -> true if condition, statement
+ -> false if condition, skip statement
+ -> true if condition, closed statement, "else", skip open statement
+ -> false if condition, skip closed statement, "else", open statement
+ -> open while, execute while
+
+(void) true if condition, false if condition
+ -> "if", '(', expression:x, ')'     ={if (x == 0) CHANGE_REDUCTION(false_if_condition);}
+
+(void) closed while
+ -> while:c, balanced parens, skip closed statement =PCB.stackLoop(c);
+
+(void) open while
+ -> while:c, balanced parens, skip open statement   =PCB.stackLoop(c);
+
+(Location) while
+ -> "while"              =PCB.location();
+
+/*
+  The "execute while" syntax does not actually occur in the
+	input file. It is actually the implementation of the while
+	loop. The "closed while" productions identify and stack
+	the locations of the while condition and the exit location in
+	the script file. The "while loop" productions reset the input
+	pointer to the while condition. On encountering a false
+	condition, the "execute while" production restores the input
+	pointer to the end of the while loop so that normal parsing
+	can then continue.
+*/
+
+(void) execute while
+ -> while loop, false while condition                =PCB.loopExit();
+
+(void) while loop
+ ->
+ -> while loop, true while condition, statement      =PCB.loopContinue();
+
+// Semantically determined production to control parsing of while loop
+
+(void) true while condition, false while condition
+ -> '(', expression:x, ')'  =x == 0 ? CHANGE_REDUCTION(false_while_condition) : 0;
+
+/*
+  The following expression syntax is essentially that of C/C++.
+  An exponentiation operator, similar to that in Fortran has
+  been added. Note that the right hand operand of the && and ||
+  operators is evaluated whether it needs to be or not.
+*/
+
+expression
+ -> conditional expression
+ -> name:pointer, '=',  expression:x                  =*pointer = x;
+ -> name:pointer, "+=", expression:x                 =*pointer += x;
+ -> name:pointer, "-=", expression:x                 =*pointer -= x;
+ -> name:pointer, "*=", expression:x                 =*pointer *= x;
+ -> name:pointer, "/=", expression:x                 =*pointer /= x;
+
+conditional expression
+ -> logical or expression
+ -> logical or expression:c, '?',
+      expression:x, ':', conditional expression:y                 =c ? x : y;
+
+logical or expression
+ -> logical and expression
+ -> logical or expression:x, "||", logical and expression:y      = x ? x : y;
+
+logical and expression
+ -> equality expression
+ -> logical and expression:x, "&&", equality expression:y         =x ? y : x;
+
+equality expression
+ -> relational expression
+ -> equality expression:x, "==", relational expression:y             =x == y;
+ -> equality expression:x, "!=", relational expression:y             =x != y;
+
+relational expression
+ -> additive expression
+ -> relational expression:x, '<',  additive expression:y              =x < y;
+ -> relational expression:x, "<=", additive expression:y             =x <= y;
+ -> relational expression:x, '>',  additive expression:y              =x > y;
+ -> relational expression:x, ">=", additive expression:y             =x >= y;
+
+additive expression
+ -> multiplicative expression
+ -> additive expression:x, '+', multiplicative expression:y           =x + y;
+ -> additive expression:x, '-', multiplicative expression:y           =x - y;
+
+multiplicative expression
+ -> unary expression
+ -> multiplicative expression:x, '*', unary expression:y              =x * y;
+ -> multiplicative expression:x, '/', unary expression:y =x/PCB.checkZero(y);
+
+unary expression
+ -> factor
+ -> '-', unary expression:x                                              =-x;
+ -> '+', unary expression:x                                               =x;
+
+factor
+ -> primary
+ -> primary:x, "**", unary expression:y                            =pow(x,y);
+
+primary
+ -> real
+ -> name:valuePointer                                         =*valuePointer;
+ -> "log", '(', expression:x, ')'                                    =log(x);
+ -> "exp", '(', expression:x, ')'                                    =exp(x);
+ -> "sin", '(', expression:x, ')'                                    =sin(x);
+ -> "cos", '(', expression:x, ')'                                    =cos(x);
+ -> "tan", '(', expression:x, ')'                                    =tan(x);
+ -> '(', expression:x, ')'                                                =x;
+ -> '!', primary:x                                                  = x == 0;
+
+// -- LEXICAL UNITS ------------------------------------------------
+blank          = ' ' + '\t' + '\f' + '\v' + '\r' + '\n'
+digit          = '0-9'
+eof            = 0
+letter         = 'a-z' + 'A-Z' + '_'
+statement char = 32..126 - blank - ';' - '(' - ')' - '{' - '}'
+
+(void) white space
+ -> blank
+ -> "/*", ~eof?..., "*/"                          // C style comment
+ -> "//", ~(eof+'\n')?..., '\n'                 // C++ style comment
+
+// Productions for use skipping over statements
+
+statement text
+	-> statement char
+	-> balanced parens
+	-> statement text, statement char
+	-> statement text, balanced parens
+	-> statement text, balanced braces
+
+balanced parens
+ -> '(', statement text?, ')'
+
+ balanced braces
+	-> '{', [statement text?, ';']..., '}'
+	-> '{', balanced braces, '}'
+
+/*
+	Identifying variable names
+
+  Characters in a name string are pushed onto the character
+	stack. The integer value of the name string token is the
+	length of the string on the stack.
+
+  The locate function returns a pointer to the value of the
+	named variable. If the variable has not been previously
+	referenced, its value is initialized to zero.
+*/
+
+(int) name string
+ -> letter: c                                       =PCB.charStack.push(c), 1;
+ -> name string:k, letter+digit: c                  =PCB.charStack.push(c), k+1;
+
+(double *) name
+ -> name string:k                                   =PCB.locateValue(k);
+
+// Parsing and evaluating numeric constants
+
+real
+ -> simple real
+ -> simple real:x, 'e'+'E', '+'?,exponent:e            =x*pow(10,e);
+ -> simple real:x, 'e'+'E', '-',exponent:e            =x*pow(10,-e);
+
+simple real
+ -> integer part:i, '.', fraction part:f                      = i+f;
+ -> integer part, '.'?
+ -> '.', fraction part:f                                        = f;
+
+integer part
+ -> digit:d                                                 = d-'0';
+ -> integer part:x, digit:d                          = 10*x + d-'0';
+
+fraction part
+ -> digit:d                                            =(d-'0')/10.;
+ -> digit:d, fraction part:f                       =(d-'0' + f)/10.;
+
+(int) exponent
+ -> digit:d                                                 = d-'0';
+ -> exponent:x, digit:d                              = 10*x + d-'0';
+
+
+{ // begin embedded C
+
+#include <math.h>
+
+// Check for division by zero
+double asi_pcb_type::checkZero(double value) {
+  if (value) return value;
+  error_message = "Divide by Zero";
+	exit_flag = AG_SEMANTIC_ERROR_CODE;
+  return 1;
+}
+
+// external interface to the parser
+int asi_pcb_type::interpret(char *text, SymbolTable *st) {
+	symbolTable = st;
+  charStack.reset();
+  pointer = (unsigned char *) text;
+  asi(this);
+  return exit_flag != AG_SUCCESS_CODE;
+}
+
+/*
+  locate value of variable whose name is given by the top k characters on the
+  character stack.
+  Return a pointer so the value can be either fetched or stored
+*/
+
+double *asi_pcb_type::locateValue(int k) {
+	double *pointer = &symbolTable->locate(charStack.popString(k)).value;
+	if (symbolTable->overflow()) {
+		error_message = "Symbol table overflow";
+		exit_flag = AG_SEMANTIC_ERROR_CODE;
+	}
+	return pointer;
+}
+
+// Encapsulate current location in source text
+Location asi_pcb_type::location() {
+	return Location(pointer, line, column);
+}
+
+// Set source file location for loop continuation
+void asi_pcb_type::loopContinue() {
+	setLocation(whileStack.continueLocation());
+}
+
+// Set source file location for loop exit
+void asi_pcb_type::loopExit() {
+	setLocation(whileStack.exitLocation());
+	whileStack.pop();
+}
+
+// Push character onto character stack
+void asi_pcb_type::pushChar(int c) {
+	if (charStack.push(c)) {
+		error_message = "Name is too long";
+		exit_flag = AG_SEMANTIC_ERROR_CODE;
+	}
+}
+
+// Set parse location in source text
+void asi_pcb_type::setLocation(const Location &l) {
+	pointer = l.pointer;
+	line = l.line;
+	column = l.column;
+}
+
+// Save currently active loop, if any, and init nested loop
+void asi_pcb_type::stackLoop(const Location &c) {
+	// Current source location is exit location for loop
+	// c is the continue location
+	if (whileStack.push(c, location())) {
+		error_message = "While stack overflow";
+		exit_flag = AG_SEMANTIC_ERROR_CODE;
+	}
+	setLocation(c);                // Set location to loop condition
+}
+
+} // end of embedded C