我想在OpenGL着色语言(GLSL)代码中解析自定义标记,这是一种非常类似C的语言。一般用例如下所示:
#version 150
@bind ProjectionMatrix
uniform mat4 projMatrix;
@bind ViewMatrix
uniform mat4 viewMatrix;
in vec4 position;
in vec3 color;
out vec3 Color;
void main()
{
Color = color;
gl_Position = projMatrix * viewMatrix * position;
}
我想这样做是用@bind
标签'注释'变量,这样我就可以将它们连接到我实际应用程序中的变量(即我可以将值从我的app传递给glsl)。所以我会解析glsl代码,每当我找到@bind
标记时,我就会解析ProjectionMatrix
(或ViewMatrix
)作为变量从c ++传递给glsl,然后解析projMatrix
(或viewMatrix
)作为应该存储从c ++发送的值的变量。
我想知道的是 - 为此使用助推波或精神会更好吗?那些是我正在寻求解决这个问题的两个库。
我有增强波词法分析器工作,因为它迭代所有令牌。所以我必须编写代码来解析返回的标记并寻找模式。
我不确定我是如何用精神做到这一点的,但它似乎是一个更强大的词法分析器/解析器。
有人有任何建议吗?
答案 0 :(得分:3)
我仍然不确定你希望我们如何知道glsl是什么。所以我真的只能对实际的输入格式进行广泛的猜测。
让我说我用我认为合适的最简单的方式解释这个(没有荒谬的无用):
annot = "@bind" >> ident >> eol;
declaration =
omit [ +(ident >> !char_(';')) ] // omit the type, TODO
>> ident >> ';' >> eol;
现在,我们只需要一种简单的方法来忽略整行,直到我们找到一个包含注释的方法:
ignore = !annot >> *(char_ - eol) >> eol;
如果您想忽略未附加声明的@bind
行,您可能需要使用!combi
而不是!annot
。
这只是你的首发。而且,并非所有可忽略的行的“隐含”定义都可能导致大量的回溯。所以不要指望一流的表现。
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted.hpp>
#include <map>
namespace qi = boost::spirit::qi;
typedef std::map<std::string, std::string> Map;
template <typename It>
struct grammar : qi::grammar<It, Map(), qi::blank_type>
{
grammar() : grammar::base_type(start)
{
using namespace qi;
ident = lexeme [ alpha >> *alnum ];
annot = "@bind" >> ident >> eol;
declaration =
omit [ +(ident >> !char_(';')) ] // omit the type, TODO
>> ident >> ';' >> eol;
ignore = !annot >> *(char_ - eol) >> eol;
combi = annot >> declaration;
start = *ignore >> combi % *ignore;
BOOST_SPIRIT_DEBUG_NODE(start);
BOOST_SPIRIT_DEBUG_NODE(combi);
BOOST_SPIRIT_DEBUG_NODE(ignore);
BOOST_SPIRIT_DEBUG_NODE(declaration);
BOOST_SPIRIT_DEBUG_NODE(annot);
BOOST_SPIRIT_DEBUG_NODE(ident);
}
private:
qi::rule<It, qi::blank_type> ignore;
qi::rule<It, std::string(), qi::blank_type> ident, declaration, annot;
qi::rule<It, std::pair<std::string, std::string>(), qi::blank_type> combi;
qi::rule<It, Map(), qi::blank_type> start;
};
template <typename It>
void test(It f, It l)
{
grammar<It> p;
Map mappings;
bool ok = qi::phrase_parse(f, l, p, qi::blank, mappings);
if (ok)
{
for (auto it = mappings.begin(); it!=mappings.end(); ++it)
std::cout << "'" << it->second << "' annotated with name '" << it->first << "'\n";
}
if (f!=l)
std::cerr << "warning: remaing unparsed: '" << std::string(f,l) << "'\n";
}
int main()
{
const std::string input(
"#include <reality>\n"
"@bind VarName\n"
"uniform int myVariable;\n"
"// other stuff\n"
"@bind Var2Name\n"
"uniform int myVariable2;\n");
test(input.begin(), input.end());
}
这将打印:
'myVariable2' annotated with name 'Var2Name'
'myVariable' annotated with name 'VarName'
请参阅详细(DEBUG)输出直播liveworkspace.org