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