Parser.cpp
No OneTemporary

File Metadata

Created
Wed, Jul 8, 8:12 AM

Parser.cpp

/*----------------------------------------------------------------------
Compiler Generator Coco/R,
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
extended by M. Loeberbauer & A. Woess, Univ. of Linz
ported to C++ by Csaba Balazs, University of Szeged
with improvements by Pat Terry, Rhodes University
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As an exception, it is allowed to write an extension of Coco/R that is
used as a plugin in non-free software.
If not otherwise stated, any source code generated by Coco/R (other than
Coco/R itself) does not fall under the GNU General Public License.
-----------------------------------------------------------------------*/
#include <wchar.h>
#include "Parser.h"
#include "Scanner.h"
void Parser::SynErr(int n) {
if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n);
errDist = 0;
}
void Parser::SemErr(const wchar_t* msg) {
if (errDist >= minErrDist) errors->Error(t->line, t->col, msg);
errDist = 0;
}
void Parser::Get() {
for (;;) {
t = la;
la = scanner->Scan();
if (la->kind <= maxT) { ++errDist; break; }
if (dummyToken != t) {
dummyToken->kind = t->kind;
dummyToken->pos = t->pos;
dummyToken->col = t->col;
dummyToken->line = t->line;
dummyToken->next = NULL;
coco_string_delete(dummyToken->val);
dummyToken->val = coco_string_create(t->val);
t = dummyToken;
}
la = t;
}
}
void Parser::Expect(int n) {
if (la->kind==n) Get(); else { SynErr(n); }
}
void Parser::ExpectWeak(int n, int follow) {
if (la->kind == n) Get();
else {
SynErr(n);
while (!StartOf(follow)) Get();
}
}
bool Parser::WeakSeparator(int n, int syFol, int repFol) {
if (la->kind == n) {Get(); return true;}
else if (StartOf(repFol)) {return false;}
else {
SynErr(n);
while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) {
Get();
}
return StartOf(syFol);
}
}
void Parser::Xreate() {
while (la->kind == _ident || la->kind == 26 /* "rule" */) {
if (la->kind == _ident) {
FDecl();
} else {
RuleDecl();
}
}
}
void Parser::FDecl() {
std::wstring fname; std::wstring varname; TypeAnnotation typIn; TypeAnnotation typOut;
Ident(fname);
Expect(_assign);
Expect(10 /* "function" */);
Expect(11 /* ":" */);
Function f = Function(fname);
if (StartOf(1)) {
Type(typOut);
f.setReturnType(typOut);
} else if (la->kind == _lparen) {
Get();
if (la->kind == _ident) {
Ident(varname);
Expect(11 /* ":" */);
Type(typIn);
f.addArg(std::move(varname), move(typIn));
while (la->kind == 12 /* "," */) {
Get();
Ident(varname);
Expect(11 /* ":" */);
Type(typIn);
f.addArg(std::move(varname), move(typIn));
}
}
Expect(_rparen);
Expect(_implic);
Type(typOut);
f.setReturnType(typOut);
while (la->kind == 12 /* "," */) {
Get();
FnTag(f);
}
} else SynErr(37);
BDecl(f.getEntryScope());
root.add(f);
}
void Parser::RuleDecl() {
Expect(26 /* "rule" */);
Expect(11 /* ":" */);
RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg;
Expect(_lparen);
Ident(arg);
Expect(11 /* ":" */);
Domain(typ);
args.add(arg, typ);
while (la->kind == 12 /* "," */) {
Get();
Ident(arg);
Expect(11 /* ":" */);
Domain(typ);
args.add(arg, typ);
}
Expect(_rparen);
if (la->kind == 27 /* "case" */) {
Get();
RGuard(guards);
while (la->kind == 12 /* "," */) {
Get();
RGuard(guards);
}
}
Expect(19 /* "{" */);
RBody(args, guards);
Expect(20 /* "}" */);
}
void Parser::Ident(std::wstring& name) {
Expect(_ident);
name = t->val;
}
void Parser::Type(TypeAnnotation& typ) {
TypeAnnotation typ2; TypeAtom typ3;
if (la->kind == _lbrack) {
Get();
Type(typ2);
Expect(_rbrack);
typ = TypeAnnotation(TypeOperator::LIST, {typ2});
} else if (StartOf(2)) {
TypeTerm(typ3);
typ = TypeAnnotation(typ3);
} else SynErr(38);
}
void Parser::FnTag(Function& f) {
Expression tag; TagModifier mod = TagModifier::NONE;
MetaSimpExpr(tag);
if (la->kind == 23 /* "-" */) {
Get();
TagMod(mod);
}
f.addTag(std::move(tag), mod);
}
void Parser::BDecl(CodeScope& scope) {
Expression body;
Expect(19 /* "{" */);
while (StartOf(3)) {
if (checkAssignment()) {
VDecl(scope);
Expect(18 /* ";" */);
} else if (la->kind == 11 /* ":" */) {
TagsDecl(scope);
Expect(18 /* ";" */);
} else {
Expr(body);
Expect(18 /* ";" */);
scope.setBody(body);
}
}
Expect(20 /* "}" */);
}
void Parser::TypeTerm(TypeAtom& typ) {
if (la->kind == 13 /* "string" */) {
Get();
} else if (la->kind == 14 /* "int" */) {
Get();
} else if (la->kind == 15 /* "num" */) {
Get();
} else if (la->kind == 16 /* "float" */) {
Get();
} else if (la->kind == 17 /* "bool" */) {
Get();
} else SynErr(39);
typ = Atom<Type_t>(t->val);
}
void Parser::VDecl(CodeScope& f) {
std::wstring vname; Expression e; TypeAnnotation typ;
Ident(vname);
Expect(_assign);
if (la->kind == _lbrack) {
ListLiteral(e);
Expect(11 /* ":" */);
Type(typ);
} else if (la->kind == 21 /* "loop" */) {
LoopDecl(e, typ);
Expect(18 /* ";" */);
} else if (StartOf(4)) {
Expr(e);
Expect(11 /* ":" */);
Type(typ);
} else SynErr(40);
f.addDeclaration(move(vname), move(typ), move(e));
}
void Parser::ListLiteral(Expression& e) {
Expression e2;
Expect(_lbrack);
e.setOp(Operator::LIST);
if (StartOf(4)) {
Expr(e2);
e.addArg(std::move(e2));
while (la->kind == 12 /* "," */) {
Get();
Expr(e2);
e.addArg(std::move(e2));
}
}
Expect(_rbrack);
}
void Parser::LoopDecl(Expression& e, TypeAnnotation& typOut) {
std::wstring varIn, varEl; TypeAnnotation typEl; CodeScope block;
Expect(21 /* "loop" */);
Expect(22 /* "map" */);
Expect(_lparen);
Ident(varIn);
Expect(_implic);
Ident(varEl);
Expect(11 /* ":" */);
Type(typEl);
Expect(_rparen);
Expect(11 /* ":" */);
Type(typOut);
BDecl(block);
e = Expression(Operator::LOOP, {Expression(Atom<Identifier_t>(varIn))}); e.addBindings({Atom<Identifier_t>(varEl)});
block.addArg(Atom<Identifier_t>(varEl), move(typEl)); e.addBlock(move(block));
}
void Parser::Expr(Expression& e) {
Operator op; Expression e2;
SimExpr(e);
if (la->kind == _assign || la->kind == 34 /* "<" */ || la->kind == 35 /* ">" */) {
RelOp(op);
SimExpr(e2);
e = Expression(op, {e, e2});
}
}
void Parser::TagsDecl(CodeScope& f) {
Expression tag; TagModifier mod = TagModifier::NONE;
Expect(11 /* ":" */);
while (la->kind == _ident || la->kind == 23 /* "-" */) {
MetaSimpExpr(tag);
if (la->kind == 23 /* "-" */) {
Get();
TagMod(mod);
}
}
}
void Parser::MetaSimpExpr(Expression& e) {
std::wstring i1, infix; Expression e2;
if (la->kind == 23 /* "-" */) {
Get();
MetaSimpExpr(e2);
e = Expression(Operator::NEG, {e2});
} else if (checkParametersList()) {
Ident(i1);
e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))});
Expect(_lparen);
if (StartOf(4)) {
CalleeParams(e);
}
Expect(_rparen);
} else if (checkInfix()) {
Ident(i1);
Ident(infix);
MetaSimpExpr(e2);
e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(infix))});
e.addArg(Expression(Atom<Identifier_t>(i1)));
e.addArg(std::move(e2));
} else if (la->kind == _ident) {
Ident(i1);
e = Expression(Atom<Identifier_t>(i1));
} else SynErr(41);
}
void Parser::TagMod(TagModifier& mod) {
if (la->kind == 24 /* "assert" */) {
Get();
mod = TagModifier::ASSERT;
} else if (la->kind == 25 /* "require" */) {
Get();
mod = TagModifier::REQUIRE;
} else SynErr(42);
}
void Parser::Domain(DomainAnnotation& dom) {
if (la->kind == 10 /* "function" */) {
Get();
dom = DomainAnnotation::FUNCTION;
} else if (la->kind == 28 /* "variable" */) {
Get();
dom = DomainAnnotation::VARIABLE;
} else SynErr(43);
}
void Parser::RGuard(RuleGuards& guards) {
Expression e;
MetaExpr(e);
guards.add(std::move(e));
}
void Parser::RBody(const RuleArguments& args, const RuleGuards& guards) {
Expression e; std::wstring msg;
Expect(29 /* "warning" */);
MetaExpr(e);
if (la->kind == 30 /* "message" */) {
Get();
Expect(_string);
msg = t->val;
}
root.add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg)));
}
void Parser::MetaExpr(Expression& e) {
Operator op; Expression e2;
MetaExpr2(e);
if (la->kind == _implic) {
MetaOp(op);
MetaExpr2(e2);
e = Expression(op, {e, e2});
}
}
void Parser::MetaExpr2(Expression& e) {
if (la->kind == _lparen) {
Get();
MetaExpr(e);
Expect(_rparen);
} else if (la->kind == _ident || la->kind == 23 /* "-" */) {
MetaSimpExpr(e);
} else SynErr(44);
}
void Parser::MetaOp(Operator& op) {
Expect(_implic);
op = Operator::IMPL;
}
void Parser::CalleeParams(Expression& e) {
Expression e2;
Expr(e2);
e.addArg(std::move(e2));
while (la->kind == 12 /* "," */) {
Get();
Expr(e2);
e.addArg(std::move(e2));
}
}
void Parser::SimExpr(Expression& e) {
Operator op; Expression e2;
Term(e);
while (la->kind == 23 /* "-" */ || la->kind == 31 /* "+" */) {
AddOp(op);
Term(e2);
e = Expression(op, {e, e2});
}
}
void Parser::RelOp(Operator& op) {
op = Operator::EQU;
if (la->kind == _assign) {
Get();
Expect(_assign);
} else if (la->kind == 34 /* "<" */) {
Get();
op = Operator::LSS;
} else if (la->kind == 35 /* ">" */) {
Get();
op = Operator::GTR;
} else SynErr(45);
}
void Parser::Term(Expression& e) {
Operator op; Expression e2;
Factor(e);
while (la->kind == 32 /* "*" */ || la->kind == 33 /* "/" */) {
MulOp(op);
Factor(e2);
e = Expression(op, {e, e2});
}
}
void Parser::AddOp(Operator& op) {
op = Operator::ADD;
if (la->kind == 31 /* "+" */) {
Get();
} else if (la->kind == 23 /* "-" */) {
Get();
op = Operator::SUB;
} else SynErr(46);
}
void Parser::Factor(Expression& e) {
std::wstring name;
if (checkParametersList()) {
Ident(name);
e = Expression(Operator::CALL, {Atom<Identifier_t>(name)});
Expect(_lparen);
if (StartOf(4)) {
CalleeParams(e);
}
Expect(_rparen);
} else if (checkIndex()) {
Ident(name);
e = Expression(Operator::INDEX, {Atom<Identifier_t>(name)});
Expect(_lbrack);
CalleeParams(e);
Expect(_rbrack);
} else if (la->kind == _ident) {
Ident(name);
e = Expression(Atom<Identifier_t>(name));
} else if (la->kind == _number) {
Get();
e = Expression(Atom<Number_t>(t->val));
} else if (la->kind == 23 /* "-" */) {
Get();
Factor(e);
e = Expression(Operator::NEG, {e});
} else if (la->kind == _lparen) {
Get();
Expr(e);
Expect(_rparen);
} else SynErr(47);
}
void Parser::MulOp(Operator& op) {
op = Operator::MUL;
if (la->kind == 32 /* "*" */) {
Get();
} else if (la->kind == 33 /* "/" */) {
Get();
op = Operator::DIV;
} else SynErr(48);
}
// If the user declared a method Init and a mehtod Destroy they should
// be called in the contructur and the destructor respctively.
//
// The following templates are used to recognize if the user declared
// the methods Init and Destroy.
template<typename T>
struct ParserInitExistsRecognizer {
template<typename U, void (U::*)() = &U::Init>
struct ExistsIfInitIsDefinedMarker{};
struct InitIsMissingType {
char dummy1;
};
struct InitExistsType {
char dummy1; char dummy2;
};
// exists always
template<typename U>
static InitIsMissingType is_here(...);
// exist only if ExistsIfInitIsDefinedMarker is defined
template<typename U>
static InitExistsType is_here(ExistsIfInitIsDefinedMarker<U>*);
enum { InitExists = (sizeof(is_here<T>(NULL)) == sizeof(InitExistsType)) };
};
template<typename T>
struct ParserDestroyExistsRecognizer {
template<typename U, void (U::*)() = &U::Destroy>
struct ExistsIfDestroyIsDefinedMarker{};
struct DestroyIsMissingType {
char dummy1;
};
struct DestroyExistsType {
char dummy1; char dummy2;
};
// exists always
template<typename U>
static DestroyIsMissingType is_here(...);
// exist only if ExistsIfDestroyIsDefinedMarker is defined
template<typename U>
static DestroyExistsType is_here(ExistsIfDestroyIsDefinedMarker<U>*);
enum { DestroyExists = (sizeof(is_here<T>(NULL)) == sizeof(DestroyExistsType)) };
};
// The folloing templates are used to call the Init and Destroy methods if they exist.
// Generic case of the ParserInitCaller, gets used if the Init method is missing
template<typename T, bool = ParserInitExistsRecognizer<T>::InitExists>
struct ParserInitCaller {
static void CallInit(T *t) {
// nothing to do
}
};
// True case of the ParserInitCaller, gets used if the Init method exists
template<typename T>
struct ParserInitCaller<T, true> {
static void CallInit(T *t) {
t->Init();
}
};
// Generic case of the ParserDestroyCaller, gets used if the Destroy method is missing
template<typename T, bool = ParserDestroyExistsRecognizer<T>::DestroyExists>
struct ParserDestroyCaller {
static void CallDestroy(T *t) {
// nothing to do
}
};
// True case of the ParserDestroyCaller, gets used if the Destroy method exists
template<typename T>
struct ParserDestroyCaller<T, true> {
static void CallDestroy(T *t) {
t->Destroy();
}
};
void Parser::Parse() {
t = NULL;
la = dummyToken = new Token();
la->val = coco_string_create(L"Dummy Token");
Get();
Xreate();
Expect(0);
}
Parser::Parser(Scanner *scanner) {
maxT = 36;
ParserInitCaller<Parser>::CallInit(this);
dummyToken = NULL;
t = la = NULL;
minErrDist = 2;
errDist = minErrDist;
this->scanner = scanner;
errors = new Errors();
}
bool Parser::StartOf(int s) {
const bool T = true;
const bool x = false;
static bool set[5][38] = {
{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
{x,x,x,x, x,x,T,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
{x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
{x,T,T,x, T,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
{x,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x}
};
return set[s][la->kind];
}
Parser::~Parser() {
ParserDestroyCaller<Parser>::CallDestroy(this);
delete errors;
delete dummyToken;
}
Errors::Errors() {
count = 0;
}
void Errors::SynErr(int line, int col, int n) {
wchar_t* s;
switch (n) {
case 0: s = coco_string_create(L"EOF expected"); break;
case 1: s = coco_string_create(L"ident expected"); break;
case 2: s = coco_string_create(L"number expected"); break;
case 3: s = coco_string_create(L"string expected"); break;
case 4: s = coco_string_create(L"lparen expected"); break;
case 5: s = coco_string_create(L"rparen expected"); break;
case 6: s = coco_string_create(L"lbrack expected"); break;
case 7: s = coco_string_create(L"rbrack expected"); break;
case 8: s = coco_string_create(L"assign expected"); break;
case 9: s = coco_string_create(L"implic expected"); break;
case 10: s = coco_string_create(L"\"function\" expected"); break;
case 11: s = coco_string_create(L"\":\" expected"); break;
case 12: s = coco_string_create(L"\",\" expected"); break;
case 13: s = coco_string_create(L"\"string\" expected"); break;
case 14: s = coco_string_create(L"\"int\" expected"); break;
case 15: s = coco_string_create(L"\"num\" expected"); break;
case 16: s = coco_string_create(L"\"float\" expected"); break;
case 17: s = coco_string_create(L"\"bool\" expected"); break;
case 18: s = coco_string_create(L"\";\" expected"); break;
case 19: s = coco_string_create(L"\"{\" expected"); break;
case 20: s = coco_string_create(L"\"}\" expected"); break;
case 21: s = coco_string_create(L"\"loop\" expected"); break;
case 22: s = coco_string_create(L"\"map\" expected"); break;
case 23: s = coco_string_create(L"\"-\" expected"); break;
case 24: s = coco_string_create(L"\"assert\" expected"); break;
case 25: s = coco_string_create(L"\"require\" expected"); break;
case 26: s = coco_string_create(L"\"rule\" expected"); break;
case 27: s = coco_string_create(L"\"case\" expected"); break;
case 28: s = coco_string_create(L"\"variable\" expected"); break;
case 29: s = coco_string_create(L"\"warning\" expected"); break;
case 30: s = coco_string_create(L"\"message\" expected"); break;
case 31: s = coco_string_create(L"\"+\" expected"); break;
case 32: s = coco_string_create(L"\"*\" expected"); break;
case 33: s = coco_string_create(L"\"/\" expected"); break;
case 34: s = coco_string_create(L"\"<\" expected"); break;
case 35: s = coco_string_create(L"\">\" expected"); break;
case 36: s = coco_string_create(L"??? expected"); break;
case 37: s = coco_string_create(L"invalid FDecl"); break;
case 38: s = coco_string_create(L"invalid Type"); break;
case 39: s = coco_string_create(L"invalid TypeTerm"); break;
case 40: s = coco_string_create(L"invalid VDecl"); break;
case 41: s = coco_string_create(L"invalid MetaSimpExpr"); break;
case 42: s = coco_string_create(L"invalid TagMod"); break;
case 43: s = coco_string_create(L"invalid Domain"); break;
case 44: s = coco_string_create(L"invalid MetaExpr2"); break;
case 45: s = coco_string_create(L"invalid RelOp"); break;
case 46: s = coco_string_create(L"invalid AddOp"); break;
case 47: s = coco_string_create(L"invalid Factor"); break;
case 48: s = coco_string_create(L"invalid MulOp"); break;
default:
{
wchar_t format[20];
coco_swprintf(format, 20, L"error %d", n);
s = coco_string_create(format);
}
break;
}
wprintf(L"-- line %d col %d: %ls\n", line, col, s);
coco_string_delete(s);
count++;
}
void Errors::Error(int line, int col, const wchar_t *s) {
wprintf(L"-- line %d col %d: %ls\n", line, col, s);
count++;
}
void Errors::Warning(int line, int col, const wchar_t *s) {
wprintf(L"-- line %d col %d: %ls\n", line, col, s);
}
void Errors::Warning(const wchar_t *s) {
wprintf(L"%ls\n", s);
}
void Errors::Exception(const wchar_t* s) {
wprintf(L"%ls", s);
exit(1);
}

Event Timeline