Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F3996022
Parser.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Jul 8, 8:12 AM
Size
18 KB
Mime Type
text/x-c
Expires
Fri, Jul 10, 8:12 AM (1 d, 19 h)
Engine
blob
Format
Raw Data
Handle
271871
Attached To
rXR Xreate
Parser.cpp
View Options
/*----------------------------------------------------------------------
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
Log In to Comment