diff tests/agcl/oldagsrc/bcip.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/bcip.syn	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,330 @@
+{/*
+ bcip.syn  Version 1.0
+
+ A simple byte code compiler
+
+ Copyright (c) 1996-1999 Parsifal Software, All Rights Reserved.
+
+ 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 the following 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                  (  )
+   Built-in functions           log, exp, sqrt
+
+ All arithmetic is double precision floating point.
+
+ Statements may include expression statements, blocks, if/else
+ statements, while statements, do-while statements, or for
+ 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.
+
+ The parser is invoked by the constructor for the virtual machine
+ to parse the source code and compile it into byte code.
+
+ With this organization, it is possible to create various
+ virtual machine objects all of which use the same symbol dictionary,
+ so that all can operate on the same data array. Furthermore, if
+ there are multiple data arrays, all consistent with the same
+ symbol dictionary, then any virtual machine object created using the
+ given symbol dictionary can operate on any of the data arrays.
+
+ Thus a given virtual machine may operate on different data
+ arrays at different times. The data array, of course, must be
+ consistent with the symbol dictionary used to initialize the virtual
+ machine.
+
+ The symbol dictionary maps character strings to indices into the
+ data array, so that each unique variable name is assigned a
+ particular location in the data array. Different virtual
+ machines may be initialized with the same symbol dictionary. When
+ this is done, these virtual machines can all operate on the
+ same data array.
+
+ An override for the SYNTAX_ERROR macro defined by AnaGram and
+ the definition of the ScriptMethod class are in the bci.h
+ file. bci.cpp has function definitons for the ScriptMethod
+ class. bcidemo.cpp demonstrates one way to use the virtual
+ machine.
+
+ bcip.syn is compiled with the AnaGram parser generator yielding
+ bcip.h and bcip.cpp.
+
+ To build bcidemo, compile bcip.cpp, bci.cpp, cntnrs.cpp and bcidemo.cpp
+ and link them with your C++ compiler.
+
+ For information about AnaGram, visit http://www.parsifalsoft.com.
+*/
+
+#include <math.h>
+#include "bci.h"                  // defines external interface
+
+}
+// -- CONFIGURATION SECTION ----------------------------
+[
+  disregard white space
+  lexeme {real, name}
+  pointer input
+  parser name = bciParse
+  parser file name = "#.cpp"
+  reentrant parser
+  extend pcb {
+    AgStringDictionary *symbolDictionary;
+    AgStack<double> realList;                         // List of real constants
+    int compile(AgStringDictionary *, AgString);
+    CodeFragment code;
+
+    AgCharStack charStack;           // Stack to accumulate variable names
+    int locateVariable(int k);    // Identify variable named on character stack
+    int stashReal(double);
+    CodeFragment codeIfElse(CodeFragment &, CodeFragment &, CodeFragment &);
+    CodeFragment codeWhile(CodeFragment &, CodeFragment &);
+    CodeFragment codeDoWhile(CodeFragment &, CodeFragment &);
+    CodeFragment codeFor(CodeFragment &, CodeFragment &, CodeFragment &, CodeFragment &);
+  }
+  wrapper {CodeFragment}
+]
+
+(CodeFragment) input string $                          // specify grammar token
+ -> statements:x, eof                                              =x.cat(HLT);
+
+(CodeFragment) statements
+ ->                                                            =CodeFragment();
+ -> statements:x, statement:y                                        =x.cat(y);
+
+(CodeFragment) statement
+ -> open statement
+ -> closed statement
+
+ // Any statement that could be followed by an else is an open statement
+(CodeFragment) open statement
+ -> if clause:x, statement:s                      =x.cat(BRF, s.size()).cat(s);
+ -> if clause:x, closed statement:s1,
+      "else", open statement:s2                       =PCB.codeIfElse(x,s1,s2);
+ -> while clause:x, open statement:s                       =PCB.codeWhile(x,s);
+ -> "for", '(', expression:init, ';', expression:cond, ';',
+      expression:inc, ')', open statement:s   =PCB.codeFor(init, cond, inc, s);
+
+ // A statement that cannot be followed by "else" is a closed statement
+(CodeFragment) closed statement
+ -> simple statement
+ -> if clause:x, closed statement:s1, "else",
+      closed statement:s2                             =PCB.codeIfElse(x,s1,s2);
+ -> while clause:x, closed statement:s                     =PCB.codeWhile(x,s);
+ -> "do", statement:s, while clause:x, ';'               =PCB.codeDoWhile(s,x);
+ -> "for", '(', expression:init, ';', expression:cond, ';',
+      expression:inc, ')', closed statement:s =PCB.codeFor(init, cond, inc, s);
+
+(CodeFragment) if clause
+ -> "if", '(', expression:x, ')'                                            =x;
+
+(CodeFragment) while clause
+ -> "while", '(', expression:x, ')'                                         =x;
+
+(CodeFragment) simple statement
+ -> expression:x, ';'                                              =x.cat(POP);
+ -> ';'                                                        =CodeFragment();
+ -> '{', statements:s, '}'                                                  =s;
+
+(CodeFragment) expression
+ -> assignment expression
+ -> expression:x, ',', assignment expression:y              =x.cat(POP).cat(y);
+
+(CodeFragment) assignment expression
+ -> conditional expression
+ -> name:k, '=',  assignment expression:x                     =x.cat(STORE, k);
+ -> name:k, "+=", assignment expression:x                      =x.cat(ADDM, k);
+ -> name:k, "-=", assignment expression:x                      =x.cat(SUBM, k);
+ -> name:k, "*=", assignment expression:x                       =x.cat(MULM,k);
+ -> name:k, "/=", assignment expression:x                      =x.cat(DIVM, k);
+
+(CodeFragment) conditional expression
+ -> logical or expression
+ -> logical or expression:c, '?', expression:x,
+      ':', conditional expression:y                   =PCB.codeIfElse(c, x, y);
+
+(CodeFragment) logical or expression
+ -> logical and expression
+ -> logical and expression:x, "||",
+      logical or expression:y                      =x.cat(OR, y.size()).cat(y);
+
+(CodeFragment) logical and expression
+ -> equality expression
+ -> equality expression:x, "&&",
+      logical and expression:y                    =x.cat(AND, y.size()).cat(y);
+
+(CodeFragment) equality expression
+ -> relational expression
+ -> equality expression:x, "==", relational expression:y     =x.cat(y).cat(EQ);
+ -> equality expression:x, "!=", relational expression:y     =x.cat(y).cat(NE);
+
+(CodeFragment) relational expression
+ -> additive expression
+ -> relational expression:x, '<',  additive expression:y     =x.cat(y).cat(LT);
+ -> relational expression:x, "<=", additive expression:y     =x.cat(y).cat(LE);
+ -> relational expression:x, '>',  additive expression:y     =x.cat(y).cat(GT);
+ -> relational expression:x, ">=", additive expression:y     =x.cat(y).cat(GE);
+
+(CodeFragment) additive expression
+ -> multiplicative expression
+ -> additive expression:x, '+', multiplicative expression:y =x.cat(y).cat(ADD);
+ -> additive expression:x, '-', multiplicative expression:y =x.cat(y).cat(SUB);
+
+(CodeFragment) multiplicative expression
+ -> unary expression
+ -> multiplicative expression:x, '*', unary expression:y    =x.cat(y).cat(MUL);
+ -> multiplicative expression:x, '/', unary expression:y    =x.cat(y).cat(DIV);
+
+(CodeFragment) unary expression
+ -> factor
+ -> '-', unary expression:x                                        =x.cat(NEG);
+ -> '+', unary expression:x                                                = x;
+
+(CodeFragment) factor
+ -> primary
+ -> primary:x, "**", unary expression:y                     =x.cat(y).cat(POW);
+
+(CodeFragment) primary
+ -> real:x                                       =CodeFragment().cat(PUSHI, x);
+ -> name:k                                        =CodeFragment().cat(PUSH, k);
+ -> "log", '(', assignment expression:x, ')'                       =x.cat(LOG);
+ -> "exp", '(', assignment expression:x, ')'                       =x.cat(EXP);
+ -> "sqrt", '(', assignment expression:x, ')'                     =x.cat(SQRT);
+ -> '(', expression:x, ')'                                                  =x;
+ -> '!', primary:x                                                 =x.cat(NOT);
+
+// -- LEXICAL UNITS ------------------------------------------------
+digit   = '0-9'
+eof     = 0
+letter  = 'a-z' + 'A-Z' + '_'
+
+(void) white space
+ -> ' ' + '\t' + '\f' + '\v' + '\r' + '\n'
+ -> "/*", ~eof?..., "*/"                                     // C style comment
+ -> "//", ~(eof+'\n')?..., '\n'                            // C++ style comment
+
+(int) real
+ -> simple real:x                                            =PCB.stashReal(x);
+ -> simple real:x, 'e'+'E', '+'?,exponent:e        =PCB.stashReal(x*pow(10,e));
+ -> simple real:x, 'e'+'E', '-',exponent:e        =PCB.stashReal(x*pow(10,-e));
+
+(double) simple real
+ -> integer part:i, '.', fraction part:f                                 = i+f;
+ -> integer part, '.'?
+ -> '.', fraction part:f                                                   = f;
+
+(double) integer part
+ -> digit:d                                                            = d-'0';
+ -> integer part:x, digit:d                                     = 10*x + d-'0';
+
+(double) 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';
+
+(int) name
+ -> name string     =PCB.symbolDictionary->identify(PCB.charStack.popString());
+
+name string
+ -> letter: c                                    =PCB.charStack.push((char) c);
+ -> name string, letter+digit: c                 =PCB.charStack.push((char) c);
+
+{ // Begin embedded C
+
+#define SYNTAX_ERROR
+
+int bciParse_pcb_struct::stashReal(double x) {
+  int n = realList.size();
+  realList.push(x);
+  return n;
+}
+
+CodeFragment bciParse_pcb_struct::codeIfElse(CodeFragment &condition,
+                                             CodeFragment &trueStatement,
+                                             CodeFragment &falseStatement)
+{
+  return condition.cat(BRF, trueStatement.size() + 2)
+                  .cat(trueStatement)
+                  .cat(BR, falseStatement.size())
+                  .cat(falseStatement);
+}
+
+CodeFragment bciParse_pcb_struct::codeWhile(CodeFragment &condition,
+                                            CodeFragment &statement)
+{
+  // loop back distance is length of statement + length of condition + 2 branch instructions
+  int loopBackDistance = condition.size() + statement.size() + 4;
+  return condition.cat(BRF, statement.size() + 2)       // size of statement +size of loopback
+                  .cat(statement)
+                  .cat(BR, -loopBackDistance);
+}
+
+CodeFragment bciParse_pcb_struct::codeDoWhile(CodeFragment &statement,
+                                              CodeFragment &condition)
+{
+  // loop back distance is
+  //    length of statement + length of condition + 1 branch instruction
+  int loopBackDistance = statement.size() + condition.size() + 2;
+  return statement.cat(condition)
+                  .cat(BRT, -loopBackDistance);
+}
+
+CodeFragment bciParse_pcb_struct::codeFor(CodeFragment &initializer,
+                                          CodeFragment &condition,
+                                          CodeFragment &increment,
+                                          CodeFragment &statement)
+{
+  // Calculate the length of the jump back at the bottom of the loop
+  // It consists of the length of the increment, condition and statement
+  // CodeFragments + 5 inserted Bytecodes: 1 Pop, and 2 each for each of
+  // two branches
+  int loopBackDistance = increment.size() + condition.size() + statement.size() + 5;
+
+  // Put it all together
+  return initializer.cat(POP)                           // clear expression value from stack
+                    .cat(BR, increment.size() + 1)      // Skip increment on first time through
+                    .cat(increment).cat(POP)            // clear expresson value from stack
+                    .cat(condition)
+                    .cat(BRF, statement.size() + 2)     // exit when condition is false
+                    .cat(statement)
+                    .cat(BR, -loopBackDistance);
+}
+
+int bciParse_pcb_struct::compile(AgStringDictionary *s, AgString text) {
+  symbolDictionary = s;
+  charStack.reset();
+  pointer = (unsigned char *) text.ptr();
+  bciParse(this);
+  if(exit_flag != AG_SUCCESS_CODE) return 1;
+  code = bciParse_value(this);
+  return 0;
+}
+
+} // End of embedded C
+/********************* End of bcip.syn ************************/
+