Warum sind Teile deiner Ausgaben übersetzt? Schreibst du eigentlich auf Englisch?
Aber mal abgesehen davon:
Fehlermeldung
Flex und Bison haben bei mir die gleiche Version. Als du mc_parser.yy direkt an bison übergeben hast, gibt er dir die Info, dass er nicht weiß, in welcher Reihenfolge er die Grammatik bei der source-Regel auflösen soll.
Also die hier:
sources : sources STRING { std::cout << "source: " << $2; }
| sources QUOTED_STRING { std::cout << "source: " << $2; }
| STRING { std::cout << " source: " << $1; }
| QUOTED_STRING { std::cout << " source: " << $1; }
| % empty
Eigentlich ist das ja alles rechts-terminiert, aber bin in Grammatiken grad nicht genug drin, um zu sehen, was ihm nicht gefällt.
Wäre eigentlich nützlich, wenn Bison dir einen Baum ausgeben könnte. Besonders, wenn man noch im Experimentier-Stadium ist. Vielleicht gibts das ja, aber ich habe nichts in der Art gesehen.
Testen
Das manuelle Testen der Tokens ist ganz gut machbar und es berücksichtig auch die Regeln aus dem Parser. Eigentlich hat flex einen tollen Testmodus, in dem man interaktiv Token erkennen lassen kann. Im Tutorial wird das in ähnlicher Form durch
my_wc -o
umgesetzt. Hier fliegt man allerdings beim ersten Fehler raus. Trotzdem eine gute Möglichkeit zum Testen.
Damit man nicht zugespammt wird, muss man aber noch mc_driver.cpp anpassen oder in main.cpp den driver.print auskommentieren.
int main(const int argc, const char **argv) {
MC::MC_Driver driver;
/** check for the right # of arguments **/
if (argc != 2) {
/** exit with failure condition **/
return (EXIT_FAILURE);
}
if (std::strncmp(argv[1], "-h", 2) == 0) {
/** simple help menu **/
std::cout << "use -o for pipe to std::cin\n";
std::cout << "just give a filename to count from a file\n";
std::cout << "use -h to get this menu\n";
return (EXIT_SUCCESS);
}
/** example for piping input from terminal, i.e., using cat **/
if (std::strncmp(argv[1], "-o", 2) == 0) {
driver.parse(std::cin);
}
/** example reading input from a file **/
else {
/** assume file, prod code, use stat to check **/
driver.parse(argv[1]);
}
//driver.print(std::cout) << "\n";
return (EXIT_SUCCESS);
}
Du kriegst zwar eine Bison-Warnung, aber es wird trotzdem kompiliert und man kann es interaktiv testen, zB mit CMake bauen und dann ausführen. Als möglicher Einzeiler, den man wiederholt im Basisverzeichnis ausführen kann:
mkdir build || true && popd||true && pushd build && cmake .. && make && popd && ./build/my_wc -o
Ergebnis:
build/my_wc -o
mkdir: cannot create directory ‘build’: File exists
-bash: popd: directory stack empty
/mnt/z/Projekte/Programmieren/DevCommunity/user/Mupfel/makefile-parser-test/build /mnt/z/Projekte/Programmieren/DevCommunity/user/Mupfel/makefile-parser-test
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/z/Projekte/Programmieren/DevCommunity/user/Mupfel/makefile-parser-test/build
Consolidate compiler generated dependencies of target my_wc
[100%] Built target my_wc
/mnt/z/Projekte/Programmieren/DevCommunity/user/Mupfel/makefile-parser-test
# dies ist ein kommentar
### dies dies ist ist ein ein kommentar kommentar
-z.PHONY: irgendeinblock
.PHONY: irgendeinblock source: irgendeinblock
zuweisung = dings
zuweisung target: .PHONYby dings
assignment: zuweisung dingscy
bla
Error: syntax error at 1.67
Parse failed!!
Könntest als Info erstmal die Tokennamen ausgeben lassen, anstatt direkt zu transformieren. Und Zeilen, die mit
#
beginnen kann man ja eigentlich komplett löschen/ignorieren, anstatt sie umzuwandeln. Ich glaube, dafür braucht man nicht mal eine Regel im Parser und auch keinen Comment-Eater.
Wie GNU Makefiles verarbeitet
Die gnu-Seite war gestern offline bei mir, jetzt konnte ich endlich eine Info dazu finden, wie makefiles verarbeitet werden:
Parsing Makefiles (GNU make)
www.gnu.org
Hab jetzt den Quellcode nicht gefunden, aber liest sich erstmal so, als würde es nicht Grammatik-Konstrukte verwenden und eher situationsbedingt Strings abgleichen. Da kann man sich also eher schlecht die Grammatik abschauen.
CMake ist da vielleicht etwas nützlicher, auch wenn es Makefiles nur generiert und nicht liest, wenn ich das richtig verstehe. Aber immerhin hat es ein paar Lexer und Parser:
CMake, the cross-platform, open-source build system.
gitlab.kitware.com