Permalink
Browse files

Cleanup various deficiencies

Summary:
This cleans up a lot of junk in the code like stray virtuals, missing refs and consts where applicable, better exceptions, and proper string literal rendering.

Test Plan:
Compiles

Reviewed By: epriestley
  • Loading branch information...
1 parent c235a01 commit 6ea3afb0a099952cae6532e1a1824c76f326cb58 @laverdet laverdet committed Nov 19, 2010
Showing with 121 additions and 53 deletions.
  1. +1 −1 Makefile
  2. +62 −14 node.cpp
  3. +34 −16 node.hpp
  4. +7 −14 parser.cpp
  5. +4 −2 parser.hpp
  6. +4 −1 parser.ll
  7. +9 −5 parser.yy
View
@@ -70,4 +70,4 @@ clean:
parser.lex.cpp parser.yacc.cpp parser.yacc.hpp parser.yacc.output \
libfbjs.so libfbjs.a \
dmg_fp_dtoa.o dmg_fp_g_fmt.o \
- parser.lex.o parser.yacc.o parser.o node.o
+ parser.lex.o parser.yacc.o parser.o node.o walker.o
View
@@ -313,7 +313,7 @@ bool NodeNumericLiteral::operator== (const Node &that) const {
//
// NodeStringLiteral: "Hello."
-NodeStringLiteral::NodeStringLiteral(string value, bool quoted, const unsigned int lineno /* = 0 */) : NodeExpression(lineno), value(value), quoted(quoted) {}
+NodeStringLiteral::NodeStringLiteral(const string &value, bool quoted, const unsigned int lineno /* = 0 */) : NodeExpression(lineno), value(value), quoted(quoted) {}
Node* NodeStringLiteral::clone(Node* node) const {
return new NodeStringLiteral(this->value, this->quoted);
@@ -323,7 +323,63 @@ rope_t NodeStringLiteral::render(render_guts_t* guts, int indentation) const {
if (this->quoted) {
return rope_t(this->value.c_str());
} else {
+ const char *val = this->value.c_str();
+ size_t len = 0;
+ for (const char* ii = val; *ii; ++ii) {
+ if (*ii < 32) {
+ switch (*ii) {
+ case '\'': case '\\': case '\b': case '\f': case '\n': case '\r': case '\t':
+ len += 2;
+ break;
+ default:
+ len += 4;
+ }
+ } else {
+ ++len;
+ }
+ }
+ if (len == this->value.size()) {
return rope_t("\"") + this->value.c_str() + "\"";
+ } else {
+ char *new_str = new char[len + 1];
+ char *ii = new_str;
+ new_str[len] = 0;
+ for (; *val; ++val) {
+ if (*val == '\'') {
+ sprintf(ii, "\\'");
+ ii += 2;
+ } else if (*val == '\\') {
+ sprintf(ii, "\\'");
+ ii += 2;
+ } else if (*val == '\b') {
+ sprintf(ii, "\\b");
+ ii += 2;
+ } else if (*val == '\f') {
+ sprintf(ii, "\\f");
+ ii += 2;
+ } else if (*val == '\n') {
+ sprintf(ii, "\\n");
+ ii += 2;
+ } else if (*val == '\r') {
+ sprintf(ii, "\\r");
+ ii += 2;
+ } else if (*val == '\t') {
+ sprintf(ii, "\\t");
+ ii += 2;
+ } else if (*val < 32) {
+ sprintf(ii, "\\x%02x", *val);
+ ii += 4;
+ } else {
+ *ii = *val;
+ ++ii;
+ }
+ }
+ rope_t ret("\"");
+ ret += new_str;
+ ret += "\"";
+ delete[] new_str;
+ return ret;
+ }
}
}
@@ -334,7 +390,7 @@ bool NodeStringLiteral::operator== (const Node &that) const {
//
// NodeRegexLiteral: /foo|bar/
-NodeRegexLiteral::NodeRegexLiteral(string value, string flags, const unsigned int lineno /* = 0 */) : NodeExpression(lineno), value(value), flags(flags) {}
+NodeRegexLiteral::NodeRegexLiteral(const string &value, const string &flags, const unsigned int lineno /* = 0 */) : NodeExpression(lineno), value(value), flags(flags) {}
Node* NodeRegexLiteral::clone(Node* node) const {
return new NodeRegexLiteral(this->value, this->flags);
@@ -551,7 +607,7 @@ rope_t NodeConditionalExpression::render(render_guts_t* guts, int indentation) c
}
//
-// NodeParenthetical: an expression in ()'s. this is actually implicit in the AST, but we also make it an explicit
+// NodeParenthetical: an expression in ()'s. This is actually implicit in the AST, but we also make it an explicit
// node. Otherwise, the renderer would have to be aware of operator precedence which would be cumbersome.
NodeParenthetical::NodeParenthetical(const unsigned int lineno /* = 0 */) : NodeExpression(lineno) {}
Node* NodeParenthetical::clone(Node* node) const {
@@ -640,10 +696,6 @@ rope_t NodeAssignment::render(render_guts_t* guts, int indentation) const {
return ret;
}
-const node_assignment_t NodeAssignment::operatorType() const {
- return this->op;
-}
-
bool NodeAssignment::operator== (const Node &that) const {
return Node::operator==(that) && this->op == static_cast<const NodeAssignment*>(&that)->op;
}
@@ -698,10 +750,6 @@ rope_t NodeUnary::render(render_guts_t* guts, int indentation) const {
return ret;
}
-const node_unary_t NodeUnary::operatorType() const {
- return this->op;
-}
-
bool NodeUnary::operator== (const Node &that) const {
return Node::operator==(that) && this->op == static_cast<const NodeUnary*>(&that)->op;
}
@@ -733,7 +781,7 @@ bool NodePostfix::operator== (const Node &that) const {
//
// NodeIdentifier
-NodeIdentifier::NodeIdentifier(string name, const unsigned int lineno /* = 0 */) : NodeExpression(lineno), _name(name) {}
+NodeIdentifier::NodeIdentifier(const string &name, const unsigned int lineno /* = 0 */) : NodeExpression(lineno), _name(name) {}
Node* NodeIdentifier::clone(Node* node) const {
return Node::clone(new NodeIdentifier(this->_name));
@@ -743,15 +791,15 @@ rope_t NodeIdentifier::render(render_guts_t* guts, int indentation) const {
return rope_t(this->_name.c_str());
}
-string NodeIdentifier::name() const {
+const string& NodeIdentifier::name() const {
return this->_name;
}
bool NodeIdentifier::isValidlVal() const {
return true;
}
-void NodeIdentifier::rename(const std::string &str) {
+void NodeIdentifier::rename(const string &str) {
this->_name = str;
}
View
@@ -20,9 +20,11 @@
#pragma once
#include <stdio.h>
+#include <stdlib.h>
#include <stdexcept>
#include <sstream>
#include <list>
+#include <memory>
#include <ext/rope>
#define NODE_WALKER_ACCEPT_DECL virtual void accept(class NodeWalker& walker)
@@ -132,11 +134,16 @@ namespace fbjs {
// NodeStringLiteral
class NodeStringLiteral: public NodeExpression {
protected:
- std::string value;
+ const std::string value;
bool quoted;
public:
NODE_WALKER_ACCEPT_DECL;
- NodeStringLiteral(std::string value, bool quoted, const unsigned int lineno = 0);
+ NodeStringLiteral(const std::string& value, bool quoted, const unsigned int lineno = 0);
+ std::string unquoted_value() const {
+ if (!quoted) return value;
+ return value.substr(1, value.size() - 2);
+ }
+
virtual Node* clone(Node* node = NULL) const;
virtual rope_t render(render_guts_t* guts, int indentation) const;
virtual bool operator== (const Node&) const;
@@ -146,11 +153,11 @@ namespace fbjs {
// NodeRegexLiteral
class NodeRegexLiteral: public NodeExpression {
protected:
- std::string value;
- std::string flags;
+ const std::string value;
+ const std::string flags;
public:
NODE_WALKER_ACCEPT_DECL;
- NodeRegexLiteral(std::string value, std::string flags, const unsigned int lineno = 0);
+ NodeRegexLiteral(const std::string& value, const std::string& flags, const unsigned int lineno = 0);
virtual Node* clone(Node* node = NULL) const;
virtual rope_t render(render_guts_t* guts, int indentation) const;
virtual bool operator== (const Node&) const;
@@ -221,6 +228,7 @@ namespace fbjs {
NodeOperator(node_operator_t op, const unsigned int lineno = 0);
virtual Node* clone(Node* node = NULL) const;
virtual rope_t render(render_guts_t* guts, int indentation) const;
+ const node_operator_t operatorType() const { return op; };
virtual bool operator== (const Node&) const;
};
@@ -262,7 +270,7 @@ namespace fbjs {
NodeAssignment(node_assignment_t op, const unsigned int lineno = 0);
virtual Node* clone(Node* node = NULL) const;
virtual rope_t render(render_guts_t* guts, int indentation) const;
- const node_assignment_t operatorType() const;
+ const node_assignment_t operatorType() const { return op; };
virtual bool operator== (const Node&) const;
};
@@ -282,7 +290,7 @@ namespace fbjs {
NodeUnary(node_unary_t op, const unsigned int lineno = 0);
virtual Node* clone(Node* node = NULL) const;
virtual rope_t render(render_guts_t* guts, int indentation) const;
- const node_unary_t operatorType() const;
+ const node_unary_t operatorType() const { return op; };
virtual bool operator== (const Node&) const;
};
@@ -309,12 +317,12 @@ namespace fbjs {
std::string _name;
public:
NODE_WALKER_ACCEPT_DECL;
- NodeIdentifier(std::string name, const unsigned int lineno = 0);
+ NodeIdentifier(const std::string& name, const unsigned int lineno = 0);
virtual Node* clone(Node* node = NULL) const;
virtual rope_t render(render_guts_t* guts, int indentation) const;
- virtual std::string name() const;
+ const std::string& name() const;
virtual bool isValidlVal() const;
- virtual void rename(const std::string &str);
+ void rename(const std::string &str);
virtual bool operator== (const Node&) const;
};
@@ -575,11 +583,21 @@ namespace fbjs {
//
// Parser exception
- class ParseException: public std::exception {
- public:
- char error[128];
- ParseException(const std::string msg);
- const char* what() const throw();
+ class ParseException: public std::runtime_error {
+ private:
+ mutable std::string wut;
+ int lineno;
+ public:
+ ParseException(const std::string& what_arg, const int lineno) : std::runtime_error(what_arg), lineno(lineno) {}
+ ~ParseException() throw() {}
+ const char* what() const throw() {
+ if (wut.empty()) {
+ wut =
+ "SyntaxError on line " +
+ static_cast<std::stringstream&>(std::stringstream() << lineno << ": ").str() +
+ std::runtime_error::what();
+ }
+ return wut.c_str();
+ }
};
-
}
View
@@ -26,20 +26,14 @@ extern int yydebug;
using namespace std;
using namespace fbjs;
-ParseException::ParseException(const string msg) {
- memcpy(error, msg.c_str(), msg.length() > 127 ? 128 : msg.length() + 1);
- error[127] = 0;
-}
-
-const char* ParseException::what() const throw() {
- return error;
-}
-
void* fbjs_init_parser(fbjs_parse_extra* extra) {
// Initialize the scanner.
void* scanner;
yylex_init_extra(extra, &scanner);
+ extra->error = NULL;
+ extra->error_line = 0;
+ extra->terminated = false;
extra->lineno = 1;
extra->last_tok = 0;
extra->last_paren_tok = 0;
@@ -57,11 +51,10 @@ void* fbjs_init_parser(fbjs_parse_extra* extra) {
void fbjs_cleanup_parser(fbjs_parse_extra* extra, void* scanner) {
yylex_destroy(scanner);
- if (!extra->errors.empty()) {
- list<string>::iterator ii;
- for (ii = extra->errors.begin(); ii != extra->errors.end(); ++ii) {
- throw ParseException(*ii);
- }
+ if (extra->error != NULL) {
+ string error(extra->error);
+ free(extra->error);
+ throw ParseException(error, extra->error_line);
}
}
View
@@ -38,15 +38,16 @@
#include "libfbjs/parser.yy.h"
#endif
struct fbjs_parse_extra {
- std::list<std::string> errors;
+ char* error;
+ int error_line;
+ bool terminated;
std::stack<int> paren_stack;
std::stack<int> curly_stack;
int virtual_semicolon_last_state;
int last_tok;
int last_paren_tok;
int last_curly_tok;
int lineno;
- const char* strstream;
};
// Why the hell doesn't flex provide a header file?
@@ -55,6 +56,7 @@ int yylex(YYSTYPE* param, YYLTYPE* yylloc, void* scanner);
int yylex_init_extra(YY_EXTRA_TYPE user_defined, void** scanner);
int yylex_destroy(void* scanner);
YY_EXTRA_TYPE yyget_extra(void* scanner);
+YYLTYPE* yyget_lloc(void* yyscanner);
void yyset_extra(YY_EXTRA_TYPE arbitrary_data, void* scanner);
void yyset_debug(int bdebug, void* yyscanner);
void yyrestart(FILE* input_file, void* yyscanner);
View
@@ -37,6 +37,8 @@
using namespace fbjs;
+#define YY_USER_ACTION if (yyextra->terminated) return 0;
+
#ifdef DEBUG_FLEX
#define FBJSBEGIN(a) if(a!=YY_START) { \
switch(a) { \
@@ -68,7 +70,8 @@ using namespace fbjs;
#define parsertok(a) parsertok_(yyg, a);
-int parsertok_(void*, int);
+int parsertok_(void*, int, bool = false);
+void terminate(void* yyscanner, const char* str);
%}
%option noyywrap
View
@@ -43,16 +43,20 @@
#define yylineno (unsigned int)(yylloc.first_line)
#define parsererror(str) yyerror(&yylloc, yyscanner, NULL, str)
- void parser_note_error(void* yyscanner, const char* str) {
+ void terminate(void* yyscanner, const char* str) {
fbjs_parse_extra* extra = yyget_extra(yyscanner);
- extra->errors.push_back(str);
+ if (!extra->terminated) {
+ YYLTYPE* loc = yyget_lloc(yyscanner);
+ extra->error = strdup(str);
+ extra->error_line = loc->first_line;
+ extra->terminated = true;
+ }
}
void yyerror(YYLTYPE* yyloc, void* yyscanner, void* node, const char* str) {
- char loc[1024];
- sprintf(loc, "Error on line %d: %s", yyloc->first_line, str);
- parser_note_error(yyscanner, loc);
+ terminate(yyscanner, str);
}
+
%}
%locations

0 comments on commit 6ea3afb

Please sign in to comment.