Skip to content

Instantly share code, notes, and snippets.

@mikeymop
Last active November 14, 2018 00:03
Show Gist options
  • Save mikeymop/78209e89d447a5c796e1ba56216738b1 to your computer and use it in GitHub Desktop.
Save mikeymop/78209e89d447a5c796e1ba56216738b1 to your computer and use it in GitHub Desktop.
/*
* lex.cpp
*
* CS280 - Fall 2018
*/
#include <cctype>
#include <map>
using std::map;
#include "tokens.h"
static map<TokenType,string> tokenPrint = {
{ IF, "IF" },
{ THEN, "THEN" },
{ PRINT, "PRINT" },
{ TRUE, "TRUE" },
{ FALSE, "FALSE" },
{ IDENT, "IDENT" },
{ ICONST, "ICONST" },
{ SCONST, "SCONST" },
{ PLUS, "PLUS" },
{ MINUS, "MINUS" },
{ STAR, "STAR" },
{ SLASH, "SLASH" },
{ ASSIGN, "ASSIGN" },
{ EQ, "EQ" },
{ NEQ, "NEQ" },
{ LT, "LT" },
{ LEQ, "LEQ" },
{ GT, "GT" },
{ GEQ, "GEQ" },
{ LOGICAND, "LOGICAND" },
{ LOGICOR, "LOGICOR" },
{ SC, "SC" },
{ ERR, "ERR" },
{ DONE, "DONE" }
};
ostream& operator<<(ostream& out, const Token& tok) {
TokenType tt = tok.GetTokenType();
out << tokenPrint[ tt ];
if( tt == IDENT || tt == ICONST || tt == SCONST || tt == ERR ) {
out << "(" << tok.GetLexeme() << ")";
}
return out;
}
static map<string,TokenType> kwmap = {
{ "if", IF },
{ "then", THEN },
{ "print", PRINT },
{ "true", TRUE },
{ "false", FALSE },
};
Token
id_or_kw(const string& lexeme, int linenum)
{
TokenType tt = IDENT;
auto kIt = kwmap.find(lexeme);
if( kIt != kwmap.end() )
tt = kIt->second;
return Token(tt, lexeme, linenum);
}
// macro to putback and decrement if newline
// the string PB is replaced by this block of code... it's a little hacky
#define PB { in->putback(ch); if( ch == '\n' ) (*linenum)--; }
// inline function to putback and decrement if newline
// this is cleaner but longer to call
inline void PutBack(char ch, istream *in, int *linenum) {
in->putback(ch);
if( ch == '\n' )
(*linenum)--;
}
// another version of the macro could have been
#define PB2(ch,in,linenum) { in->putback(ch); if( ch == '\n' ) (*linenum)--; }
Token
getNextToken(istream *in, int *linenum)
{
enum LexState { BEGIN, INID, INSTRING, SAWEQ, SAWLT, SAWGT, SAWAND, SAWOR, SAWNOT, ININT, INCOMMENT } lexstate = BEGIN;
string lexeme;
char ch;
while(in->get(ch)) {
if( ch == '\n' ) {
(*linenum)++;
}
switch( lexstate ) {
case BEGIN:
if( isspace(ch) )
continue;
lexeme = ch;
if( isalpha(ch) ) {
lexstate = INID;
}
else if( ch == '"' ) {
lexstate = INSTRING;
}
else if( ch == '=' ) {
lexstate = SAWEQ;
}
else if( ch == '!' ) {
if( in->peek() == '=' ) {
in->get(ch);
return Token(NEQ, "!=", *linenum);
}
else {
if( in->peek() == '\n' )
(*linenum)++;
return Token(ERR, "!", *linenum);
}
}
else if( ch == '>' ) {
lexstate = SAWGT;
}
else if( ch == '<' ) {
lexstate = SAWLT;
}
else if( ch == '&' ) {
lexstate = SAWAND;
}
else if( ch == '|' ) {
lexstate = SAWOR;
}
else if( ch == '!' ) {
lexstate = SAWNOT;
}
else if( isdigit(ch) ) {
lexstate = ININT;
}
else if( ch == '#' ) {
lexstate = INCOMMENT;
}
else {
TokenType tt = ERR;
switch( ch ) {
case '+':
tt = PLUS;
break;
case '-':
tt = MINUS;
break;
case '*':
tt = STAR;
break;
case '/':
tt = SLASH;
break;
case '(':
tt = LPAREN;
break;
case ')':
tt = RPAREN;
break;
case ';':
tt = SC;
break;
}
return Token(tt, lexeme, *linenum);
}
break;
case INID:
if( isalpha(ch) || isdigit(ch) ) {
lexeme += ch;
}
else {
if( ch == '\n' )
(*linenum)--;
in->putback(ch);
return id_or_kw(lexeme, *linenum);
}
break;
case INSTRING:
lexeme += ch;
if( ch == '\n' ) {
return Token(ERR, lexeme, *linenum );
}
if( ch == '"' ) {
lexeme = lexeme.substr(1, lexeme.length()-2);
return Token(SCONST, lexeme, *linenum );
}
break;
case SAWEQ:
if( ch == '=' )
return Token(EQ, lexeme, *linenum);
else {
PB
return Token(ASSIGN, lexeme, *linenum);
}
break;
case SAWGT:
if( ch == '=' )
return Token(GEQ, lexeme, *linenum);
else {
PutBack(ch, in, linenum);
return Token(GT, lexeme, *linenum);
}
break;
case SAWLT:
if( ch == '=' )
return Token(LEQ, lexeme, *linenum);
else {
if( ch == '\n' )
(*linenum)--;
in->putback(ch);
return Token(LT, lexeme, *linenum);
}
break;
case SAWAND:
if( ch == '&' )
return Token(LOGICAND, lexeme, *linenum);
else {
return Token(ERR, lexeme, *linenum);
}
break;
case SAWOR:
if( ch == '|' )
return Token(LOGICOR, lexeme, *linenum);
else {
return Token(ERR, lexeme, *linenum);
}
break;
case SAWNOT:
if( ch == '=' )
return Token(NEQ, lexeme, *linenum);
else {
return Token(ERR, lexeme, *linenum);
}
break;
case ININT:
if( isdigit(ch) ) {
lexeme += ch;
}
else if( isalpha(ch) ) {
lexeme += ch;
return Token(ERR, lexeme, *linenum);
}
else {
if( ch == '\n' )
(*linenum)--;
in->putback(ch);
return Token(ICONST, lexeme, *linenum);
}
break;
case INCOMMENT:
if( ch == '\n' ) {
lexstate = BEGIN;
}
break;
}
}
if( in->eof() )
return Token(DONE, "", *linenum);
return Token(ERR, "some strange I/O error", *linenum);
}
/*
* main.cpp
*/
#include "tokens.h"
#include "parse.h"
#include "parsetree.h"
#include "tokens.h"
#include <iostream>
#include <fstream>
#include <string.h>
using std::cin;
using std::cout;
using std::endl;
using std::ifstream;
/*
array<string, 4> names = {"ERRTYPE", "INTTYPE", "STRTYPE", "BOOLTYPE"};
//Demangles class names when printing them out for debugging.
string demangle(const char* name) {
int status;
char* demangledName = abi::__cxa_demangle(name, nullptr, nullptr, &status);
string retVal = string(demangledName);
free(demangledName);
return retVal;
}
// Prints out the parse tree if debug is enabled.
void debugPrint(ParseTree* tree, uint level = 0) {
ParseTree* currTree = tree->getLeft();
string className = demangle(typeid(*tree).name());
cout << string(level, '\t') << className << string(8 - level - className.length() / 4, '\t') << names[tree->GetType()] << '\n';
if (currTree)
debugPrint(currTree, level + 1);
currTree = tree->getRight();
if (currTree)
debugPrint(currTree, level + (tree->GetType() != treeType::STMTLIST));
}
*/
void ParseOut(ParseTree *prog);
int main(int argc, char *argv[]) {
ifstream ifile;
istream *in;
int linenum = 0;
//Token tok;
// CHECK ARGUMENTS, OPEN FILES
if(argc == 1) {
in = &cin;
}
if(argc > 2) {
cout << "TOO MANY FILENAMES" << endl;
return 1;
}
if(argc == 2) {
ifile.open(argv[1]);
if(!ifile.is_open()) {
string x = argv[1];
cout << "COULD NOT OPEN " << x << endl;
return 2;
}
} else {
in = &ifile;
}
ParseTree *prog = Prog(in, &linenum);
if( prog == 0 )
return 0; // quit on error
ParseOut(prog);
return 0;
}
/*
* parse.cpp
*/
#include "parse.h"
#include "parsetree.h"
#include "tokens.h"
#include <string.h>
#include <vector>
#include <algorithm>
/* GRAMMAR
Prog := Slist
Slist := Stmt SC { Slist }
Stmt := IfStmt | PrintStmt | Expr
IfStmt := IF Expr THEN Stmt
PrintStmt := PRINT Expr
Expr := LogicExpr { ASSIGN LogicExpr }
LogicExpr := CompareExpr { (LOGICAND | LOGICOR) CompareExpr }
CompareExpr := AddExpr { (EQ | NEQ | GT | GEQ | LT | LEQ) AddExpr }
AddExpr := MulExpr { (PLUS | MINUS) MulExpr }
MulExpr := Factor { (STAR | SLASH) Factor }
Factor := MINUS Primary | Primary
Primary := IDENT | ICONST | SCONST | TRUE | FALSE | LPAREN Expr
RPAREN
*/
//int stringct = 0;
int identct = 0;
std::string tempWord = "";
std::vector<std::string> idents;
void ParseOut(ParseTree *prog) {
cout << "LEAF COUNT: " << prog->LeafCount() << endl;
cout << "STRING COUNT: " << prog->StringCount() << endl;
if(identct != 0) {
cout << "IDENT COUNT: " << identct << endl;
//need alphabetical order
sort(idents.begin(), idents.end());
//have to remove dupes
idents.erase(unique(idents.begin(), idents.end()), idents.end());
//cout << "IDENTIFIERS: ";
for (int i = 0; i <= idents.size() - 1; ++i) {
if(i == idents.size()-1) {
cout << idents[i] << endl;
} else {
cout << idents[i] << ", ";
}
}
}
}
// WRAPPER FOR PUSHBACK
namespace Parser {
bool pushed_back = false;
Token pushed_token;
static Token GetNextToken(istream *in, int *line) {
if( pushed_back ) {
pushed_back = false;
return pushed_token;
}
return getNextToken(in, line);
}
static void PushBackToken(Token& t) {
if( pushed_back ) {
abort();
}
pushed_back = true;
pushed_token = t;
}
}
static int error_count = 0;
void ParseError(int line, string msg) {
++error_count;
cout << line << ": " << msg << endl;
}
ParseTree *Prog(istream *in, int *line) {
ParseTree *sl = Slist(in, line);
if( sl == 0 )
ParseError(*line, "No statements in program");
if( error_count )
return 0;
return sl;
}
// Slist is a Statement followed by a Statement List
ParseTree *Slist(istream *in, int *line) {
ParseTree *s = Stmt(in, line);
if( s == 0 )
return 0;
if( Parser::GetNextToken(in, line) != SC ) {
ParseError(*line, "Missing semicolon");
return 0;
}
return new StmtList(s, Slist(in,line));
}
ParseTree *Stmt(istream *in, int *line) {
ParseTree *s;
Token t = Parser::GetNextToken(in, line);
switch( t.GetTokenType() ) {
case IF:
s = IfStmt(in, line);
break;
case PRINT:
s = PrintStmt(in, line);
break;
case DONE:
return 0;
case ERR:
ParseError(*line, "Invalid token");
return 0;
default:
// put back the token and then see if it's an Expr
Parser::PushBackToken(t);
s = Expr(in, line);
if( s == 0 ) {
ParseError(*line, "Invalid statement");
return 0;
}
break;
}
return s;
}
ParseTree *IfStmt(istream *in, int *line) {
//assume next node is Expr
ParseTree *ex = Expr(in, line);
if (ex == 0) {
ParseError(*line, "Invalid statement");
return 0;
}
Token t = Parser::GetNextToken(in, line);
ParseTree *stmt = Stmt(in, line);
if(t.GetTokenType() != THEN ) {
ParseError(*line, "If statement screwed up");
return 0;
}
if(stmt == 0) {
ParseError(*line, "Invalid statement");
}
return new IfStatement(t.GetLinenum(), ex, stmt);
}
ParseTree *PrintStmt(istream *in, int *line) {
// ADD HANDLER
// if parse tree type is printstatement add it to parse tree list?
ParseTree *ex = Expr(in, line);
if(ex == 0) {
ParseError(*line, "Bad prt stmt");
return 0;
}
return new PrintStatement(ex->GetLinenum(), ex);
}
ParseTree *Expr(istream *in, int *line) {
ParseTree *t1 = LogicExpr(in, line);
if( t1 == 0 ) {
return 0;
}
Token t = Parser::GetNextToken(in, line);
if( t != ASSIGN ) {
Parser::PushBackToken(t);
return t1;
}
ParseTree *t2 = Expr(in, line); // right assoc
if( t2 == 0 ) {
ParseError(*line, "Missing expression after operator");
return 0;
}
return new Assignment(t2->GetLinenum(), t1, t2);
}
ParseTree *LogicExpr(istream *in, int *line) {
ParseTree *t1 = CompareExpr(in, line);
if( t1 == 0 ) {
return 0;
}
// HANDLE OP
while (true) {
Token t = Parser::GetNextToken(in, line);
if(t != LOGICAND && t != LOGICOR) {
Parser::PushBackToken(t);
return t1;
}
//right node
ParseTree *t2 = CompareExpr(in, line);
//if its not a valid expr for right leaf
if(t2 == 0) {
ParseError(*line, "Missing expression after op");
return 0;
}
//return right leaf
if(t == LOGICAND) {
return new LogicAndExpr(t.GetLinenum(), t1, t2);
} else {
return new LogicOrExpr(t.GetLinenum(), t1, t2);
}
}
return 0;
}
ParseTree *CompareExpr(istream *in, int *line) {
ParseTree *t1 = AddExpr(in, line);
if( t1 == 0 ) {
return 0;
}
// HANDLE OP
while (true) {
Token t = Parser::GetNextToken(in, line);
if(t != EQ && t != NEQ && t != LT && t != LEQ && t != GT && t != GEQ) {
Parser::PushBackToken(t);
return t1;
}
//right node
ParseTree *t2 = CompareExpr(in, line);
//if its not a valid expr for right leaf
if(t2 == 0) {
ParseError(*line, "Missing expression after op");
return 0;
}
//return right leaf
switch(t.GetTokenType()) {
case EQ:
return new EqExpr(t.GetLinenum(), t1, t2);
case NEQ:
return new NEqExpr(t.GetLinenum(), t1, t2);
case LT:
return new LtExpr(t.GetLinenum(), t1, t2);
case LEQ:
return new LEqExpr(t.GetLinenum(), t1, t2);
case GT:
return new GtExpr(t.GetLinenum(), t1, t2);
case GEQ:
return new GEqExpr(t.GetLinenum(), t1, t2);
default:
return 0;
}
}
//return 0;
}
ParseTree *AddExpr(istream *in, int *line) {
ParseTree *t1 = MulExpr(in, line);
if( t1 == 0 ) {
return 0;
}
while ( true ) {
Token t = Parser::GetNextToken(in, line);
if( t != PLUS && t != MINUS ) {
Parser::PushBackToken(t);
return t1;
}
ParseTree *t2 = MulExpr(in, line);
if( t2 == 0 ) {
ParseError(*line, "Missing expression after operator");
return 0;
}
if( t == PLUS )
t1 = new PlusExpr(t.GetLinenum(), t1, t2);
else
t1 = new MinusExpr(t.GetLinenum(), t1, t2);
}
}
ParseTree *MulExpr(istream *in, int *line) {
ParseTree *t1 = Factor(in, line);
if( t1 == 0 ) {
return 0;
}
// HANDLE OP
while ( true ) {
Token t = Parser::GetNextToken(in, line);
if(t != STAR && t != SLASH) {
Parser::PushBackToken(t);
return t1;
}
//2nd factor
ParseTree *t2 = Factor(in, line);
if( t2 == 0 ) {
ParseError(*line, "Missing expression after operator");
return 0;
}
//return the expressions
if( t != STAR )
t1 = new TimesExpr(t.GetLinenum(), t1, t2);
else
t1 = new DivideExpr(t.GetLinenum(), t1, t2);
}
}
ParseTree *Factor(istream *in, int *line) {
bool neg = false;
Token t = Parser::GetNextToken(in, line);
if( t == MINUS ) {
neg = true;
}
else {
Parser::PushBackToken(t);
}
ParseTree *p1 = Primary(in, line);
if( p1 == 0 ) {
ParseError(*line, "Missing primary");
return 0;
}
if( neg ) {
// handle as -1 * Primary
return new TimesExpr(t.GetLinenum(), new IConst(t.GetLinenum(), -1), p1);
}
else
return p1;
}
ParseTree *Primary(istream *in, int *line) {
Token t = Parser::GetNextToken(in, line);
// PROCESS TOKEN, IDENTIFY PRIMARY, RETURN SOMETHING
switch( t.GetTokenType() ) {
case IDENT:
//make ident map and append to it
identct++;
tempWord = t.GetLexeme();
idents.push_back(tempWord);
return new Ident(t);
case ICONST:
return new IConst(t);
case SCONST:
return new SConst(t);
case TRUE:
return new BoolConst(t, TRUE);
case FALSE:
return new BoolConst(t, FALSE);
case LPAREN:
{
ParseTree *ex = Expr(in, line);
Token t1 = Parser::GetNextToken(in, line);
if (t1 != RPAREN) {
ParseError(t1.GetLinenum(), "Syntax Err");
Parser::PushBackToken(t1);
return 0;
} else {
return ex;
}
}
default:
// put back the token and then see if it's an Expr
Parser::PushBackToken(t);
ParseError(*line, "Invalid statement");
return 0;
}//case
}//Parsetree
/*
* parse.h
*/
/* GRAMMAR
Prog := Slist
Slist := Stmt SC { Slist }
Stmt := IfStmt | PrintStmt | Expr
-+IfStmt := IF Expr THEN Stmt
+PrintStmt := PRINT Expr
Expr := LogicExpr { ASSIGN LogicExpr }
-+LogicExpr := CompareExpr { (LOGICAND | LOGICOR) CompareExpr }
-+CompareExpr := AddExpr { (EQ | NEQ | GT | GEQ | LT | LEQ) AddExpr }
AddExpr := MulExpr { (PLUS | MINUS) MulExpr }
-+MulExpr := Factor { (STAR | SLASH) Factor }
Factor := MINUS Primary | Primary
-+Primary := IDENT | ICONST | SCONST | TRUE | FALSE | LPAREN Expr
RPAREN
*/
#ifndef PARSE_H_
#define PARSE_H_
#include <iostream>
using namespace std;
#include "tokens.h"
#include "parsetree.h"
extern ParseTree *Prog(istream *in, int *line);
extern ParseTree *Slist(istream *in, int *line);
extern ParseTree *Stmt(istream *in, int *line);
extern ParseTree *IfStmt(istream *in, int *line);
extern ParseTree *PrintStmt(istream *in, int *line);
extern ParseTree *Expr(istream *in, int *line);
extern ParseTree *LogicExpr(istream *in, int *line);
extern ParseTree *CompareExpr(istream *in, int *line);
extern ParseTree *AddExpr(istream *in, int *line);
extern ParseTree *MulExpr(istream *in, int *line);
extern ParseTree *Factor(istream *in, int *line);
extern ParseTree *Primary(istream *in, int *line);
#endif /* PARSE_H_ */
/*
* parsetree.h
*/
#ifndef PARSETREE_H_
#define PARSETREE_H_
#include <vector>
#include <map>
using std::vector;
using std::map;
// NodeType represents all possible types
enum NodeType { ERRTYPE, INTTYPE, STRTYPE, BOOLTYPE };
// a "forward declaration" for a class to hold values
class Value;
class ParseTree {
int linenum;
ParseTree *left;
ParseTree *right;
public:
ParseTree(int linenum, ParseTree *l = 0, ParseTree *r = 0)
: linenum(linenum), left(l), right(r) {}
virtual ~ParseTree() {
delete left;
delete right;
}
int GetLinenum() const { return linenum; }
virtual NodeType GetType() const { return ERRTYPE; }
int LeafCount() const {
int lc = 0;
if( left ) lc += left->LeafCount();
if( right ) lc += right->LeafCount();
if( left == 0 && right == 0 )
lc++;
return lc;
}
// other methods
int StringCount() const {
int sc = 0;
if( left ) sc += left->LeafCount();
if( right ) sc += right->LeafCount();
if((*this).GetType() == STRTYPE)
sc++;
return sc;
}
};
class StmtList : public ParseTree {
public:
StmtList(ParseTree *l, ParseTree *r) : ParseTree(0, l, r) {}
};
class IfStatement : public ParseTree {
public:
IfStatement(int line, ParseTree *ex, ParseTree *stmt) : ParseTree(line, ex, stmt) {}
};
class Assignment : public ParseTree {
public:
Assignment(int line, ParseTree *lhs, ParseTree *rhs) : ParseTree(line, lhs, rhs) {}
};
class PrintStatement : public ParseTree {
public:
PrintStatement(int line, ParseTree *e) : ParseTree(line, e) {}
};
class PlusExpr : public ParseTree {
public:
PlusExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class MinusExpr : public ParseTree {
public:
MinusExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class TimesExpr : public ParseTree {
public:
TimesExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class DivideExpr : public ParseTree {
public:
DivideExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class LogicAndExpr : public ParseTree {
public:
LogicAndExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class LogicOrExpr : public ParseTree {
public:
LogicOrExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class EqExpr : public ParseTree {
public:
EqExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class NEqExpr : public ParseTree {
public:
NEqExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class LtExpr : public ParseTree {
public:
LtExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class LEqExpr : public ParseTree {
public:
LEqExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class GtExpr : public ParseTree {
public:
GtExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class GEqExpr : public ParseTree {
public:
GEqExpr(int line, ParseTree *l, ParseTree *r) : ParseTree(line,l,r) {}
};
class IConst : public ParseTree {
int val;
public:
IConst(int l, int i) : ParseTree(l), val(i) {}
IConst(Token& t) : ParseTree(t.GetLinenum()) {
val = stoi(t.GetLexeme());
}
NodeType GetType() const { return INTTYPE; }
};
class BoolConst : public ParseTree {
bool val;
public:
BoolConst(Token& t, bool val) : ParseTree(t.GetLinenum()), val(val) {}
NodeType GetType() const { return BOOLTYPE; }
};
class SConst : public ParseTree {
string val;
public:
SConst(Token& t) : ParseTree(t.GetLinenum()) {
val = t.GetLexeme();
}
NodeType GetType() const { return STRTYPE; }
};
class Ident : public ParseTree {
string id;
public:
Ident(Token& t) : ParseTree(t.GetLinenum()), id(t.GetLexeme()) {}
};
#endif /* PARSETREE_H_ */
true; true; true;
"waffles";
45;
327;
10312;
if 77 then true;
/*
* projlex.h
*
* CS280
* Spring 2018
*/
#ifndef TOKENS_H_
#define TOKENS_H_
#include <string>
#include <iostream>
using std::string;
using std::istream;
using std::ostream;
enum TokenType {
// keywords
PRINT,
IF,
THEN,
TRUE,
FALSE,
// an identifier
IDENT,
// an integer and string constant
ICONST,
SCONST,
// the operators, parens and semicolon
PLUS,
MINUS,
STAR,
SLASH,
ASSIGN,
EQ,
NEQ,
LT,
LEQ,
GT,
GEQ,
LOGICAND,
LOGICOR,
LPAREN,
RPAREN,
SC,
// any error returns this token
ERR,
// when completed (EOF), return this token
DONE
};
class Token {
TokenType tt;
string lexeme;
int lnum;
public:
Token() {
tt = ERR;
lnum = -1;
}
Token(TokenType tt, string lexeme, int line) {
this->tt = tt;
this->lexeme = lexeme;
this->lnum = line;
}
bool operator==(const TokenType tt) const { return this->tt == tt; }
bool operator!=(const TokenType tt) const { return this->tt != tt; }
TokenType GetTokenType() const { return tt; }
string GetLexeme() const { return lexeme; }
int GetLinenum() const { return lnum; }
};
extern ostream& operator<<(ostream& out, const Token& tok);
extern Token getNextToken(istream *in, int *linenum);
#endif /* TOKENS_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment