Commit f76234f1 authored by Erik Verbruggen's avatar Erik Verbruggen

Removed left-overs from initial development.

parent 3787aa7a
#include <glslengine.h>
#include <glslparser.h>
#include <glsllexer.h>
#include <glslastdump.h>
#include <glslsemantic.h>
#include <glslsymbols.h>
#include <glsltypes.h>
#include <QtCore/QTextStream>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cassert>
#include <cstdio>
using namespace GLSL;
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
namespace {
QTextStream qout(stdout, QIODevice::WriteOnly);
}
int main(int argc, char *argv[])
{
int variant = 0;
while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') {
if (!strcmp(argv[1], "--version=1.20")) {
variant |= Lexer::Variant_GLSL_120;
} else if (!strcmp(argv[1], "--version=1.50")) {
variant |= Lexer::Variant_GLSL_150;
} else if (!strcmp(argv[1], "--version=4.00")) {
variant |= Lexer::Variant_GLSL_400;
} else if (!strcmp(argv[1], "--version=es")) {
variant |= Lexer::Variant_GLSL_ES_100;
} else if (!strcmp(argv[1], "--shader=vertex")) {
variant |= Lexer::Variant_VertexShader;
} else if (!strcmp(argv[1], "--shader=fragment")) {
variant |= Lexer::Variant_FragmentShader;
} else {
std::cerr << "glsl: unknown option: " << argv[1] << std::endl;
return EXIT_FAILURE;
}
++argv;
--argc;
}
if (argc != 2) {
std::cerr << "glsl: no input file" << std::endl;
return EXIT_FAILURE;
}
std::ifstream fin(argv[1]);
if (! fin) {
std::cerr << "glsl: No such file or directory" << std::endl;
return EXIT_FAILURE;
}
fin.seekg(0, std::ios::end);
size_t size = fin.tellg();
fin.seekg(0, std::ios::beg);
char *source = new char[size];
fin.read(source, size);
fin.close();
if (!variant)
variant = Lexer::Variant_Mask & ~Lexer::Variant_Reserved;
else if ((variant & (Lexer::Variant_VertexShader | Lexer::Variant_FragmentShader)) == 0)
variant |= Lexer::Variant_VertexShader | Lexer::Variant_FragmentShader;
Engine engine;
Parser parser(&engine, source, size, variant);
TranslationUnitAST *ast = parser.parse();
std::cout << argv[1] << (ast ? " OK " : " KO ") << std::endl;
ASTDump dump(qout);
dump(ast);
Semantic sem;
Scope *globalScope = engine.newNamespace();
sem.translationUnit(ast, globalScope, &engine);
delete source;
delete ast;
return EXIT_SUCCESS;
}
TEMPLATE = app
CONFIG -= app_bundle
CONFIG += console
TARGET = glsl
DEPENDPATH += .
INCLUDEPATH += . ..
QT = core
# Input
SOURCES += main.cpp
include(../glsl-lib.pri)
/*
Copyright 2007 Roberto Raggi <roberto@kdevelop.org>
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string>
#include <iostream>
#include <map>
#include <list>
#include <vector>
#include <set>
#include <cstdlib>
#include <cctype>
#include <functional>
#include <algorithm>
class State;
class DottedItem;
typedef std::list<std::string> RuleList;
typedef RuleList::iterator RulePtr;
typedef std::list<State> StateList;
typedef StateList::iterator StatePtr;
typedef std::string::iterator Dot;
typedef std::vector<DottedItem>::iterator DottedItemPtr;
class DottedItem {
public:
RulePtr rule;
Dot dot;
DottedItem() {}
DottedItem(RulePtr rule, Dot dot):
rule(rule), dot(dot) {}
bool operator == (const DottedItem &other) const {
return rule == other.rule && dot == other.dot;
}
bool operator != (const DottedItem &other) const {
return ! operator == (other);
}
bool terminal() const {
return dot == rule->end();
}
DottedItem next() const {
DottedItem item;
item.rule = rule;
item.dot = dot;
++item.dot;
return item;
}
};
struct State {
public:
State() {}
template <typename _ForwardIterator>
State(_ForwardIterator first, _ForwardIterator last) {
_items.insert(_items.end(), first, last);
}
static State &intern(const State &state) {
StatePtr ptr = std::find(first_state(), last_state(), state);
if (ptr == last_state())
ptr = states().insert(last_state(), state);
return *ptr;
}
State &next(char ch) {
std::vector<DottedItem> n;
for (DottedItemPtr it = first_item(); it != last_item(); ++it) {
if (! it->terminal() && *it->dot == ch)
n.push_back(it->next());
}
return intern(State(n.begin(), n.end()));
}
std::set<char> firsts() {
std::set<char> s;
for (DottedItemPtr it = first_item(); it != last_item(); ++it) {
if (! it->terminal())
s.insert(*it->dot);
}
return s;
}
size_t item_count() const { return _items.size(); }
DottedItemPtr first_item() { return _items.begin(); }
DottedItemPtr last_item() { return _items.end(); }
static StatePtr first_state() { return states().begin(); }
static StatePtr last_state() { return states().end(); }
bool operator == (const State &other) const { return _items == other._items; }
bool operator != (const State &other) const { return _items != other._items; }
template <typename _Iterator>
static State &start(_Iterator first, _Iterator last) {
std::vector<DottedItem> items;
for (; first != last; ++first)
items.push_back(DottedItem(first, first->begin()));
return intern(State(items.begin(), items.end()));
}
static void reset() {
states().clear();
}
private:
static StateList &states() {
static StateList _states;
return _states;
}
private:
std::vector<DottedItem> _items;
};
static bool option_no_enums = false;
static bool option_toupper = false;
static std::string option_namespace_name;
static std::string option_class_name;
static std::string option_token_prefix = "Token_";
static std::string option_variant_prefix = "Variant_";
static std::string option_char_type = "char";
static std::string option_unicode_function = "";
static std::map<std::string, std::string> variants;
std::string token_id(const std::string &id)
{
std::string token = option_token_prefix;
if (! option_toupper)
token += id;
else {
for (size_t i = 0; i < id.size(); ++i)
token += toupper(id[i]);
}
return token;
}
std::string variant_id(const std::string &id)
{
if (variants.find(id) == variants.end())
return "";
std::string variant = variants[id];
size_t posn = 0;
bool sep = true;
std::string result;
while (posn < variant.size()) {
char ch = variant[posn++];
if (isalnum(ch) || ch == '_') {
if (sep) {
result += " | " + option_variant_prefix;
sep = false;
}
result += ch;
} else if (!sep) {
sep = true;
}
}
return result;
}
bool starts_with(const std::string &line, const std::string &text) {
if (text.length() < line.length()) {
return std::equal(line.begin(), line.begin() + text.size(), text.begin());
}
return false;
}
void doit(State &state)
{
static int depth = 0;
++depth;
std::string indent(depth * 2, ' ');
std::set<char> firsts = state.firsts();
for (std::set<char>::iterator it = firsts.begin(); it != firsts.end(); ++it) {
std::string _else = it == firsts.begin() ? "" : "else ";
std::cout << indent << _else << "if (s[" << (depth - 1) << "]" << option_unicode_function << " == '" << *it << "') {" << std::endl;
State &next_state = state.next(*it);
bool found = false;
for (DottedItemPtr item = next_state.first_item(); item != next_state.last_item(); ++item) {
if (item->terminal()) {
if (found) {
std::cerr << "*** Error. Too many accepting states" << std::endl;
exit(EXIT_FAILURE);
}
found = true;
std::cout << indent << " return " << option_namespace_name << token_id(*item->rule) << variant_id(*item->rule) << ";" << std::endl;
}
}
if (! found)
doit(next_state);
std::cout << indent << "}" << std::endl;
}
--depth;
}
void gen_classify_n(State &start_state, int N)
{
std::cout << "static inline int classify" << N << "(const " << option_char_type << " *s) {" << std::endl;
doit(start_state);
std::cout << " return " << option_namespace_name << token_id("identifier") << ";" << std::endl
<< "}" << std::endl << std::endl;
}
void gen_classify(const std::multimap<size_t, std::string> &keywords)
{
std::cout << "int " << option_class_name << "classify(const " << option_char_type << " *s, int n) {" << std::endl
<< " switch (n) {" << std::endl;
std::multimap<size_t, std::string>::const_iterator it = keywords.begin();
while (it != keywords.end()) {
size_t size = it->first;
std::cout << " case " << size << ": return classify" << size << "(s);" << std::endl;
do { ++it; } while (it != keywords.end() && it->first == size);
}
std::cout << " default: return " << option_namespace_name << token_id("identifier") << ";" << std::endl
<< " } // switch" << std::endl
<< "}" << std::endl << std::endl;
}
void gen_keyword_list(const std::multimap<size_t, std::string> &keywords)
{
std::cout << "QStringList " << option_class_name << "keywords(int variant) {" << std::endl
<< " QStringList list;" << std::endl;
std::multimap<size_t, std::string>::const_iterator it = keywords.begin();
for (; it != keywords.end(); ++it) {
std::string varid = variant_id(it->second);
if (varid.empty()) {
std::cout << " list += QLatin1String(\"" << it->second << "\");" << std::endl;
} else {
varid = varid.substr(3);
std::cout << " if (variant & (" << varid << "))" << std::endl;
std::cout << " list += QLatin1String(\"" << it->second << "\");" << std::endl;
}
}
std::cout << " return list;" << std::endl
<< "}" << std::endl << std::endl;
}
void gen_enums(const std::multimap<size_t, std::string> &keywords)
{
std::cout << "enum {" << std::endl;
std::multimap<size_t, std::string>::const_iterator it = keywords.begin();
for (; it != keywords.end(); ++it) {
std::cout << " " << token_id(it->second) << variant_id(it->second) << "," << std::endl;
}
std::cout << " " << token_id("identifier") << std::endl
<< "};" << std::endl << std::endl;
}
inline bool not_whitespace_p(char ch) {
return ! std::isspace(ch);
}
int main(int argc, char *argv[]) {
const std::string ns = "--namespace=";
for (int i = 0; i < argc; ++i) {
const std::string arg(argv[i]);
if (arg == "--no-enums")
option_no_enums = true;
else if (starts_with(arg, ns)) {
option_namespace_name.assign(arg.begin() + ns.size(), arg.end());
option_namespace_name += "::";
}
}
std::multimap<size_t, std::string> keywords;
std::string textline;
bool readKeywords = false;
const std::string opt_no_enums = "%no-enums";
const std::string opt_toupper = "%toupper";
const std::string opt_ns = "%namespace=";
const std::string opt_class = "%lexer-class=";
const std::string opt_tok_prefix = "%token-prefix=";
const std::string opt_var_prefix = "%variant-prefix=";
const std::string opt_char_type = "%char-type=";
const std::string opt_unicode_function = "%unicode-function=";
while (getline(std::cin, textline)) {
// remove trailing spaces
textline.assign(textline.begin(), std::find_if(textline.rbegin(), textline.rend(), not_whitespace_p).base());
if (! readKeywords) {
if (textline.size() >= 2 && textline[0] == '%') {
if (textline[1] == '%') {
readKeywords = true;
} else if (textline == opt_no_enums) {
option_no_enums = true;
} else if (textline == opt_toupper) {
option_toupper = true;
} else if (starts_with(textline, opt_tok_prefix)) {
option_token_prefix.assign(textline.begin() + opt_tok_prefix.size(), textline.end());
} else if (starts_with(textline, opt_var_prefix)) {
option_variant_prefix.assign(textline.begin() + opt_var_prefix.size(), textline.end());
} else if (starts_with(textline, opt_char_type)) {
option_char_type.assign(textline.begin() + opt_char_type.size(), textline.end());
} else if (starts_with(textline, opt_unicode_function)) {
option_unicode_function.assign(textline.begin() + opt_unicode_function.size(), textline.end());
} else if (starts_with(textline, opt_ns)) {
option_namespace_name.assign(textline.begin() + opt_ns.size(), textline.end());
option_namespace_name += "::";
} else if (starts_with(textline, opt_class)) {
option_class_name.assign(textline.begin() + opt_class.size(), textline.end());
option_class_name += "::";
}
continue;
}
std::cout << textline << std::endl;
} else {
if (textline.empty())
continue;
std::string::iterator start = textline.begin();
while (start != textline.end() && std::isspace(*start))
++start;
std::string::iterator stop = start;
while (stop != textline.end() && (std::isalnum(*stop) || *stop == '_'))
++stop;
if (start != stop) {
std::string keyword(start, stop);
if (keyword == "identifier") {
std::cerr << "*** Error. `identifier' is reserved" << std::endl;
exit(EXIT_FAILURE);
}
keywords.insert(std::make_pair(keyword.size(), keyword));
start = stop;
while (start != textline.end() && std::isspace(*start))
++start;
if (start != textline.end() && *start == '%') {
++start;
std::string::iterator stop = start;
while (stop != textline.end() && (std::isalnum(*stop) || *stop == '_'))
++stop;
std::string directive(start, stop);
if (directive == "variant") {
while (stop != textline.end() && std::isspace(*stop))
++stop;
std::string variant(stop, textline.end());
variants.insert(std::make_pair(keyword, variant));
}
}
}
}
}
if (option_class_name.empty())
option_class_name = option_namespace_name;
if (! option_no_enums)
gen_enums(keywords);
std::multimap<size_t, std::string>::iterator it = keywords.begin();
while (it != keywords.end()) {
size_t size = it->first;
RuleList rules;
do { rules.push_back(it->second); ++it; }
while (it != keywords.end() && it->first == size);
gen_classify_n(State::start(rules.begin(), rules.end()), size);
State::reset();
}
gen_classify(keywords);
gen_keyword_list(keywords);
}
#!/usr/bin/python
import sys
try:
file = open(sys.argv[1], "r")
klass = sys.argv[2]
except:
print("Usage: mkvisitor.py grammar.txt classname")
exit()
lines = file.readlines()
ruleno = 0
print("""
#include "glslast.h"
namespace GLSL {
class %s
{
typedef void (%s::*dispatch_func)(AST *);
static dispatch_func dispatch[];
public:
void accept(AST *ast)
{
if (! ast)
return;
else if (Operator *op = ast->asOperator())
(this->*dispatch[op->ruleno])(ast);
}
template <typename It>
void accept(It first, It last)
{
for (; first != last; ++first)
accept(*first);
}
private:""" % (klass, klass))
for line in lines:
sections = line.split()
if len(sections) and sections[1] == "::=":
ruleno = ruleno + 1
print(" void on_%s_%d(AST *);" % (sections[0], ruleno))
print("};")
print("} // end of namespace GLSL")
print("""
#include <iostream>
using namespace GLSL;
namespace {
bool debug = false;
}
""")
print("%s::dispatch_func %s::dispatch[] = {" % (klass, klass))
ruleno = 0
for line in lines:
sections = line.split()
if len(sections) and sections[1] == "::=":
ruleno = ruleno + 1
print(" &%s::on_%s_%d," % (klass, sections[0], ruleno))
print("0, };\n")
ruleno = 0
for line in lines:
sections = line.split()
if len(sections) and sections[1] == "::=":
ruleno = ruleno + 1
print("""// %svoid %s::on_%s_%d(AST *ast)
{
if (debug)
std::cout << "%s" << std::endl;
Operator *op = ast->asOperator();
accept(op->begin(), op->end());
}
""" % (line, klass, sections[0], ruleno, line[:-3]))
Markdown is supported
0%