view tests/agcl/oldagsrc/xvmc.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

{
/*
 XVMC.SYN

 Extensible Scripting Language
 Copyright (c) 1998 Parsifal Software, All Rights Reserved.

 The expression syntax is borrowed from C but with the
 addition of the FORTRAN exponentiation operator (**).

 The supported operations are:
   Assignment operators:        =, +=, -=, *=, /=, %=, , &=, |=, ^=>>=, <<=
   Conditional expressions:     ? :
   Logical operators:           !, &&, ||
   Bitwise logical operators:   &, |, ^, ~
   Comparison operators:        ==, !=, <, <=, >, >=
   Shift operators:             <<, >>
   Binary arithmetic operators: +, -, *, /, %
   Unary arithmetic operators:  +, -
   Exponentiation:              **
   Autoincrement operators:     ++, --;
   Cast operators               (<type name>)
   Parentheses
   Function calls
   Object method calls

 Built in data types are int, double and String.

 Statements may include variable declarations, expression statements,
 blocks, if/else statements, while , do/while, or for statements,
 following the rules of C.

 The statement syntax has been written to avoid the conventional
 if/else ambiguity.

 Input strings may contain any number of statements. White space may be
 used freely, including both C and C++ style comments.

 xvmc.syn is compiled with the AnaGram parser generator
 yielding xvm.h and xvm.cpp.

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

#include <math.h>
#include "xvm.h"                  // defines external interface
#include "integer.h"
#include "double.h"
#include "xstring.h"

static VirtualMachine *vm;

typedef VirtualMachine::CodeSeg Code;             // For the sake of readability

}
// -- CONFIGURATION SECTION ----------------------------
[
  default token type = Code
  disregard white space
  lexeme {real, name string, string literal, character constant}
  distinguish lexemes
  distinguish keywords {'a-z' + 'A-Z' + '0-9' + '_'}
  pointer input
  parser name = vmCompile
  parser file name = "#.cpp"
  line numbers
  ~allow macros
  escape backslashes                        // for Visual C++
]

input string $                       // specify grammar token
 -> eof                                     =Code();
 -> statements:x, eof                       =x;
 -> statements:x, error, ~(eof + ';' + '}' + space)?..., eof   =x;

statement
 -> executable statement
 -> declaration, ';'
 -> error, ~(eof + ';' + '}' + space)?..., ';'       =errorLog.add("Continuing scan"), Code();

declaration
 -> type name:t, name string:n                           =vm->declareVariable(t,n), Code();
 -> type name:t, name string:n, '=', expression:x   ={
    int name = vm->declareVariable(t,n);
    return Code(VirtualMachine::PUSHV) << name << x << VirtualMachine::ASSIGN << VirtualMachine::POP;
 }
 -> type name:t, name string:n, '[', expression:size, ']'    =vm->declareArray(t,n, size);
 -> type name:t, name string:n, '(', expression list:args, ')' =vm->declareObject(t,n,args);

expression list
 ->                                                          =Code();
 -> expressions:x                                            =x;

expressions
 -> expression:x                                             =x.initList();
 -> expressions:list, ',', expression:x                      =list.append(x);


executable statement
 -> unconditional statement
 -> conditional statement

statements
 -> statement:x                                =x;
 -> statements:x, statement:s                  =x << s;


/*
 An unconditional statement is any statement that does not involve
 an if statement
*/

unconditional statement
 -> expression:x, ';'                          =x << VirtualMachine::POP;
 -> ';'                                        =Code();
 -> '{', '}'                                   =Code();
 -> '{', statements:s, '}'                     =s;
 -> '{', statements:s, error, ~(eof + ';' + '}' + space)?..., '}'   =errorLog.add("Continuing scan"), s;
 -> "do", executable statement:s, while clause:x, ';'  =vm->codeDoWhile(s,x);
 -> while clause:x, unconditional statement:s          =vm->codeWhile(x,s);
 -> "for", '(', for exprs:init, ';', condition:cond, ';', for exprs:inc,
    ')', unconditional statement:s                     =vm->codeFor(init, cond, inc, s);

for exprs
 ->                                             =Code();
 -> for expr list

for expr list
 -> expression:x                                =x << VirtualMachine::POP;
 -> for expr list:list, ',', expression:x       =list << x << VirtualMachine::POP;

while clause
 -> "while", '(', condition:x, ')'            =x;


/*
 Any statement with an if in it is a conditional statement
*/

conditional statement
 -> while clause:x, conditional statement:s         =vm->codeWhile(x,s);
 -> "for", '(', for exprs:init, ';', condition:cond, ';', for exprs:inc,
    ')', conditional statement:s                     =vm->codeFor(init, cond, inc, s);
 -> if clause:x, executable statement:s             =x << VirtualMachine::BRF << s.size() << s;
 -> if clause:x, unconditional statement:s1,
      "else", statement:s2                     ={
      s1 << VirtualMachine::BR << s2.size();
      x << VirtualMachine::BRF << s1.size() << s1 << s2;
      return x;
    }

if clause
 -> "if", '(', condition:x, ')'               =x;

condition
 -> expression:x                              =x.testOK();

expression
 -> conditional expression
 -> lvalue:k, '=',  expression:x                 =k << x << VirtualMachine::ASSIGN;
 -> lvalue:k, "+=", expression:x                 =k << x << VirtualMachine::ADD_EQ;
 -> lvalue:k, "-=", expression:x                 =k << x << VirtualMachine::SUB_EQ;
 -> lvalue:k, "*=", expression:x                 =k << x << VirtualMachine::MULT_EQ;
 -> lvalue:k, "/=", expression:x                 =k << x << VirtualMachine::DIV_EQ;
 -> lvalue:k, "%=", expression:x                 =k << x << VirtualMachine::MOD_EQ;
 -> lvalue:k, "|=", expression:x                 =k << x << VirtualMachine::OR_EQ;
 -> lvalue:k, "&=", expression:x                 =k << x << VirtualMachine::AND_EQ;
 -> lvalue:k, "^=", expression:x                 =k << x << VirtualMachine::XOR_EQ;
 -> lvalue:k, "<<=", expression:x                =k << x << VirtualMachine::LS_EQ;
 -> lvalue:k, ">>=", expression:x                =k << x << VirtualMachine::RS_EQ;

lvalue
 -> variable name:k                              =Code(VirtualMachine::PUSHV).setType(vm->symbolTable[k].type) << k;
 -> lvalue:k, '[', expression:x, ']'             =k.setType(k.type->element) << x << VirtualMachine::SUBSCRIPT;

conditional expression
 -> logical or expression
 -> logical or condition:c, '?',
      expression:x, ':', conditional expression:y    ={
      //if (!c.type->isTruthDefined()) errorLog.add("True/False not defined");
      x << VirtualMachine::BR << y.size();
      c << VirtualMachine::BRF << x.size() << x << y;
      return c;
    }

logical or condition
 -> logical or expression:x     =x.testOK();

logical or expression
 -> logical and expression
 -> logical or condition:x, "||",logical and expression:y        ={
      //if (!x.type->isTruthDefined()) errorLog.add("True/False not defined");
      return x << VirtualMachine::OR << y.size() << y;
    }

logical and expression
 -> bitwise or expression
 -> logical and condition:x, "&&", bitwise or expression:y          ={
      //if (!x.type->isTruthDefined()) errorLog.add("True/False not defined");
      return x << VirtualMachine::AND << y.size() << y;
    }

logical and condition
 -> logical and expression:x     =x.testOK();



bitwise or expression
 -> bitwise xor expression
 -> bitwise or expression:x, '|',
      bitwise xor expression:y         =x.binop(VirtualMachine::BITOR,y);

bitwise xor expression
 -> bitwise and expression
 -> bitwise xor expression:x, '^',
      bitwise and expression:y         =x.binop(VirtualMachine::XOR,y);

bitwise and expression
 -> equality expression
 -> bitwise and expression:x, '&',
      equality expression:y             =x.binop(VirtualMachine::BITAND,y);

equality expression
 -> relational expression
 -> equality expression:x, "==", relational expression:y    =x.binop(VirtualMachine::EQ,y);
 -> equality expression:x, "!=", relational expression:y    =x.binop(VirtualMachine::NE,y);

relational expression
 -> shift expression
 -> relational expression:x, '<',  shift expression:y    =x.binop(VirtualMachine::LT,y);
 -> relational expression:x, "<=", shift expression:y    =x.binop(VirtualMachine::LE,y);
 -> relational expression:x, '>',  shift expression:y    =x.binop(VirtualMachine::GT,y);
 -> relational expression:x, ">=", shift expression:y    =x.binop(VirtualMachine::GE,y);

shift expression
 -> additive expression
 -> shift expression:x, "<<", additive expression:y  =x.binop(VirtualMachine::LS,y);
 -> shift expression:x, ">>", additive expression:y  =x.binop(VirtualMachine::RS,y);

additive expression
 -> multiplicative expression
 -> additive expression:x, '+',
      multiplicative expression:y                          =x.binop(VirtualMachine::ADD,y);
 -> additive expression:x, '-',
      multiplicative expression:y                          =x.binop(VirtualMachine::SUB,y);

multiplicative expression
 -> cast expression
 -> multiplicative expression:x, '*', cast expression:y           =x.binop(VirtualMachine::MULT,y);
 -> multiplicative expression:x, '/', cast expression:y           =x.binop(VirtualMachine::DIV,y);
 -> multiplicative expression:x, '%', cast expression:y           =x.binop(VirtualMachine::MOD,y);

cast expression
 -> unary expression
 -> '(', type name:t, ')', cast expression:x                      =x.cast((VirtualMachine::Type::Id) t) << VirtualMachine::CAST << t;

unary expression
 -> power expression
 -> "++", unary expression:x                             =x << VirtualMachine::INCR;
 -> "--", unary expression:x                             =x << VirtualMachine::INCR;
 -> '-', unary expression:x                              =x << VirtualMachine::NEG;
 -> '+', unary expression:x                              =x;
 -> '!', unary expression:x                              =vm->list(stdout), x << VirtualMachine::NOT;
 -> '~', unary expression:x                              =x << VirtualMachine::COMPL;



power expression
 -> primary
 -> primary:x, "**", unary expression:y                  =x.binop(VirtualMachine::POW,y);

primary
 -> real:x                                      =vm->doubleList.push(x), Code(VirtualMachine::PUSHD).setType(&DoubleType::doubleType) << (int)(vm->doubleList.size() - 1);
 -> integer constant:x                          =Code(VirtualMachine::PUSHI).setType(&IntegerType::intType) << x;
 -> string literal:k                            =Code(VirtualMachine::PUSHS).setType(&StringType::stringType) << k;
 -> lvalue:k                                    =k;
 -> lvalue:k, "++"                              =k << VirtualMachine::PUSH << VirtualMachine::INCR << VirtualMachine::POP;
 -> lvalue:k, "--"                              =k << VirtualMachine::PUSH << VirtualMachine::DECR << VirtualMachine::POP;
 -> name string:n, '(', expression list:args, ')'  =vm->invokeFunction(n, args);
 -> lvalue:k, '.', name string:n, '(', expression list: args, ')' =vm->invokeMethod(k, n, args);
 -> '(', expression:x, ')'                      =x;

// -- LEXICAL UNITS ------------------------------------------------
digit   = '0-9'
eof     = 0
letter  = 'a-z' + 'A-Z' + '_'
space =  ' ' + '\t' + '\f' + '\v' + '\r' + '\n'


(void) white space
 -> space
 -> "/*", ~eof?..., "*/"                        // C style comment
 -> "//", ~(eof+'\n')?..., '\n'                 // C++ style comment

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

(int) integer constant
 -> integer
 -> character constant

(int) integer
 -> digit:d                                                 = d-'0';
 -> integer: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) type name, variable name
 -> name string:k           ={
    char *name = popString(k);
    VirtualMachine::Type::Id id = VirtualMachine::Type::idType(name);
    if (id != VirtualMachine::Type::UNDEFINED) return (int) id;
    CHANGE_REDUCTION(variable_name);
    return vm->locateVariable(name);
 }

(int) name string
 -> letter: c                                       =pushChar(c), 1;
 -> name string:k, letter+digit: c                  =pushChar(c), k+1;

not double quote    = ~eof - ('"' + '\\' + '\n')
not single quote    = ~eof - ('\'' + '\\' + '\n')

(int) character constant
 -> '\'', char constant element:c, '\''     =c;

(int) char constant element
 -> not single quote
 -> escape sequence

(int) string literal
  -> string chars:k, '"'                    =vm->stringList.push(CharString(popString(k))), vm->stringList.size() - 1;

(int) string chars
  -> '"'                                    =0;
  -> string chars:k, string char:c          =pushChar(c), k+1;

(int) string char
 -> not double quote
 -> escape sequence

(int) escape sequence
 -> "\\a"   ='\a';
 -> "\\b"   ='\b';
 -> "\\f"   ='\f';
 -> "\\n"   ='\n';
 -> "\\r"   ='\r';
 -> "\\t"   ='\t';
 -> "\\v"   ='\v';
 -> "\\\\"  ='\\';
 -> "\\?"   = '\?';
 -> "\\'"   ='\'';
 -> "\\\""  ='"';
 -> octal escape
 -> hex escape

(int) octal escape
 -> one octal | two octal | three octal

(int) one octal
 -> '\\', '0-7':d                           =d-'0';

(int) two octal
 -> one octal:n, '0-7':d                    =8*n + d-'0';

(int) three octal
 -> two octal:n, '0-7':d                    =8*n + d-'0';

(int) hex escape
 -> "\\x", hex digit:d                      =d;
 -> hex escape:n, hex digit:d               =16*n + d;

(int) hex digit
 -> '0-9'
 -> 'a-f' + 'A-F':d                         =(d&7) + 9;

[
   sticky {one octal, two octal, hex escape}
]



{ // begin embedded C

#include <string.h>


ErrorRecord::ErrorRecord(char *msg) : message(msg), line(PCB.line), column(PCB.column)
{/* Initializers do it all */}

ErrorLog errorLog;

#define SYNTAX_ERROR errorLog.add(PCB.error_message)

int VirtualMachine::compile(char *text) {
  vm = this;
  resetCharStack();
  vmCompile_pcb.pointer = (unsigned char *) text;
  vmCompile();
  {
    Code program = vmCompile_value() << EXIT;
    int n = program.size();
    codeStore = new int[n];
    while (n--) codeStore[n] = program[n];
  }

  return vmCompile_pcb.exit_flag != AG_SUCCESS_CODE;
}

Code VirtualMachine::codeWhile(Code x, Code s) {
  Code branch(VirtualMachine::BR);
  branch << 0;
  //if (!x.type->isTruthDefined()) errorLog.add("True/False not defined");
  x << VirtualMachine::BRF << (s.size() + branch.size());
  int blockLength = s.size() + x.size() + branch.size();
  x << s << VirtualMachine::BR << -blockLength;
  return x;
}

Code VirtualMachine::codeDoWhile(Code s, Code x) {
  Code branch(VirtualMachine::BR);
  branch << 0;
  int blockLength = s.size() + x.size() + branch.size();
  //if (!x.type->isTruthDefined()) errorLog.add("True/False not defined");
  s << x << VirtualMachine::BRT << -blockLength;
  return s;
}

Code VirtualMachine::codeFor(Code init, Code cond, Code inc, Code s) {
  s << inc;               // append increment code to end of body of for loop
  //if (!cond.type->isTruthDefined()) errorLog.add("True/False not defined");
  init << codeWhile(cond, s);
  return init;
}

} // end of embedded C
/********************* End of VM.SYN ************************/