Ich möchte analysieren (in erster Instanz, nur erkennen, Symbole behalten) LaTeX math. Gerade jetzt, ich habe Probleme mit den Super-und Indices, in Kombination mit geschweiften Klammern (z. B. a^{bc}
und Kombinationen davon, ich habe die grundlegende a^b
funktioniert gut). Ein minimales Beispiel (so kurz wie irgend möglich, während die Lesbarkeit zu halten):Wie bekomme ich diese rekursive Regel zu arbeiten?
#include <iostream>
using std::cout;
#include <string>
using std::string;
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
using x3::space;
using x3::char_;
using x3::lit;
using x3::repeat;
x3::rule<struct scripts, string> scripts = "super- and subscripts";
x3::rule<struct braced_thing, string> braced_thing = "thing optionaly surrounded by curly braces";
x3::rule<struct superscript, string> superscript = "superscript";
x3::rule<struct subscript, string> subscript = "subscript";
// main rule: any number of items with or without braces
auto const scripts_def = *braced_thing;
// second level main rule: optional braces, and any number of characters or sub/superscripts
auto const braced_thing_def = -lit('{') >> *(subscript | superscript | repeat(1)[(char_ - "_^{}")]) >> -lit('}');
// superscript: things of the form a^b where a and b can be surrounded by curly braces
auto const superscript_def = braced_thing >> '^' >> braced_thing;
// subscript: things of the form a_b where a and b can be surrounded by curly braces
auto const subscript_def = braced_thing >> '_' >> braced_thing;
BOOST_SPIRIT_DEFINE(scripts)
BOOST_SPIRIT_DEFINE(braced_thing)
BOOST_SPIRIT_DEFINE(superscript)
BOOST_SPIRIT_DEFINE(subscript)
int main()
{
const string input = "a^{b_x y}_z {v_x}^{{x^z}_y}";
string output; // will only contain the characters as the grammar is defined above
auto first = input.begin();
auto last = input.end();
const bool result = x3::phrase_parse(first, last,
scripts,
space,
output);
if(first != last)
std::cout << "partial match only:\n" << output << '\n';
else if(!result)
std::cout << "parse failed!\n";
else
std::cout << "parsing succeeded:\n" << output << '\n';
}
Es ist auch Available on Coliru.
Problem ist, diese segfaults (ich bin sicher aus offensichtlichen Gründen) und ich habe keine andere Möglichkeit, dies in einer ... Ausdruck Grammatik auszudrücken.
Ihr Problem ist ähnlich (aber weitaus komplexer) auf [diese man] (http://stackoverflow.com/questions/18611990/flipping-the-order-of-subrules-inside-a-rule-in-a-boostspirit-grammar-results). Ich bin weit davon entfernt, sicher zu sein, dass [das] (http://coliru.stacked-crooked.com/a/79e2edf0a6ff86d1) korrekt ist, aber sehen Sie, ob es hilft. Wenn Sie in Zukunft einen AST erstellen müssen, wird es nicht schön sein (semantische Aktionshölle). Hoffentlich bekommst du eine bessere Antwort. PS: Dein 'char _-" _^{} "' ist nicht korrekt, es ist äquivalent zu 'char_-lit (" _^{} ")' aber 'lit (" abc ")' stimmt genau mit "abc" nicht mit "a" überein "oder" b "oder" c ". – llonesmiz
@cv_and_he Tatsächlich entfernt das Beispiel die Linksrekursion und behebt die schlampige Handhabung von '{}'. Hier ist [ein Update, das zeigt] (http://coliru.stacked-crooked.com/a/30b2ee7981c52bab) es mindestens _matching_ die gleichen Testfälle (ich bin mir ziemlich sicher, es gibt einen Unterschied in den ASTs "geleistet" aber wir können sage nicht, was besser zum OP passt, denke ich). – sehe