view tests/agcl/oldagsrc/bciastp.syn @ 17:12171da8943f

Don't refer to CVS.
author David A. Holland
date Tue, 31 May 2022 01:56:37 -0400
parents 13d2b8934445
children
line wrap: on
line source

{
/*
 BCIAST.SYN

 Compiler for Byte Code Interpreter (using parse tree)
 Copyright (c) 1997 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 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

 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.

 vmParse makes the following external calls:
   void pushChar(int character);
     Push the specified character onto a character stack.

   int locateVariable(int nameLength);
     Pop the last nameLength characters from the character stack
     and, treating them as the name of a variable, return an
     index into the variable array.

 Overrides for macros defined by AnaGram, such as SYNTAX_ERROR
 are included in VMDEFS.H

 VMPT.SYN is compiled with the AnaGram parser generator
 yielding VMPT.H and VMPT.CPP.

 To build VMPT, compile and link VMPT.CPP, VMDEMO.CPP and PTREE.CPP
 with your C++ compiler.

 For information about AnaGram, visit http://www.parsifalsoft.com.
*/

#include "bciast.h"
#include "agstk.h"             // Defines AgStack<Object>
#include "agstr.h"             // Defines AgString et al
#include <math.h>              // for pow()
#include "ptree.h"

//typedef AgStack<Statement *> StatementList;

}
// -- CONFIGURATION SECTION ----------------------------
[
  disregard white space
  lexeme {real, name}
  pointer input
  parser name = astParse
  parser file name = "#.cpp"
  reentrant parser

  wrapper {AgStack<Statement *>, AgString}

  // Put the following in the parser control block for use during parsing
  extend pcb {
    // Maps symbol names to variables
    // AgSharedStringDictionary symbolDictionary;
    AbstractSyntaxTree *ast;

    // Temporary space to accumulate identifiers while parsing
    AgString charStack;
  }
]

/*
 * Mark input string with $ to indicate it is the "grammar token",
 * that is, the whole of the input we're intending to parse.
 */
(Program *) input string $
 -> statements:s, eof                         = PCB.ast->makeProgram(s);

/*
 * Zero or more statements. Generate a list of pointers to
 * statement descriptors.
 */
(AgStack<Statement *>) statements
 ->                                            =AgStack<Statement *>();
 -> statements:s, statement:x                  =s.push(x);

/*
 * A single statement.
 *
 * Here, an "open" statement is a statement that can legally be
 * followed by an "else" keyword. A "closed" statement is one that
 * cannot.
 *
 * This resolves the common if-then-else ambiguity. See ifelse.html for
 * a discussion of the ambiguity and this technique for resolving it.
 */
(Statement *) statement
 -> closed statement
 -> open statement

/*
 Any statement than can accept a dengling else clause
 is an open statement
*/

(Statement *) open statement
 -> "if", '(', expression:x, ')',
      statement:s                            = PCB.ast->makeIfStatement(x, s);
 -> "if", '(', expression:x, ')',
      closed statement:s1,
    "else",
      open statement:s2                      = PCB.ast->makeIfElseStatement(x,s1,s2);
 -> "while", '(', expression:x, ')',
      open statement:s                       = PCB.ast->makeWhileStatement(x,s);
 -> "for", '(',
      expression:init, ';',
      expression:cond, ';',
      expression:inc, ')', open statement:s  = PCB.ast->makeForStatement(init, cond, inc, s);

(Statement *) closed statement
 -> "if", '(', expression:x, ')', closed statement:s1,
    "else", closed statement:s2              = PCB.ast->makeIfElseStatement(x,s1,s2);
 -> "while", '(', expression:x, ')',
      closed statement:s                     = PCB.ast->makeWhileStatement(x,s);
 -> "for", '(',
      expression:init, ';',
      expression:cond, ';',
      expression:inc, ')', closed statement:s = PCB.ast->makeForStatement(init, cond, inc, s);
 -> simple statement:x                        = x;

/*
 * Statements that do not end with other statements. These all behave the
 * same way with respect to the closed statement/open statement construct
 * above, and are therefore factored out to PCB.ast->make it clearer.
 *
 * The bare expression appendss a pop instruction so that the resulting
 * byte code will discard the expression's value. (This is not an
 * optimizing compiler.)
 */
(Statement *) simple statement
 -> "do", statement:s,
    "while", '(', expression:x, ')', ';'      = PCB.ast->makeDoStatement(s,x);
 -> expression:x, ';'                         = PCB.ast->makeExpressionStatement(x);
 -> ';'                                       = PCB.ast->makeStatement();
 -> '{', statements:s, '}'                    = PCB.ast->makeStatementBlock(s);

// General expression. As in C, comma expression has the lowest precedence.
(Expression *) expression
 -> assignment expression
 -> expression:x, ',', assignment expression:y = PCB.ast->makeCommaExpression(x,y);

/*
 * Next precedence: assignments. Again, as in C, except we don't
 * support quite all the operators.
 */
(Expression *) assignment expression
 -> conditional expression
 -> name:k, '=',  assignment expression:x    =PCB.ast->makeSimpleAssignment(k, x);
 -> name:k, "+=", assignment expression:x    =PCB.ast->makeAddMemory(k, x);
 -> name:k, "-=", assignment expression:x    =PCB.ast->makeSubMemory(k, x);
 -> name:k, "*=", assignment expression:x    =PCB.ast->makeMulMemory(k, x);
 -> name:k, "/=", assignment expression:x    =PCB.ast->makeDivMemory(k, x);

 // Conditional expression (ternary operator)
(Expression *) conditional expression
 -> logical or expression
 -> logical or expression:c, '?',
      expression:x, ':', conditional expression:y  =PCB.ast->makeConditionalExpression(c,x,y);

// Logical expressions with short-cut evaluation, as in C.
(Expression *) logical or expression
 -> logical and expression
 -> logical or expression:x, "||",
      logical and expression:y                    =PCB.ast->makeLogicalOrExpression(x, y);

(Expression *) logical and expression
 -> equality expression
 -> logical and expression:x, "&&",
      equality expression:y                       =PCB.ast->makeLogicalAndExpression(x,y);

// Arithmetic expressions, in operator precedence order.
(Expression *) equality expression
 -> relational expression
 -> equality expression:x, "==", relational expression:y    =PCB.ast->makeEqExpression(x,y);
 -> equality expression:x, "!=", relational expression:y    =PCB.ast->makeNeExpression(x,y);

(Expression *) relational expression
 -> additive expression
 -> relational expression:x, '<',  additive expression:y    =PCB.ast->makeLtExpression(x,y);
 -> relational expression:x, "<=", additive expression:y    =PCB.ast->makeLeExpression(x,y);
 -> relational expression:x, '>',  additive expression:y    =PCB.ast->makeGtExpression(x,y);
 -> relational expression:x, ">=", additive expression:y    =PCB.ast->makeGeExpression(x,y);

(Expression *) additive expression
 -> multiplicative expression
 -> additive expression:x, '+',
      multiplicative expression:y                          =PCB.ast->makeAddExpression(x,y);
 -> additive expression:x, '-',
      multiplicative expression:y                          =PCB.ast->makeSubExpression(x,y);

(Expression *) multiplicative expression
 -> unary expression
 -> multiplicative expression:x, '*', unary expression:y   =PCB.ast->makeMulExpression(x,y);
 -> multiplicative expression:x, '/', unary expression:y   =PCB.ast->makeDivExpression(x,y);

(Expression *) unary expression
 -> factor
 -> '-', unary expression:x                                =PCB.ast->makeNegExpression(x);
 -> '+', unary expression:x                                =x;
 -> '!', unary expression:x                                =PCB.ast->makeNotExpression(x);

/*
 * Syntactically, we can use ** for exponentiation because we don't have
 * pointers. (In C, ** could be confused with pointer indirection.)
 * Note that the precedence of ** is inserted between unary +/- and unary !.
 */
(Expression *) factor
 -> primary
 -> primary:x, "**", unary expression:y                   =PCB.ast->makePowExpression(x,y);

/*
 * Primary expression - bottom level of expression syntax.
 * Variable references, constants, the builtin functions.
 * Also, another expression in parentheses. (This is how you make
 * parentheses work the way they're supposed to.)
 */
(Expression *) primary
 -> real:x                                                =PCB.ast->makeConstant(x);
 -> name:k                                                =PCB.ast->makeVariable(k);
 -> "log", '(', expression:x, ')'                         =PCB.ast->makeLogExpression(x);
 -> "exp", '(', expression:x, ')'                         =PCB.ast->makeExpExpression(x);
 -> "sqrt", '(', assignment expression:x, ')'             =PCB.ast->makeSqrtExpression(x);
 -> '(', expression:x, ')'                                =x;

// -- 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

(double) real
 -> simple real:x                                                =x;
 -> simple real:x, 'e'+'E', '+'?,exponent:e            =x*pow(10,e);
 -> simple real:x, 'e'+'E', '-',exponent:e            =x*pow(10,-e);

(double) simple real
 -> integer part:i, '.', fraction part:f                      = i+f;
 -> integer part:i, '.'?                                        = i;
 -> '.', 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';

(AgString) name
 -> letter: c                                       =AgString().concat(c);
 -> name:s, letter+digit: c                         =s.concat(c);

{ // begin embedded C

void ag_delete_wrappers(astParse_pcb_struct *);

void parseStatements(AbstractSyntaxTree *tree, char *text) {
  astParse_pcb_struct pcb;
  pcb.ast = tree;
  pcb.pointer = (unsigned char *) text;
  astParse(&pcb);
  if (pcb.exit_flag == AG_SUCCESS_CODE)  tree->setRoot(astParse_value(&pcb));
  else ag_delete_wrappers(&pcb);
}
} // end of embedded C
/********************* End of bciast.syn ************************/