OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
example_usage.cpp
1// Example usage of ANTLR v4 OMDParser
2// This file shows how to integrate the new parser into OpenMD
3
4#include "antlr4-runtime.h"
5#include "OMDLexer.h"
6#include "OMDParser.h"
7#include "OMDTreeVisitor.hpp"
8#include "io/Globals.hpp"
9#include <fstream>
10#include <iostream>
11
12// Custom error listener for better error reporting
13class OMDErrorListener : public antlr4::BaseErrorListener {
14public:
15 void syntaxError(
16 antlr4::Recognizer *recognizer,
17 antlr4::Token *offendingSymbol,
18 size_t line,
19 size_t charPositionInLine,
20 const std::string &msg,
21 std::exception_ptr e
22 ) override {
23 std::cerr << "Syntax error at line " << line
24 << ":" << charPositionInLine
25 << " - " << msg << std::endl;
26
27 // You can throw an exception here if you want to halt parsing
28 // throw std::runtime_error("Parse error");
29 }
30};
31
32// Function to parse an OpenMD file and return Globals configuration
33Globals* parseOmdFile(const std::string& filename) {
34 try {
35 // Open the file
36 std::ifstream stream(filename);
37 if (!stream.is_open()) {
38 std::cerr << "Failed to open file: " << filename << std::endl;
39 return nullptr;
40 }
41
42 // Create ANTLR input stream from file
43 antlr4::ANTLRInputStream input(stream);
44
45 // Create lexer
46 OMDLexer lexer(&input);
47
48 // Optional: Set up filename observer for preprocessor directives
49 // FilenameObserver* observer = new FilenameObserver();
50 // lexer.setObserver(observer);
51
52 // Create token stream
53 antlr4::CommonTokenStream tokens(&lexer);
54
55 // Create parser
56 OMDParser parser(&tokens);
57
58 // Optional: Add custom error listener
59 OMDErrorListener errorListener;
60 parser.removeErrorListeners(); // Remove default console error listener
61 parser.addErrorListener(&errorListener);
62
63 // Parse the file (top-level rule is 'omdfile')
64 OMDParser::OmdfileContext* tree = parser.omdfile();
65
66 // Check for parse errors
67 if (parser.getNumberOfSyntaxErrors() > 0) {
68 std::cerr << "Parsing failed with "
69 << parser.getNumberOfSyntaxErrors()
70 << " errors" << std::endl;
71 return nullptr;
72 }
73
74 // Create visitor and walk the parse tree
75 OMDTreeVisitor visitor;
76 Globals* conf = visitor.walkTree(tree);
77
78 return conf;
79
80 } catch (const std::exception& e) {
81 std::cerr << "Exception during parsing: " << e.what() << std::endl;
82 return nullptr;
83 }
84}
85
86// Function to parse from a string (useful for testing)
87Globals* parseOmdString(const std::string& input) {
88 try {
89 // Create ANTLR input stream from string
90 antlr4::ANTLRInputStream inputStream(input);
91
92 // Create lexer
93 OMDLexer lexer(&inputStream);
94
95 // Create token stream
96 antlr4::CommonTokenStream tokens(&lexer);
97
98 // Create parser
99 OMDParser parser(&tokens);
100
101 // Parse
102 OMDParser::OmdfileContext* tree = parser.omdfile();
103
104 // Visit tree
105 OMDTreeVisitor visitor;
106 Globals* conf = visitor.walkTree(tree);
107
108 return conf;
109
110 } catch (const std::exception& e) {
111 std::cerr << "Exception during parsing: " << e.what() << std::endl;
112 return nullptr;
113 }
114}
115
116// Example main function
117int main(int argc, char* argv[]) {
118 if (argc < 2) {
119 std::cerr << "Usage: " << argv[0] << " <input.omd>" << std::endl;
120 return 1;
121 }
122
123 std::string filename = argv[1];
124
125 std::cout << "Parsing file: " << filename << std::endl;
126
127 Globals* config = parseOmdFile(filename);
128
129 if (config) {
130 std::cout << "Parsing successful!" << std::endl;
131 // Use config...
132
133 // Don't forget to delete when done
134 delete config;
135 return 0;
136 } else {
137 std::cerr << "Parsing failed!" << std::endl;
138 return 1;
139 }
140}
141
142// ============================================================================
143// Advanced Usage Examples
144// ============================================================================
145
146// Example: Custom visitor for specific processing
147class CustomOMDVisitor : public OMDTreeVisitor {
148public:
149 int moleculeCount = 0;
150 int atomCount = 0;
151
152 virtual antlrcpp::Any visitMoleculeblock(OMDParser::MoleculeblockContext *ctx) override {
153 moleculeCount++;
154 std::cout << "Found molecule #" << moleculeCount << std::endl;
155 return OMDTreeVisitor::visitMoleculeblock(ctx);
156 }
157
158 virtual antlrcpp::Any visitAtomblock(OMDParser::AtomblockContext *ctx) override {
159 atomCount++;
160 std::cout << "Found atom #" << atomCount << std::endl;
161 return OMDTreeVisitor::visitAtomblock(ctx);
162 }
163};
164
165// Example: Print parse tree structure
166void printParseTree(antlr4::tree::ParseTree* tree, const OMDParser& parser, int indent = 0) {
167 std::string indentStr(indent * 2, ' ');
168
169 if (auto* terminalNode = dynamic_cast<antlr4::tree::TerminalNode*>(tree)) {
170 // Leaf node (token)
171 std::cout << indentStr << "TOKEN: " << terminalNode->getText() << std::endl;
172 } else if (auto* ruleNode = dynamic_cast<antlr4::RuleContext*>(tree)) {
173 // Rule node
174 std::string ruleName = parser.getRuleNames()[ruleNode->getRuleIndex()];
175 std::cout << indentStr << "RULE: " << ruleName << std::endl;
176
177 // Recursively print children
178 for (size_t i = 0; i < ruleNode->children.size(); i++) {
179 printParseTree(ruleNode->children[i], parser, indent + 1);
180 }
181 }
182}
183
184// Example: Validate without processing
185bool validateOmdFile(const std::string& filename) {
186 std::ifstream stream(filename);
187 if (!stream.is_open()) {
188 return false;
189 }
190
191 antlr4::ANTLRInputStream input(stream);
192 OMDLexer lexer(&input);
193 antlr4::CommonTokenStream tokens(&lexer);
194 OMDParser parser(&tokens);
195
196 // Just parse, don't process
197 parser.omdfile();
198
199 return parser.getNumberOfSyntaxErrors() == 0;
200}
201
202// Example: Get detailed error information
203struct ParseError {
204 size_t line;
205 size_t column;
206 std::string message;
207};
208
209class DetailedErrorListener : public antlr4::BaseErrorListener {
210public:
211 std::vector<ParseError> errors;
212
213 void syntaxError(
214 antlr4::Recognizer *recognizer,
215 antlr4::Token *offendingSymbol,
216 size_t line,
217 size_t charPositionInLine,
218 const std::string &msg,
219 std::exception_ptr e
220 ) override {
221 ParseError error;
222 error.line = line;
223 error.column = charPositionInLine;
224 error.message = msg;
225 errors.push_back(error);
226 }
227};
228
229std::vector<ParseError> getParseErrors(const std::string& filename) {
230 std::ifstream stream(filename);
231 antlr4::ANTLRInputStream input(stream);
232 OMDLexer lexer(&input);
233 antlr4::CommonTokenStream tokens(&lexer);
234 OMDParser parser(&tokens);
235
236 DetailedErrorListener errorListener;
237 parser.removeErrorListeners();
238 parser.addErrorListener(&errorListener);
239
240 parser.omdfile();
241
242 return errorListener.errors;
243}