diff examples/mpp/ex.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/examples/mpp/ex.syn	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,314 @@
+{
+/*
+ * AnaGram, a System for Syntax Directed Programming
+ * C Macro preprocessor
+ * Constant Expression Evaluator Module
+ *
+ * Copyright 1993-2000 Parsifal Software. All Rights Reserved.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "mpp.h"
+}
+
+[
+  //far tables                             // uncomment for 16 bit environment
+ ~allow macros
+  line numbers
+  //escape backslashes                     // uncomment if using MSVC++
+  default token type = long
+  default input type = token
+ ~declare pcb
+ ~diagnose errors
+  error trace
+  event driven
+  input values
+ ~test range
+ ~lines and columns
+  enum {
+    eof               =0,
+    SPACE             =' ',
+    ANDAND            ='A', // "&&"
+    ANDassign,              // "&="
+    ARROW,                  // "->"
+    CONCAT,                 // "##"
+    DECR,                   // "--"
+    DIVassign,              // "/="
+    ELLIPSIS,               // "..."
+    EQ,                     // "=="
+    ERassign,               // "^="
+    GE,                     // ">="
+    ICR,                    // "++"
+    LE,                     // "<="
+    LS,                     // "<<"
+    LSassign,               // "<<="
+    MODassign,              // "%="
+    MINUSassign,            // "-="
+    MULTassign,             // "*="
+    NE,                     // "!="
+    ORassign,               // "|="
+    OROR,                   // "||"
+    PLUSassign,             // "+="
+    RS,                     // ">>"
+    RSassign,               // ">>="
+    CHARACTERconstant,      // character constant
+    STRINGliteral,          // character string
+    HEXconstant       =129,
+    OCTconstant,
+    DECconstant,
+    FLOATconstant,          // real
+    NAME,
+    AUTO,                   // "auto"
+    BREAK,                  // "break"
+    CASE,                   // "case"
+    CHAR,                   // "char"
+    CONSTANT,               // "const"
+    CONTINUE,               // "continue"
+    DEFAULT,                // "default"
+    DO,                     // "do"
+    DOUBLE,                 // "double"
+    ELSE,                   // "else"
+    ENUM,                   // "enum"
+    EXTERN,                 // "extern"
+    FLOAT,                  // "float"
+    FOR,                    // "for"
+    GOTO,                   // "goto"
+    IF,                     // "if"
+    INT,                    // "int"
+    LONG,                   // "long"
+    REGISTER,               // "register"
+    RETURN,                 // "return"
+    SHORT,                  // "short"
+    SIGNED,                 // "signed"
+    SIZEOF,                 // "sizeof"
+    STATIC,                 // "static"
+    STRUCT,                 // "struct"
+    SWITCH,                 // "switch"
+    TYPEDEF,                // "typedef"
+    UNION,                  // "union"
+    UNSIGNED,               // "unsigned"
+    VOIDkey,                // "void"
+    VOLATILE,               // "volatile"
+    WHILE,                  // "while"
+    UNRECOGNIZED,
+  }
+  parser file name = "#.cpp"
+]
+
+expression evaluator $
+ -> exp, eof
+
+exp
+ -> conditional exp
+
+conditional exp
+ -> logical or exp
+ -> logical or exp:c, '?', conditional exp:x, ':',
+    conditional exp:y                                  = c != 0 ? x : y;
+
+logical or exp
+ -> logical and exp
+ -> logical or exp:x, OROR, logical and exp:y          =x != 0 || y!=0;
+
+logical and exp
+ -> inclusive or exp
+ -> logical and exp:x, ANDAND, inclusive or exp:y      =x != 0 && y !=0;
+
+inclusive or exp
+ -> exclusive or exp
+ -> inclusive or exp:x, '|', exclusive or exp:y        =x | y;
+
+exclusive or exp
+ -> and exp
+ -> exclusive or exp:x, '^', and exp:y                 =x ^ y;
+
+and exp
+ -> equality exp
+ -> and exp:x, '&', equality exp:y                     =x & y;
+
+equality exp
+ -> relational exp
+ -> equality exp:x, EQ, relational exp:y               =x == y;
+ -> equality exp:x, NE, relational exp:y               =x != y;
+
+relational exp
+ -> shift exp
+ -> relational exp:x, '<', shift exp:y                 =x < y;
+ -> relational exp:x, '>', shift exp:y                 =x > y;
+ -> relational exp:x, LE, shift exp:y                  =x <= y;
+ -> relational exp:x, GE, shift exp:y                  =x >= y;
+
+shift exp
+ -> additive exp
+ -> shift exp:x, LS, additive exp:y                    =x << y;
+ -> shift exp:x, RS, additive exp:y                    =x >> y;
+
+additive exp
+ -> multiplicative exp
+ -> additive exp:x, '+', multiplicative exp:y          =x + y;
+ -> additive exp:x, '-', multiplicative exp:y          =x - y;
+
+multiplicative exp
+ -> unary exp
+ -> multiplicative exp:x, '*', unary exp:y             =x * y;
+ -> multiplicative exp:x, '/', nonzero:y               =x / y;
+ -> multiplicative exp:x, '%', nonzero:y               =x % y;
+
+nonzero
+  -> unary exp: x ={
+      if (x != 0) return x;
+      syntax_error("Divide by Zero");
+      PCB.exit_flag = 5;
+      return x;
+    }
+
+unary exp
+ -> primary exp
+ -> '+', unary exp:x            = x;
+ -> '-', unary exp:x            = -x;
+ -> '~', unary exp:x            = ~x;
+ -> '!', unary exp:x            = !x;
+
+primary exp
+ -> HEXconstant:x               =decode("%lx",x.handle);
+ -> OCTconstant:x               =decode("%lo",x.handle);
+ -> DECconstant:x               =decode("%ld",x.handle);
+ -> CHARACTERconstant:x         =decode("'%lc'",x.handle);
+ -> NAME                        =0;
+ -> '(', conditional exp:x, ')' =x;
+
+
+{                                      // Embedded C
+#include <stdio.h>
+
+
+// Macro Definitions
+
+#define PCB (*ex_pcb)
+#define SYNTAX_ERROR syntax_error("Syntax error in constant expression");
+
+
+// Static data
+
+static ex_pcb_type *ex_pcb;            // Pointer to active pcb
+
+
+/*
+
+decode() is a simple function to recover the numeric value of a
+token. Its task is somewhat simplified by the fact that the only
+values allowed in this example are longs.
+
+*/
+
+static long decode(const char *fmt, unsigned ndx) {
+  long v;
+  sscanf(td[ndx], fmt, &v);
+  return v;
+}
+
+
+// Members of expression_evaluator Class
+
+
+// Constructor
+
+/*
+  Each expression_evaluator has its own parser control block.
+  Therefore, before calling ex() or its initializer init_ex() it is
+  necessary to make sure the pcb pointer for ex() is correctly set.
+*/
+
+expression_evaluator::expression_evaluator() {
+  ex_pcb = &pcb;                       // set up pointer to pcb
+  init_ex();                           // init parser
+}
+
+
+// Reset expression_evaluator
+
+token_sink& reset(expression_evaluator &x) {
+  ex_pcb = &x.pcb;                     // set up pointer to pcb
+  init_ex();                           // init parser
+  return x;
+}
+
+
+// Xmit Token to expression_evaluator
+
+/*
+  There could be space tokens in the input to the expression
+  evaluator, but they are never significant so it is acceptable to
+  filter them out on input.
+
+  If the expression_evaluator has encountered an error, there is no
+  point in giving it any further input.
+
+  Otherwise, the input_code and input_value fields of the pcb are set
+  up, the pcb pointer for ex is set, and ex() is called to deal with
+  the token.
+
+  When looping, it is only necessary to set up ex_pcb at the
+  beginning of the loop.
+*/
+
+token_sink& expression_evaluator::operator << (token t) {
+  if (t.id == SPACE || pcb.exit_flag != AG_RUNNING_CODE) return *this;
+  pcb.input_code = t.id;
+  pcb.input_value = t;
+  ex_pcb = &pcb;
+  ex();
+  return *this;
+}
+
+token_sink &expression_evaluator::operator << (token *tp) {
+  ex_pcb = &pcb;
+  while (pcb.exit_flag == AG_RUNNING_CODE) {
+    if (pcb.input_code == SPACE) continue;
+    pcb.input_code = tp->id;
+    pcb.input_value = *tp++;
+    ex();
+  }
+  return *this;
+}
+
+
+// Return Value of expression_evaluator
+
+/*
+  The (long) cast operator is overloaded to provide a mechanism to
+  retrieve the value of the expression evaluated by the
+  expression_evaluator.
+
+  If there was a syntax error, the return value is zero.
+*/
+
+expression_evaluator::operator long() {
+  ex_pcb = &pcb;
+  if (pcb.exit_flag == AG_SUCCESS_CODE) return ex_value();
+  else return 0;
+}
+
+/*
+// Check expression_evaluator for error
+
+int error(expression_evaluator &x) {
+  return x.pcb.exit_flag != AG_SUCCESS_CODE;
+}
+*/
+}                                      // End of Embedded C