126 lines
3.6 KiB
Plaintext
126 lines
3.6 KiB
Plaintext
%skeleton "lalr1.cc"
|
|
%require "3.8"
|
|
%defines
|
|
%define api.parser.class { Parser }
|
|
%define api.token.constructor
|
|
%define api.value.type variant
|
|
%define parse.assert
|
|
%define api.namespace { stela }
|
|
|
|
%code requires {
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <cstdint>
|
|
#include "command.hpp"
|
|
|
|
namespace stela {
|
|
class Lexer;
|
|
class Interpreter;
|
|
}
|
|
}
|
|
|
|
%code top {
|
|
#include <iostream>
|
|
#include <cstdint>
|
|
#include "lexer.hpp"
|
|
#include "parser.hpp"
|
|
#include "interpreter.hpp"
|
|
#include "location.hh"
|
|
|
|
static stela::Parser::symbol_type yylex(stela::Lexer& lexer, stela::Interpreter& interpreter)
|
|
{
|
|
return lexer.next_token();
|
|
}
|
|
|
|
using namespace stela;
|
|
}
|
|
|
|
%lex-param { stela::Lexer& lexer }
|
|
%lex-param { stela::Interpreter& interpreter }
|
|
%parse-param { stela::Lexer& lexer }
|
|
%parse-param { stela::Interpreter& interpreter }
|
|
%locations
|
|
%define parse.trace
|
|
%define parse.error verbose
|
|
%define api.token.prefix {TOKEN_}
|
|
|
|
%token END 0 "end of file"
|
|
%token <std::string> STRING "string";
|
|
%token <uint64_t> NUMBER "number";
|
|
%token LEFTPAR "leftpar";
|
|
%token RIGHTPAR "rightpar";
|
|
%token SEMICOLON "semicolon";
|
|
%token COMMA "comma";
|
|
|
|
%type <stela::Command> command;
|
|
%type <std::vector<uint64_t>> arguments;
|
|
|
|
%start program
|
|
|
|
%%
|
|
|
|
program: {
|
|
std::cout << "*** RUN ***\n";
|
|
std::cout << "Type function with list of parmeters. Parameter list can be empty\n"
|
|
<< "or contain positive integers only. Examples: \n"
|
|
<< " * function()\n"
|
|
<< " * function(1,2,3)\n"
|
|
<< "Terminate listing with ; to see parsed AST\n"
|
|
<< "Terminate parser with Ctrl-D\n";
|
|
|
|
std::cout << '\n' << "prompt> ";
|
|
interpreter.clear();
|
|
}
|
|
| program command {
|
|
const Command &cmd = $2;
|
|
std::cout << "command parsed, updating AST\n";
|
|
interpreter.add_command(cmd);
|
|
std::cout << '\n' << "prompt> ";
|
|
}
|
|
| program SEMICOLON {
|
|
std::cout << "*** STOP RUN ***\n";
|
|
std::cout << interpreter.to_string() << '\n';
|
|
}
|
|
;
|
|
|
|
|
|
command : STRING LEFTPAR RIGHTPAR {
|
|
std::string &id = $1;
|
|
std::cout << "ID: " << id << '\n';
|
|
$$ = Command(id);
|
|
}
|
|
| STRING LEFTPAR arguments RIGHTPAR {
|
|
std::string &id = $1;
|
|
const std::vector<uint64_t> &args = $3;
|
|
std::cout << "function: " << id << ", " << args.size() << '\n';
|
|
$$ = Command(id, args);
|
|
}
|
|
;
|
|
|
|
arguments : NUMBER {
|
|
uint64_t number = $1;
|
|
$$ = std::vector<uint64_t>();
|
|
$$.push_back(number);
|
|
std::cout << "first argument: " << number << '\n';
|
|
}
|
|
| arguments COMMA NUMBER {
|
|
uint64_t number = $3;
|
|
std::vector<uint64_t> &args = $1;
|
|
args.push_back(number);
|
|
$$ = args;
|
|
std::cout << "next argument: " << number << ", arg list size = " << args.size() << '\n';
|
|
}
|
|
;
|
|
|
|
%%
|
|
|
|
void stela::Parser::error(const location &loc , const std::string &message) {
|
|
// Location should be initialized inside scanner action, but is not in this example.
|
|
// Let's grab location directly from driver class.
|
|
// std::cout << "Error: " << message << '\n' << "Location: " << loc << '\n';
|
|
std::cout << "Error: " << message << '\n' << "Error location: " << interpreter.location() << '\n';
|
|
}
|
|
|
|
// vim: ts=4 sw=4 et
|