#if YYDEBUG
static bool bison_;
#endif
+static bool strict_;
-void Setup(cy::parser &parser) {
+void Setup(CYDriver &driver, cy::parser &parser) {
#if YYDEBUG
if (bison_)
parser.set_debug_level(1);
#endif
+ if (strict_)
+ driver.strict_ = true;
}
void Run(int socket, const char *data, size_t size, FILE *fout = NULL, bool expand = false) {
else {
CYDriver driver("");
cy::parser parser(driver);
- Setup(parser);
+ Setup(driver, parser);
driver.data_ = command.c_str();
driver.size_ = command.size();
if (parser.parse() != 0 || !driver.errors_.empty()) {
for (CYDriver::Errors::const_iterator error(driver.errors_.begin()); error != driver.errors_.end(); ++error) {
cy::position begin(error->location_.begin);
- if (begin.line != lines.size() || begin.column - 1 != lines.back().size()) {
+ if (begin.line != lines.size() || begin.column - 1 != lines.back().size() || error->warning_) {
cy::position end(error->location_.end);
if (begin.line != lines.size()) {
goto read;
}
- if (driver.source_ == NULL)
+ if (driver.program_ == NULL)
goto restart;
if (socket != -1)
else {
std::ostringstream str;
CYOutput out(str);
- driver.source_->Show(out);
+ driver.program_->Show(out);
code = str.str();
}
}
pid_t pid(_not(pid_t));
bool compile(false);
- for (;;) switch (getopt(argc, argv, "cg:p:")) {
+ for (;;) switch (getopt(argc, argv, "cg:p:s")) {
case -1:
goto getopt;
case '?':
return 1;
}
} break;
+
+ case 's':
+ strict_ = true;
+ break;
} getopt:;
const char *script;
else {
CYDriver driver(script ?: "<stdin>");
cy::parser parser(driver);
- Setup(parser);
+ Setup(driver, parser);
char *start, *end;
if (parser.parse() != 0 || !driver.errors_.empty()) {
for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i)
std::cerr << i->location_.begin << ": " << i->message_ << std::endl;
- } else if (driver.source_ != NULL)
+ } else if (driver.program_ != NULL)
if (socket != -1)
Run(socket, start, end - start, stdout);
else {
std::ostringstream str;
CYOutput out(str);
- driver.source_->Show(out);
+ driver.program_->Show(out);
std::string code(str.str());
if (compile)
std::cout << code;
return tk::StringLiteral;
}
-\n yylloc->end.lines(); yylloc->step(); N
+\r?\n yylloc->end.lines(); yylloc->step(); N
[ \t] L
<<EOF>> L yyterminate();
CYExpression *expression_;
CYFalse *false_;
CYField *field_;
+ CYFinally *finally_;
CYForInitialiser *for_;
CYForInInitialiser *forin_;
CYFunctionParameter *functionParameter_;
CYProperty *property_;
CYPropertyName *propertyName_;
CYSelectorPart *selector_;
- CYSource *source_;
CYStatement *statement_;
CYString *string_;
CYThis *this_;
%type <compound_> ExpressionNoIn_
%type <expression_> ExpressionNoInOpt
%type <statement_> ExpressionStatement
-%type <statement_> FinallyOpt
+%type <finally_> FinallyOpt
%type <comprehension_> ForComprehension
%type <statement_> ForStatement
%type <for_> ForStatementInitialiser
%type <forin_> ForInStatementInitialiser
%type <functionParameter_> FormalParameterList
%type <functionParameter_> FormalParameterList_
-%type <source_> FunctionBody
-%type <source_> FunctionDeclaration
+%type <statement_> FunctionBody
+%type <statement_> FunctionDeclaration
%type <expression_> FunctionExpression
%type <identifier_> Identifier
%type <identifier_> IdentifierOpt
%type <expression_> PrimaryExpression
%type <expression_> PrimaryExpression_
%type <expression_> PrimaryExpressionNoBF
-%type <source_> Program
+%type <statement_> Program
%type <propertyName_> PropertyName
%type <property_> PropertyNameAndValueList
%type <property_> PropertyNameAndValueList_
%type <selector_> SelectorExpressionOpt
%type <expression_> ShiftExpression
%type <expression_> ShiftExpressionNoBF
-%type <source_> SourceElement
-%type <source_> SourceElements
+%type <statement_> SourceElement
+%type <statement_> SourceElements
%type <statement_> Statement
+%type <statement_> Statement_
%type <statement_> StatementList
%type <statement_> StatementListOpt
%type <statement_> SwitchStatement
%%
-TerminatorOpt
+StrictSemi
+ : { driver.Warning(yylloc, "warning, automatic semi-colon insertion required"); }
+ ;
+
+Terminator_
: ";"
- | "\n"
- | error { yyerrok; driver.errors_.pop_back(); }
+ | "\n" StrictSemi
+ ;
+
+TerminatorOpt
+ : Terminator_
+ | error { yyerrok; driver.errors_.pop_back(); } StrictSemi
;
Terminator
- : ";"
- | "\n"
- | error { if (yychar != 0 && yychar != cy::parser::token::CloseBrace && !yylval.newline_) YYABORT; else { yyerrok; driver.errors_.pop_back(); } }
+ : Terminator_
+ | error { if (yychar != 0 && yychar != cy::parser::token::CloseBrace && !yylval.newline_) YYABORT; else { yyerrok; driver.errors_.pop_back(); } } StrictSemi
;
/*CommaOpt
/* }}} */
/* 12 Statements {{{ */
-Statement
+Statement_
: Block { $$ = $1; }
| VariableStatement { $$ = $1; }
| EmptyStatement { $$ = $1; }
| ThrowStatement { $$ = $1; }
| TryStatement { $$ = $1; }
;
+
+Statement
+ : Statement_ { $$ = $1; }
+ ;
/* }}} */
/* 12.1 Block {{{ */
Block_
;
FinallyOpt
- : "finally" Block_ { $$ = $2; }
+ : "finally" Block_ { $$ = new(driver.pool_) CYFinally($2); }
| { $$ = NULL; }
;
/* }}} */
/* }}} */
/* 14 Program {{{ */
Program
- : SourceElements { driver.source_ = $1; }
+ : SourceElements { driver.program_ = $1; }
;
SourceElements
;
SourceElement
- : Statement { $$ = $1; }
+ : Statement_ { $$ = $1; }
| FunctionDeclaration { $$ = $1; }
;
/* }}} */
: ClassDefinition { $$ = $1; }
;
-Statement
+Statement_
: ClassDefinition { $$ = $1; }
| CategoryStatement { $$ = $1; }
;
: "for" "each" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForEachIn($4, $6, $8); }
;
/* }}} */
-/* JavaScript 1.7: Let Statements {{{ *//*
+/* JavaScript 1.7: let Statements {{{ *//*
LetStatement
: "let" "(" VariableDeclarationList ")" Block_ { $$ = new(driver.pool_) CYLet($3, $5); }
;
: LetStatement
;
*//* }}} */
+/* JavaScript FTW: Function Statements {{{ */
+Statement
+ : FunctionDeclaration { driver.Warning(yylloc, "warning, FunctionDeclaration is a SourceElement, not a Statement"); } { $$ = $1; }
+ ;
+/* }}} */
%%
data_(NULL),
size_(0),
file_(NULL),
+ strict_(false),
filename_(filename),
- source_(NULL)
+ program_(NULL)
{
ScannerInit();
}
ScannerDestroy();
}
+void CYDriver::Warning(const cy::location &location, const char *message) {
+ if (!strict_)
+ return;
+
+ CYDriver::Error error;
+ error.warning_ = true;
+ error.location_ = location;
+ error.message_ = message;
+ errors_.push_back(error);
+}
+
void cy::parser::error(const cy::parser::location_type &location, const std::string &message) {
CYDriver::Error error;
+ error.warning_ = false;
error.location_ = location;
error.message_ = message;
driver.errors_.push_back(error);
} else {
std::ostringstream str;
CYOutput out(str);
- driver.source_->Show(out);
+ driver.program_->Show(out);
std::string code(str.str());
CYExecute_ execute = {pool, code.c_str()};
[client performSelectorOnMainThread:@selector(execute:) withObject:[NSValue valueWithPointer:&execute] waitUntilDone:YES];
}
void CYBlock::Output(CYOutput &out) const {
- for (CYSource *statement(statements_); statement != NULL; statement = statement->next_)
+ for (CYStatement *statement(statements_); statement != NULL; statement = statement->next_)
statement->Output(out);
}
}
void CYCatch::Output(CYOutput &out) const {
- out << "catch(" << *name_ << ')';
- code_->Output(out, true);
+ out << "catch(" << *name_ << "){";
+ if (code_ != NULL)
+ code_->Show(out);
+ out << "}";
}
void CYCategory::Output(CYOutput &out) const {
void CYEmpty::Output(CYOutput &out, bool block) const {
if (next_ != NULL)
- CYSource::Output(out, block);
+ CYStatement::Output(out, block);
else
out << "{}";
}
// XXX: implement!
}
+void CYFinally::Output(CYOutput &out) const {
+ out << "finally{";
+ if (code_ != NULL)
+ code_->Show(out);
+ out << "}";
+}
+
void CYFor::Output(CYOutput &out) const {
out << "for(";
if (initialiser_ != NULL)
out << ')';
}
-void CYSource::Show(CYOutput &out) const {
- for (const CYSource *next(this); next != NULL; next = next->next_)
+void CYStatement::Show(CYOutput &out) const {
+ for (const CYStatement *next(this); next != NULL; next = next->next_)
next->Output_(out);
}
-void CYSource::Output(CYOutput &out, bool block) const {
+void CYStatement::Output(CYOutput &out, bool block) const {
if (!block && !IsBlock())
Output(out);
else {
}
}
-void CYSource::Output_(CYOutput &out) const {
- Output(out);
-}
-
void CYStatement::Output_(CYOutput &out) const {
for (CYLabel *label(labels_); label != NULL; label = label->next_)
out << *label->name_ << ':';
}
void CYTry::Output(CYOutput &out) const {
- out << "try";
- try_->Output(out, true);
+ out << "try{";
+ if (code_ != NULL)
+ code_->Show(out);
+ out << "}";
if (catch_ != NULL)
catch_->Output(out);
- if (finally_ != NULL) {
- out << "finally";
- finally_->Output(out, true);
- }
+ if (finally_ != NULL)
+ finally_->Output(out);
}
void CYVar::Output(CYOutput &out) const {
}
};
-struct CYSource :
- CYNext<CYSource>
-{
- virtual bool IsBlock() const {
- return next_ != NULL;
- }
-
- virtual void Show(CYOutput &out) const;
- virtual void Output(CYOutput &out) const = 0;
- virtual void Output(CYOutput &out, bool block) const;
- virtual void Output_(CYOutput &out) const;
-};
-
struct CYPropertyName {
virtual void PropertyName(CYOutput &out) const = 0;
};
};
struct CYStatement :
- CYSource
+ CYNext<CYStatement>
{
CYLabel *labels_;
labels_ = new CYLabel(identifier, labels_);
}
+ virtual bool IsBlock() const {
+ return next_ != NULL;
+ }
+
+ virtual void Show(CYOutput &out) const;
+ virtual void Output(CYOutput &out) const = 0;
+ virtual void Output(CYOutput &out, bool block) const;
virtual void Output_(CYOutput &out) const;
};
size_t size_;
FILE *file_;
+ bool strict_;
+
enum Condition {
RegExStart,
RegExRest
std::string filename_;
struct Error {
+ bool warning_;
cy::location location_;
std::string message_;
};
typedef std::vector<Error> Errors;
- CYSource *source_;
+ CYStatement *program_;
Errors errors_;
private:
~CYDriver();
void SetCondition(Condition condition);
+
+ void Warning(const cy::location &location, const char *message);
};
enum CYFlags {
bool instance_;
CYExpression *type_;
CYMessageParameter *parameter_;
- CYSource *body_;
+ CYStatement *body_;
- CYMessage(bool instance, CYExpression *type, CYMessageParameter *parameter, CYSource *body) :
+ CYMessage(bool instance, CYExpression *type, CYMessageParameter *parameter, CYStatement *body) :
instance_(instance),
type_(type),
parameter_(parameter),
{
CYIdentifier *name_;
CYFunctionParameter *parameters_;
- CYSource *body_;
+ CYStatement *body_;
- CYLambda(CYIdentifier *name, CYFunctionParameter *parameters, CYSource *body) :
+ CYLambda(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
name_(name),
parameters_(parameters),
body_(body)
struct CYFunction :
CYLambda,
- CYSource
+ CYStatement
{
- CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYSource *body) :
+ CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
CYLambda(name, parameters, body)
{
}
virtual void Output(CYOutput &out, bool block) const;
};
+struct CYFinally {
+ CYStatement *code_;
+
+ CYFinally(CYStatement *code) :
+ code_(code)
+ {
+ }
+
+ virtual void Output(CYOutput &out) const;
+};
+
struct CYTry :
CYStatement
{
- CYStatement *try_;
+ CYStatement *code_;
CYCatch *catch_;
- CYStatement *finally_;
+ CYFinally *finally_;
- CYTry(CYStatement *_try, CYCatch *_catch, CYStatement *finally) :
- try_(_try),
+ CYTry(CYStatement *code, CYCatch *_catch, CYFinally *finally) :
+ code_(code),
catch_(_catch),
finally_(finally)
{