mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
Initial stacker checkin
llvm-svn: 10178
This commit is contained in:
parent
cb0261035a
commit
1878aafde9
234
projects/Stacker/lib/compiler/Lexer.l
Normal file
234
projects/Stacker/lib/compiler/Lexer.l
Normal file
@ -0,0 +1,234 @@
|
||||
/*===-- Lexer.l - Scanner for Stacker language -----------------*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Reid Spencer and donated to the LLVM research
|
||||
// group and is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the flex scanner for Stacker languages files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===*/
|
||||
|
||||
%option prefix="Stacker"
|
||||
%option yylineno
|
||||
%option nostdinit
|
||||
%option never-interactive
|
||||
%option batch
|
||||
%option noyywrap
|
||||
%option nodefault
|
||||
%option 8bit
|
||||
%option outfile="Lexer.cpp"
|
||||
%option ecs
|
||||
%option noreject
|
||||
%option noyymore
|
||||
|
||||
%{
|
||||
|
||||
#include "StackerCompiler.h"
|
||||
#include "StackerParser.h"
|
||||
|
||||
/* Conversion of text ints to binary */
|
||||
static uint64_t IntToVal(const char *Buffer) {
|
||||
uint64_t Result = 0;
|
||||
for (; *Buffer; Buffer++) {
|
||||
uint64_t OldRes = Result;
|
||||
Result *= 10;
|
||||
Result += *Buffer-'0';
|
||||
if (Result < OldRes) // Uh, oh, overflow detected!!!
|
||||
StackerCompiler::ThrowException("constant bigger than 64 bits detected!");
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* Conversion of text hexadecimal ints to binary */
|
||||
static uint64_t HexIntToVal(const char *Buffer) {
|
||||
uint64_t Result = 0;
|
||||
for (; *Buffer; ++Buffer) {
|
||||
uint64_t OldRes = Result;
|
||||
Result *= 16;
|
||||
char C = *Buffer;
|
||||
if (C >= '0' && C <= '9')
|
||||
Result += C-'0';
|
||||
else if (C >= 'A' && C <= 'F')
|
||||
Result += C-'A'+10;
|
||||
else if (C >= 'a' && C <= 'f')
|
||||
Result += C-'a'+10;
|
||||
|
||||
if (Result < OldRes) // Uh, oh, overflow detected!!!
|
||||
StackerCompiler::ThrowException("constant bigger than 64 bits detected!");
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define YY_NEVER_INTERACTIVE 1
|
||||
%}
|
||||
|
||||
/* Comments start with a ; and go till end of line */
|
||||
Comment1 [#].*$
|
||||
/* You can also embed them in ( ... ) */
|
||||
Comment2 \(.*\)
|
||||
/* We ignore white space */
|
||||
White [ \t\n]
|
||||
|
||||
/* jdentifiers start with a % sign */
|
||||
Identifier [A-Za-z][-A-Za-z0-9_]*
|
||||
|
||||
/* Strings can contain any character except " and \ */
|
||||
String \"[^\"]*\"
|
||||
|
||||
/* Positive and negative integer constants*/
|
||||
PInteger [+]?[0-9]+
|
||||
NInteger -[0-9]+
|
||||
HexInteger 0x[0-9A-Fa-f]+
|
||||
|
||||
/* Special Characters - name them to avoid flex confusion */
|
||||
Semi [;]
|
||||
Colon [:]
|
||||
Less \<
|
||||
More \>
|
||||
LessEq \<\=
|
||||
MoreEq \>\=
|
||||
NotEq \<\>
|
||||
Equal \=
|
||||
Plus \+
|
||||
Minus \-
|
||||
Incr \+\+
|
||||
Decr \-\-
|
||||
Mult \*
|
||||
Div \/
|
||||
StarSlash \*\/
|
||||
LShift \<\<
|
||||
RShift \>\>
|
||||
InStr \<s
|
||||
InNum \<d
|
||||
InChar \<c
|
||||
OutStr \>s
|
||||
OutNum \>d
|
||||
OutChar \>c
|
||||
|
||||
%%
|
||||
|
||||
{Comment1} { /* Ignore comments */ }
|
||||
{Comment2} { /* Ignore comments */ }
|
||||
|
||||
{Colon} { return COLON; }
|
||||
{Semi} { return SEMI; }
|
||||
|
||||
TRUE { return TRUE; }
|
||||
FALSE { return FALSE; }
|
||||
ON { return TRUE; }
|
||||
OFF { return FALSE; }
|
||||
{Less} { return LESS; }
|
||||
LT { return LESS; }
|
||||
{More} { return MORE; }
|
||||
GT { return MORE; }
|
||||
{LessEq} { return LESS_EQUAL; }
|
||||
LE { return LESS_EQUAL; }
|
||||
{MoreEq} { return MORE_EQUAL; }
|
||||
GE { return MORE_EQUAL; }
|
||||
{NotEq} { return NOT_EQUAL; }
|
||||
NE { return NOT_EQUAL; }
|
||||
{Equal} { return EQUAL; }
|
||||
EQ { return EQUAL; }
|
||||
|
||||
{Plus} { return PLUS; }
|
||||
{Minus} { return MINUS; }
|
||||
{Incr} { return INCR; }
|
||||
{Decr} { return DECR; }
|
||||
{Mult} { return MULT; }
|
||||
{Div} { return DIV; }
|
||||
MOD { return MODULUS; }
|
||||
NEG { return NEGATE; }
|
||||
ABS { return ABS; }
|
||||
MIN { return MIN; }
|
||||
MAX { return MAX; }
|
||||
{StarSlash} { return STAR_SLASH; }
|
||||
|
||||
AND { return AND; }
|
||||
OR { return OR; }
|
||||
XOR { return XOR; }
|
||||
{LShift} { return LSHIFT; }
|
||||
{RShift} { return RSHIFT; }
|
||||
|
||||
DROP { return DROP; }
|
||||
NIP { return NIP; }
|
||||
DUP { return DUP; }
|
||||
SWAP { return SWAP; }
|
||||
OVER { return OVER; }
|
||||
PICK { return PICK; }
|
||||
SELECT { return SELECT; }
|
||||
ROT { return ROT; }
|
||||
RROT { return RROT; }
|
||||
ROLL { return ROLL; }
|
||||
TUCK { return TUCK; }
|
||||
DROP2 { return DROP2; }
|
||||
NIP2 { return NIP2; }
|
||||
DUP2 { return DUP2; }
|
||||
SWAP2 { return SWAP2; }
|
||||
OVER2 { return OVER2; }
|
||||
TUCK2 { return TUCK2; }
|
||||
ROT2 { return ROT2; }
|
||||
RROT2 { return RROT2; }
|
||||
|
||||
MALLOC { return MALLOC; }
|
||||
FREE { return FREE; }
|
||||
GET { return GET; }
|
||||
PUT { return PUT; }
|
||||
|
||||
IF { return IF; }
|
||||
ELSE { return ELSE; }
|
||||
ENDIF { return ENDIF; }
|
||||
WHILE { return WHILE; }
|
||||
END { return END; }
|
||||
|
||||
RECURSE { return RECURSE; }
|
||||
RETURN { return RETURN; }
|
||||
EXIT { return EXIT; }
|
||||
FORWARD { return FORWARD; }
|
||||
TAB { return TAB; }
|
||||
SPACE { return SPACE; }
|
||||
CR { return CR; }
|
||||
|
||||
{InStr} { return IN_STR; }
|
||||
{InNum} { return IN_NUM; }
|
||||
{InChar} { return IN_CHAR; }
|
||||
|
||||
{OutStr} { return OUT_STR; }
|
||||
{OutNum} { return OUT_NUM; }
|
||||
{OutChar} { return OUT_CHAR; }
|
||||
|
||||
MAIN { return MAIN; }
|
||||
|
||||
DUMP { return DUMP; }
|
||||
|
||||
!= { StackerCompiler::ThrowException(
|
||||
"You probably meant to use a <> instead of !=" ); }
|
||||
|
||||
== { StackerCompiler::ThrowException(
|
||||
"You probably meant to use a single = .. this isn't C"); }
|
||||
|
||||
{PInteger} { Stackerlval.IntegerVal = IntToVal(yytext); return INTEGER; }
|
||||
{NInteger} { uint64_t Val = IntToVal(yytext+1);
|
||||
// +1: we have bigger negative range
|
||||
if (Val > (uint64_t)INT64_MAX+1)
|
||||
StackerCompiler::ThrowException(
|
||||
"Constant too large for signed 64 bits!");
|
||||
Stackerlval.IntegerVal = -Val;
|
||||
return INTEGER;
|
||||
}
|
||||
{HexInteger} { Stackerlval.IntegerVal = HexIntToVal(yytext+3);
|
||||
return INTEGER;
|
||||
}
|
||||
|
||||
{String} { yytext[strlen(yytext)-1] = 0; // nuke end quote
|
||||
Stackerlval.StringVal = strdup(yytext+1); // Nuke start quote
|
||||
return STRING;
|
||||
}
|
||||
|
||||
{Identifier} { Stackerlval.StringVal = strdup(yytext); return IDENTIFIER; }
|
||||
|
||||
{White} { /* Ignore whitespace */ }
|
||||
%%
|
21
projects/Stacker/lib/compiler/Makefile
Normal file
21
projects/Stacker/lib/compiler/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
##===- projects/sample/lib/sample/Makefile -----------------*- Makefile -*-===##
|
||||
|
||||
#
|
||||
# Indicate where we are relative to the top of the source tree.
|
||||
#
|
||||
LEVEL=../../../..
|
||||
|
||||
#
|
||||
# Give the name of a library. This will build a dynamic version.
|
||||
#
|
||||
SHARED_LIBRARY=1
|
||||
LIBRARYNAME=stkr_compiler
|
||||
|
||||
#
|
||||
# Include Makefile.common so we know what to do.
|
||||
#
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
ifdef PARSE_DEBUG
|
||||
INCLUDES += -DPARSE_DEBUG
|
||||
endif
|
20
projects/Stacker/lib/compiler/README
Normal file
20
projects/Stacker/lib/compiler/README
Normal file
@ -0,0 +1,20 @@
|
||||
This directory contains a sample language front end for LLVM.
|
||||
|
||||
It is a *very* simple/crude implementation of FORTH. It has many
|
||||
deficiencies but provides enough basics to give you an idea of
|
||||
what programming a new language front end for LLVM looks like.
|
||||
|
||||
To keep things simple, Stacker has the following limitations:
|
||||
1. Only a single, global stack is manipulated.
|
||||
2. There is no interpretation, everything is compiled.
|
||||
3. There's no type/bounds checking .. you're on your own.
|
||||
4. There's no floating point support.
|
||||
5. Only stdin can be read. Only stdout can be written. No other
|
||||
file I/O is supported.
|
||||
|
||||
As such, this isn't a very useful language for anything other than
|
||||
the most trivial of programs. It is, however, a good learning tool
|
||||
(for both the author and the student).
|
||||
|
||||
Reid Spencer
|
||||
16 November 2003
|
1728
projects/Stacker/lib/compiler/StackerCompiler.cpp
Normal file
1728
projects/Stacker/lib/compiler/StackerCompiler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
224
projects/Stacker/lib/compiler/StackerCompiler.h
Normal file
224
projects/Stacker/lib/compiler/StackerCompiler.h
Normal file
@ -0,0 +1,224 @@
|
||||
//===-- StackerCompiler.h - Interface to the Stacker Compiler ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Reid Spencer and donated to the LLVM research
|
||||
// group and is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This header file defines the various variables that are shared among the
|
||||
// different components of the parser...
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_STACKERCOMPILER_H
|
||||
#define LLVM_STACKERCOMPILER_H
|
||||
|
||||
#include <llvm/Constants.h>
|
||||
#include <llvm/DerivedTypes.h>
|
||||
#include <llvm/Function.h>
|
||||
#include <llvm/Instruction.h>
|
||||
#include <llvm/Module.h>
|
||||
#include <llvm/Assembly/Parser.h>
|
||||
#include <Support/StringExtras.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// Global variables exported from the lexer...
|
||||
extern std::FILE *Stackerin;
|
||||
extern int Stackerlineno;
|
||||
extern char* Stackertext;
|
||||
extern int Stackerleng;
|
||||
|
||||
/// @brief This class provides the Compiler for the Stacker language.
|
||||
///
|
||||
/// The main method to call is \c compile. The other methods are
|
||||
/// all internal to the compiler and protected. In general the
|
||||
/// handle_* methods are called by the BISON generated parser
|
||||
/// (see StackerParser.y). The methods returning Instruction* all
|
||||
/// produce some snippet of code to manipulate the stack in some
|
||||
/// way. These functions are just conveniences as they are used
|
||||
/// often by the compiler.
|
||||
class StackerCompiler
|
||||
{
|
||||
/// @name Constructors and Operators
|
||||
/// @{
|
||||
public:
|
||||
/// Default Constructor
|
||||
StackerCompiler();
|
||||
|
||||
/// Destructor
|
||||
~StackerCompiler();
|
||||
private:
|
||||
/// Do not copy StackerCompilers
|
||||
StackerCompiler(const StackerCompiler&);
|
||||
|
||||
/// Do not copy StackerCompilers.
|
||||
StackerCompiler& operator=(const StackerCompiler& );
|
||||
|
||||
/// @}
|
||||
/// @name High Level Interface
|
||||
/// @{
|
||||
public:
|
||||
/// @brief Compile a single file to LLVM bytecode.
|
||||
///
|
||||
/// To use the StackerCompiler, just create one on
|
||||
/// the stack and call this method.
|
||||
Module* compile(
|
||||
const std::string& filename, ///< File to compile
|
||||
bool echo, ///< Causes compiler to echo output
|
||||
size_t stack_size ); ///< Size of generated stack
|
||||
/// @}
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
public:
|
||||
/// @brief Returns the name of the file being compiled.
|
||||
std::string& filename() { return CurFilename; }
|
||||
|
||||
/// @}
|
||||
/// @name Parse Handling Methods
|
||||
/// @{
|
||||
private:
|
||||
/// Allow only the parser to access these methods. No
|
||||
/// one else should call them.
|
||||
friend int Stackerparse();
|
||||
|
||||
/// @brief Handle the start of a module
|
||||
Module* handle_module_start();
|
||||
|
||||
/// @brief Handle the end of a module
|
||||
/// @param mod The module we're defining.
|
||||
Module* handle_module_end( Module* mod );
|
||||
|
||||
/// @brief Handle the start of a list of definitions
|
||||
Module* handle_definition_list_start( );
|
||||
|
||||
/// @brief Handle the end of a list of definitions
|
||||
/// @param mod The module we're constructing
|
||||
/// @param definition A definition (function) to add to the module
|
||||
Module* handle_definition_list_end( Module* mod, Function* definition );
|
||||
|
||||
/// @brief Handle creation of the MAIN definition
|
||||
/// @param func The function to be used as the MAIN definition
|
||||
Function* handle_main_definition( Function* func );
|
||||
|
||||
/// @brief Handle a forward definition
|
||||
/// @param name The name of the definition being declared
|
||||
Function* handle_forward( char* name );
|
||||
|
||||
/// @brief Handle a general definition
|
||||
/// @param name The name of the definition being defined
|
||||
/// @param func The Function definition.
|
||||
Function* handle_definition( char* name, Function* func );
|
||||
|
||||
/// @brief Handle the start of a definition's word list
|
||||
Function* handle_word_list_start();
|
||||
|
||||
/// @brief Handle the end of a definition's word list
|
||||
/// @param func The function to which the basic block is added
|
||||
/// @param next The block to add to the function
|
||||
Function* handle_word_list_end( Function* func, BasicBlock* next );
|
||||
|
||||
/// @brief Handle an if statement, possibly without an else
|
||||
/// @brief ifTrue The block to execute if true
|
||||
/// @brief ifFalse The optional block to execute if false
|
||||
BasicBlock* handle_if( char* ifTrue, char* ifFalse = 0 );
|
||||
|
||||
/// @brief Handle a while statement
|
||||
/// @brief todo The block to repeatedly execute
|
||||
BasicBlock* handle_while( char* todo );
|
||||
|
||||
/// @brief Handle an identifier to call the identified definition
|
||||
/// @param name The name of the identifier to be called.
|
||||
BasicBlock* handle_identifier( char * name );
|
||||
|
||||
/// @brief Handle the push of a string onto the stack
|
||||
/// @param value The string to be pushed.
|
||||
BasicBlock* handle_string( char * value );
|
||||
|
||||
/// @brief Handle the push of an integer onto the stack.
|
||||
/// @param value The integer value to be pushed.
|
||||
BasicBlock* handle_integer( const int32_t value );
|
||||
|
||||
/// @brief Handle one of the reserved words (given as a token)
|
||||
BasicBlock* handle_word( int tkn );
|
||||
|
||||
/// @}
|
||||
/// @name Utility functions
|
||||
/// @{
|
||||
public:
|
||||
/// @brief Throws an exception to indicate an error
|
||||
/// @param message The message to be output
|
||||
/// @param line Override for the current line no
|
||||
static inline void ThrowException( const std::string &message,
|
||||
int line = -1)
|
||||
{
|
||||
if (line == -1) line = Stackerlineno;
|
||||
// TODO: column number in exception
|
||||
throw ParseException(TheInstance->CurFilename, message, line);
|
||||
}
|
||||
private:
|
||||
/// @brief Generate code to increment the stack index
|
||||
Instruction* incr_stack_index( BasicBlock* bb, Value* );
|
||||
/// @brief Generate code to decrement the stack index.
|
||||
Instruction* decr_stack_index( BasicBlock* bb, Value* );
|
||||
/// @brief Generate code to dereference the top of stack.
|
||||
Instruction* get_stack_pointer( BasicBlock* bb, Value* );
|
||||
/// @brief Generate code to push any value onto the stack.
|
||||
Instruction* push_value( BasicBlock* bb, Value* value );
|
||||
/// @brief Generate code to push a constant integer onto the stack.
|
||||
Instruction* push_integer( BasicBlock* bb, int32_t value );
|
||||
/// @brief Generate code to pop an integer off the stack.
|
||||
Instruction* pop_integer( BasicBlock* bb );
|
||||
/// @brief Generate code to push a string pointer onto the stack.
|
||||
Instruction* push_string( BasicBlock* bb, const char* value );
|
||||
/// @brief Generate code to pop a string pointer off the stack.
|
||||
Instruction* pop_string( BasicBlock* bb );
|
||||
/// @brief Generate code to get the top stack element.
|
||||
Instruction* stack_top( BasicBlock* bb, Value* index );
|
||||
/// @brief Generate code to get the top stack element as a string.
|
||||
Instruction* stack_top_string( BasicBlock* bb, Value* index );
|
||||
/// @brief Generate code to replace the top element of the stack.
|
||||
Instruction* replace_top( BasicBlock* bb, Value* new_top, Value* index);
|
||||
|
||||
/// @}
|
||||
/// @name Data Members (used during parsing)
|
||||
/// @{
|
||||
public:
|
||||
static StackerCompiler* TheInstance; ///< The instance for the parser
|
||||
|
||||
private:
|
||||
std::string CurFilename; ///< Current file name
|
||||
Module* TheModule; ///< Module instance we'll build
|
||||
Function* TheFunction; ///< Function we're building
|
||||
FunctionType* DefinitionType; ///< FT for Definitions
|
||||
GlobalVariable* TheStack; ///< For referencing _stack_
|
||||
GlobalVariable* TheIndex; ///< For referencing _index_
|
||||
Function* TheScanf; ///< External input function
|
||||
Function* ThePrintf; ///< External output function
|
||||
Function* TheExit; ///< External exit function
|
||||
GlobalVariable* StrFormat; ///< Format for strings
|
||||
GlobalVariable* NumFormat; ///< Format for numbers
|
||||
GlobalVariable* ChrFormat; ///< Format for chars
|
||||
GlobalVariable* InStrFormat; ///< Format for input strings
|
||||
GlobalVariable* InNumFormat; ///< Format for input numbers
|
||||
GlobalVariable* InChrFormat; ///< Format for input chars
|
||||
ConstantInt* Zero; ///< long constant 0
|
||||
ConstantInt* One; ///< long constant 1
|
||||
ConstantInt* Two; ///< long constant 2
|
||||
ConstantInt* Three; ///< long constant 3
|
||||
ConstantInt* Four; ///< long constant 4
|
||||
ConstantInt* Five; ///< long constant 5
|
||||
ConstantInt* IZero; ///< int constant 0
|
||||
ConstantInt* IOne; ///< int constant 1
|
||||
ConstantInt* ITwo; ///< int constant 2
|
||||
std::vector<Value*> no_arguments; ///< no arguments for Stacker
|
||||
bool echo; ///< Echo flag
|
||||
size_t stack_size; ///< Size of stack to gen.
|
||||
ArrayType* stack_type; ///< The type of the stack
|
||||
/// @}
|
||||
};
|
||||
|
||||
#endif
|
190
projects/Stacker/lib/compiler/StackerParser.y
Normal file
190
projects/Stacker/lib/compiler/StackerParser.y
Normal file
@ -0,0 +1,190 @@
|
||||
//===-- llvmAsmParser.y - Parser for llvm assembly files --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the bison parser for LLVM assembly languages files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
%debug
|
||||
|
||||
%{
|
||||
#include "StackerCompiler.h"
|
||||
#include "llvm/SymbolTable.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/iTerminators.h"
|
||||
#include "llvm/iMemory.h"
|
||||
#include "llvm/iOperators.h"
|
||||
#include "llvm/iPHINode.h"
|
||||
#include "Support/STLExtras.h"
|
||||
#include "Support/DepthFirstIterator.h"
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
#define YYERROR_VERBOSE 1
|
||||
#define SCI StackerCompiler::TheInstance
|
||||
|
||||
int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit
|
||||
int yylex(); // declaration" of xxx warnings.
|
||||
int yyparse();
|
||||
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
llvm::Module* ModuleVal;
|
||||
llvm::Function* FunctionVal;
|
||||
llvm::BasicBlock* BasicBlockVal;
|
||||
uint32_t IntegerVal;
|
||||
char* StringVal;
|
||||
}
|
||||
|
||||
/* Typed Productions */
|
||||
%type <ModuleVal> Module DefinitionList
|
||||
%type <FunctionVal> Definition ForwardDef ColonDef MainDef
|
||||
%type <FunctionVal> WordList
|
||||
%type <BasicBlockVal> Word
|
||||
|
||||
/* Typed Tokens */
|
||||
%token <IntegerVal> INTEGER
|
||||
%token <StringVal> STRING IDENTIFIER
|
||||
|
||||
/* Terminal Tokens */
|
||||
%token SEMI COLON FORWARD MAIN DUMP
|
||||
%token TRUE FALSE LESS MORE LESS_EQUAL MORE_EQUAL NOT_EQUAL EQUAL
|
||||
%token PLUS MINUS INCR DECR MULT DIV MODULUS NEGATE ABS MIN MAX STAR_SLASH
|
||||
%token AND OR XOR LSHIFT RSHIFT
|
||||
%token DROP DROP2 NIP NIP2 DUP DUP2 SWAP SWAP2 OVER OVER2 ROT ROT2
|
||||
%token RROT RROT2 TUCK TUCK2 ROLL PICK SELECT
|
||||
%token MALLOC FREE GET PUT
|
||||
%token IF ELSE ENDIF WHILE END RECURSE RETURN EXIT
|
||||
%token TAB SPACE CR IN_STR IN_NUM IN_CHAR OUT_STR OUT_NUM OUT_CHAR
|
||||
|
||||
/* Start Token */
|
||||
%start Module
|
||||
|
||||
%%
|
||||
|
||||
/* A module is just a DefinitionList */
|
||||
Module : { SCI->handle_module_start( ); }
|
||||
DefinitionList { $$ = SCI->handle_module_end( $2 ); } ;
|
||||
|
||||
/* A Definitionlist is just a sequence of definitions */
|
||||
DefinitionList : DefinitionList Definition { $$ = SCI->handle_definition_list_end( $1, $2 ); }
|
||||
| /* empty */ { $$ = SCI->handle_definition_list_start(); } ;
|
||||
|
||||
/* A definition can be one of three flavors */
|
||||
Definition : ForwardDef { $$ = $1; }
|
||||
| ColonDef { $$ = $1; }
|
||||
| MainDef { $$ = $1; } ;
|
||||
|
||||
/* Forward definitions just introduce a name */
|
||||
ForwardDef : FORWARD IDENTIFIER SEMI { $$ = SCI->handle_forward( $2 ); } ;
|
||||
|
||||
/* The main definition has to generate additional code so we treat it specially */
|
||||
MainDef : COLON MAIN WordList SEMI { $$ = SCI->handle_main_definition($3); } ;
|
||||
|
||||
/* Regular definitions have a name and a WordList */
|
||||
ColonDef : COLON IDENTIFIER WordList SEMI { $$ = SCI->handle_definition( $2, $3 ); } ;
|
||||
|
||||
/* A WordList is just a sequence of words */
|
||||
WordList : WordList Word { $$ = SCI->handle_word_list_end( $1, $2 ); }
|
||||
| /* empty */ { $$ = SCI->handle_word_list_start() } ;
|
||||
|
||||
/* A few "words" have a funky syntax */
|
||||
/* FIXME: The body of compound words can currently only be function calls */
|
||||
/* This is not acceptable, it should be a WordList, but that produces a Function */
|
||||
/* Which is hard to merge into the function the compound statement is working on */
|
||||
Word : IF IDENTIFIER ELSE IDENTIFIER ENDIF { $$ = SCI->handle_if( $2, $4 ); }
|
||||
| IF IDENTIFIER ENDIF { $$ = SCI->handle_if( $2 ); }
|
||||
| WHILE IDENTIFIER END { $$ = SCI->handle_while( $2 ); } ;
|
||||
|
||||
/* A few words are handled specially */
|
||||
Word : IDENTIFIER { $$ = SCI->handle_identifier( $1 ); } ;
|
||||
Word : STRING { $$ = SCI->handle_string( $1 ); } ;
|
||||
Word : INTEGER { $$ = SCI->handle_integer( $1 ); } ;
|
||||
|
||||
/* Everything else is a terminal symbol and goes to handle_word */
|
||||
Word : TRUE { $$ = SCI->handle_word( TRUE ); } ;
|
||||
Word : FALSE { $$ = SCI->handle_word( FALSE ); } ;
|
||||
Word : LESS { $$ = SCI->handle_word( LESS ); } ;
|
||||
Word : MORE { $$ = SCI->handle_word( MORE ); } ;
|
||||
Word : LESS_EQUAL { $$ = SCI->handle_word( LESS_EQUAL ); } ;
|
||||
Word : MORE_EQUAL { $$ = SCI->handle_word( MORE_EQUAL ); } ;
|
||||
Word : NOT_EQUAL { $$ = SCI->handle_word( NOT_EQUAL ); } ;
|
||||
Word : EQUAL { $$ = SCI->handle_word( EQUAL ); } ;
|
||||
Word : PLUS { $$ = SCI->handle_word( PLUS ); } ;
|
||||
Word : MINUS { $$ = SCI->handle_word( MINUS ); } ;
|
||||
Word : INCR { $$ = SCI->handle_word( INCR ); } ;
|
||||
Word : DECR { $$ = SCI->handle_word( DECR ); } ;
|
||||
Word : MULT { $$ = SCI->handle_word( MULT ); } ;
|
||||
Word : DIV { $$ = SCI->handle_word( DIV ); } ;
|
||||
Word : MODULUS { $$ = SCI->handle_word( MODULUS ); } ;
|
||||
Word : NEGATE { $$ = SCI->handle_word( NEGATE ); } ;
|
||||
Word : ABS { $$ = SCI->handle_word( ABS ); } ;
|
||||
Word : MIN { $$ = SCI->handle_word( MIN ); } ;
|
||||
Word : MAX { $$ = SCI->handle_word( MAX ); } ;
|
||||
Word : STAR_SLASH { $$ = SCI->handle_word( STAR_SLASH ); } ;
|
||||
Word : AND { $$ = SCI->handle_word( AND ); } ;
|
||||
Word : OR { $$ = SCI->handle_word( OR ); } ;
|
||||
Word : XOR { $$ = SCI->handle_word( XOR ); } ;
|
||||
Word : LSHIFT { $$ = SCI->handle_word( LSHIFT ); } ;
|
||||
Word : RSHIFT { $$ = SCI->handle_word( RSHIFT ); } ;
|
||||
Word : DROP { $$ = SCI->handle_word( DROP ); } ;
|
||||
Word : DROP2 { $$ = SCI->handle_word( DROP2 ); } ;
|
||||
Word : NIP { $$ = SCI->handle_word( NIP ); } ;
|
||||
Word : NIP2 { $$ = SCI->handle_word( NIP2 ); } ;
|
||||
Word : DUP { $$ = SCI->handle_word( DUP ); } ;
|
||||
Word : DUP2 { $$ = SCI->handle_word( DUP2 ); } ;
|
||||
Word : SWAP { $$ = SCI->handle_word( SWAP ); } ;
|
||||
Word : SWAP2 { $$ = SCI->handle_word( SWAP2 ); } ;
|
||||
Word : OVER { $$ = SCI->handle_word( OVER ); } ;
|
||||
Word : OVER2 { $$ = SCI->handle_word( OVER2 ); } ;
|
||||
Word : ROT { $$ = SCI->handle_word( ROT ); } ;
|
||||
Word : ROT2 { $$ = SCI->handle_word( ROT2 ); } ;
|
||||
Word : RROT { $$ = SCI->handle_word( RROT ); } ;
|
||||
Word : RROT2 { $$ = SCI->handle_word( RROT2 ); } ;
|
||||
Word : TUCK { $$ = SCI->handle_word( TUCK ); } ;
|
||||
Word : TUCK2 { $$ = SCI->handle_word( TUCK2 ); } ;
|
||||
Word : ROLL { $$ = SCI->handle_word( ROLL ); } ;
|
||||
Word : PICK { $$ = SCI->handle_word( PICK ); } ;
|
||||
Word : SELECT { $$ = SCI->handle_word( SELECT ); } ;
|
||||
Word : MALLOC { $$ = SCI->handle_word( MALLOC ); } ;
|
||||
Word : FREE { $$ = SCI->handle_word( FREE ); } ;
|
||||
Word : GET { $$ = SCI->handle_word( GET ); } ;
|
||||
Word : PUT { $$ = SCI->handle_word( PUT ); } ;
|
||||
Word : RECURSE { $$ = SCI->handle_word( RECURSE ); } ;
|
||||
Word : RETURN { $$ = SCI->handle_word( RETURN ); } ;
|
||||
Word : EXIT { $$ = SCI->handle_word( EXIT ); } ;
|
||||
Word : TAB { $$ = SCI->handle_word( TAB ); };
|
||||
Word : SPACE { $$ = SCI->handle_word( SPACE ); } ;
|
||||
Word : CR { $$ = SCI->handle_word( CR ); } ;
|
||||
Word : IN_STR { $$ = SCI->handle_word( IN_STR ); } ;
|
||||
Word : IN_NUM { $$ = SCI->handle_word( IN_NUM ); } ;
|
||||
Word : IN_CHAR { $$ = SCI->handle_word( IN_CHAR ); } ;
|
||||
Word : OUT_STR { $$ = SCI->handle_word( OUT_STR ); } ;
|
||||
Word : OUT_NUM { $$ = SCI->handle_word( OUT_NUM ); } ;
|
||||
Word : OUT_CHAR { $$ = SCI->handle_word( OUT_CHAR ); } ;
|
||||
Word : DUMP { $$ = SCI->handle_word( DUMP ); } ;
|
||||
|
||||
%%
|
||||
|
||||
/* Handle messages a little more nicely than the default yyerror */
|
||||
int yyerror(const char *ErrorMsg) {
|
||||
std::string where
|
||||
= std::string((SCI->filename() == "-") ? std::string("<stdin>") : SCI->filename())
|
||||
+ ":" + utostr((unsigned) Stackerlineno ) + ": ";
|
||||
std::string errMsg = std::string(ErrorMsg) + "\n" + where + " while reading ";
|
||||
if (yychar == YYEMPTY)
|
||||
errMsg += "end-of-file.";
|
||||
else
|
||||
errMsg += "token: '" + std::string(Stackertext, Stackerleng) + "'";
|
||||
StackerCompiler::ThrowException(errMsg);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user