Mercurial > ~dholland > hg > ag > index.cgi
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