Skip to content

Commit 2617a57

Browse files
committed
Add empty AM extended command parsing
1 parent 587e303 commit 2617a57

File tree

10 files changed

+246
-17
lines changed

10 files changed

+246
-17
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
#include "gerber/ast/aperture/AMclose.hpp"
3+
#include "gerber/ast/aperture/AMopen.hpp"
4+
#include "gerber/ast/command.hpp"
5+
#include "gerber/ast/extended_command.hpp"
6+
#include <memory>
7+
#include <string>
8+
#include <vector>
9+
10+
namespace gerber {
11+
class AM : public ExtendedCommand {
12+
private:
13+
std::shared_ptr<AMopen> amOpen;
14+
std::vector<std::shared_ptr<Command>> primitives;
15+
std::shared_ptr<AMclose> amClose;
16+
17+
public:
18+
using primitive_t = Command;
19+
using primitives_container_t = std::vector<std::shared_ptr<primitive_t>>;
20+
21+
AM(std::shared_ptr<AMopen> amOpen,
22+
primitives_container_t primitives,
23+
std::shared_ptr<AMclose> amClose);
24+
25+
std::string getNodeName() const override;
26+
std::shared_ptr<AMopen> getAmOpen() const;
27+
primitives_container_t getPrimitives() const;
28+
std::shared_ptr<AMclose> getAmClose() const;
29+
};
30+
} // namespace gerber
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
#include "gerber/ast/node.hpp"
3+
#include <string>
4+
5+
namespace gerber {
6+
class AMclose : public Node {
7+
public:
8+
AMclose();
9+
std::string getNodeName() const override;
10+
};
11+
} // namespace gerber
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
#include "gerber/ast/node.hpp"
3+
#include <string>
4+
5+
namespace gerber {
6+
class AMopen: public Node {
7+
private:
8+
std::string apertureId;
9+
10+
AMopen() = delete;
11+
12+
public:
13+
AMopen(const std::string_view& apertureId);
14+
std::string getNodeName() const override;
15+
std::string getApertureId() const;
16+
};
17+
} // namespace gerber

cpp/gerber/include/gerber/ast/ast.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
#include "./aperture/AD.hpp"
88
#include "./aperture/ADC.hpp"
99
#include "./aperture/ADO.hpp"
10-
#include "./aperture/ADR.hpp"
1110
#include "./aperture/ADP.hpp"
11+
#include "./aperture/ADR.hpp"
12+
#include "./aperture/AM.hpp"
13+
#include "./aperture/AMclose.hpp"
14+
#include "./aperture/AMopen.hpp"
1215

1316
#include "./d_codes/D01.hpp"
1417
#include "./d_codes/D02.hpp"

cpp/gerber/include/gerber/parser.hpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace gerber {
3636
std::regex m_code_regex{"^[Mm]0*([1-9][0-9]*)\\*"};
3737
// Helper regex
3838
std::regex float_regex{"([+-]?((([0-9]+)(\\.[0-9]*)?)|(\\.[0-9]+)))"};
39+
std::regex name_regex{"([._a-zA-Z$][._a-zA-Z0-9]*)"};
3940

4041
public:
4142
Parser();
@@ -86,22 +87,44 @@ namespace gerber {
8687
* to point to the next character after the float. If there is no valid float
8788
* literal throw SyntaxError.
8889
*/
89-
double consume_float(std::string_view& source, offset_t& offset);
90+
double consume_float(std::string_view& source, offset_t& offset);
9091
/**
9192
* Check if next character in the source string is the expected one. If it is,
9293
* move source and offset to point to the next character. Otherwise throw SyntaxError.
9394
*/
94-
char consume_char(std::string_view& source, offset_t& offset, char expected);
95+
char consume_char(std::string_view& source, offset_t& offset, char expected);
9596
/**
9697
* Check if next character in the source string is the expected one. If it is,
9798
* move source, offset to point to the next character and return True. Otherwise
9899
* return False.
99100
*/
100-
bool try_consume_char(std::string_view& source, offset_t& offset, char expected);
101+
bool try_consume_char(std::string_view& source, offset_t& offset, char expected);
102+
/**
103+
* Check if next characters in the source string match regex. If they do,
104+
* move source and offset to point to the next character after the match and
105+
* return matched string. Otherwise throw SyntaxError.
106+
*/
107+
std::string consume_regex(std::string_view& source, offset_t& offset, std::regex& expected);
101108

102109
offset_t match_char(const std::string_view& source, char expected);
103110
std::string match_float(const std::string_view& source);
104111

112+
offset_t parse_aperture_macro(const std::string_view& source);
113+
void parse_aperture_macro_open(
114+
std::string_view& source, offset_t& offset, std::shared_ptr<AMopen>& amOpen
115+
);
116+
offset_t parse_aperture_macro_primitive(
117+
const std::string_view& source, AM::primitives_container_t& primitives
118+
);
119+
void parse_aperture_macro_close(
120+
std::string_view& source, offset_t& offset, std::shared_ptr<AMclose>& amClose
121+
);
122+
/**
123+
* Check if next characters in the source string are whitespace. If they are,
124+
* move source and offset to point to the next character after whitespaces.
125+
*/
126+
void skip_whitespace(std::string_view& source, offset_t& offset);
127+
105128
offset_t parse_g_code(const std::string_view& gerber, const location_t& index);
106129
offset_t parse_m_code(const std::string_view& gerber);
107130
offset_t parse_d_code(const std::string_view& source, const location_t& index);

cpp/gerber/src/ast/aperture/AM.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "gerber/ast/aperture/AM.hpp"
2+
3+
namespace gerber {
4+
AM::AM(
5+
std::shared_ptr<AMopen> amOpen_,
6+
AM::primitives_container_t primitives_,
7+
std::shared_ptr<AMclose> amClose_
8+
) :
9+
amOpen(amOpen_),
10+
primitives(primitives_),
11+
amClose(amClose_) {}
12+
13+
std::string AM::getNodeName() const {
14+
return "AM";
15+
}
16+
17+
std::shared_ptr<AMopen> AM::getAmOpen() const {
18+
return amOpen;
19+
}
20+
21+
AM::primitives_container_t AM::getPrimitives() const {
22+
return primitives;
23+
}
24+
25+
std::shared_ptr<AMclose> AM::getAmClose() const {
26+
return amClose;
27+
}
28+
} // namespace gerber
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "gerber/ast/aperture/AMclose.hpp"
2+
3+
namespace gerber {
4+
AMclose::AMclose() {}
5+
6+
std::string AMclose::getNodeName() const {
7+
return "AMclose";
8+
}
9+
} // namespace gerber
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "gerber/ast/aperture/AMopen.hpp"
2+
3+
namespace gerber {
4+
AMopen::AMopen(const std::string_view& apertureId_) :
5+
apertureId(apertureId_) {}
6+
7+
std::string AMopen::getNodeName() const {
8+
return "AMopen";
9+
}
10+
11+
std::string AMopen::getApertureId() const {
12+
return apertureId;
13+
}
14+
} // namespace gerber

cpp/gerber/src/parser.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "gerber/parser.hpp"
22
#include "gerber/ast/ast.hpp"
3+
#include "gerber/ast/command.hpp"
34
#include "gerber/ast/m_codes/M02.hpp"
45
#include <algorithm>
56
#include <cassert>
@@ -119,6 +120,10 @@ namespace gerber {
119120
return parse_aperture_definition(source);
120121
break;
121122

123+
case 'M':
124+
return parse_aperture_macro(source);
125+
break;
126+
122127
default:
123128
break;
124129
}
@@ -253,6 +258,26 @@ namespace gerber {
253258
return true;
254259
}
255260

261+
std::string
262+
Parser::consume_regex(std::string_view& source, offset_t& offset, std::regex& expected) {
263+
std::cmatch match;
264+
265+
const auto result = std::regex_search(
266+
source.data(),
267+
source.data() + source.size(),
268+
match,
269+
expected,
270+
std::regex_constants::match_continuous
271+
);
272+
if (result && match.size() >= 1) {
273+
auto match_length = match.length();
274+
offset += match_length;
275+
source = source.substr(match_length);
276+
return match[0].str();
277+
}
278+
throw_syntax_error();
279+
}
280+
256281
offset_t Parser::match_char(const std::string_view& source, char expected) {
257282
if (source.empty() || source[0] != expected) {
258283
throw_syntax_error();
@@ -276,6 +301,62 @@ namespace gerber {
276301
throw_syntax_error();
277302
}
278303

304+
offset_t Parser::parse_aperture_macro(const std::string_view& source) {
305+
std::shared_ptr<AMopen> amOpen;
306+
AM::primitives_container_t primitives;
307+
std::shared_ptr<AMclose> amClose;
308+
309+
std::string_view rest = source;
310+
311+
offset_t offset = 0;
312+
parse_aperture_macro_open(rest, offset, amOpen);
313+
314+
offset_t previous_offset = offset;
315+
while (!source.empty() && previous_offset) {
316+
skip_whitespace(rest, offset);
317+
previous_offset = parse_aperture_macro_primitive(rest, primitives);
318+
}
319+
320+
parse_aperture_macro_close(rest, offset, amClose);
321+
322+
commands.push_back(std::make_shared<AM>(amOpen, primitives, amClose));
323+
return offset;
324+
}
325+
326+
void Parser::parse_aperture_macro_open(
327+
std::string_view& source, offset_t& offset, std::shared_ptr<AMopen>& amOpen
328+
) {
329+
consume_char(source, offset, '%');
330+
consume_char(source, offset, 'A');
331+
consume_char(source, offset, 'M');
332+
auto name = consume_regex(source, offset, name_regex);
333+
consume_char(source, offset, '*');
334+
335+
amOpen = std::make_shared<AMopen>(name);
336+
}
337+
338+
offset_t Parser::parse_aperture_macro_primitive(
339+
const std::string_view& source, AM::primitives_container_t& primitives
340+
) {
341+
return 0;
342+
}
343+
344+
void Parser::parse_aperture_macro_close(
345+
std::string_view& source, offset_t& offset, std::shared_ptr<AMclose>& amClose
346+
) {
347+
consume_char(source, offset, '%');
348+
amClose = std::make_shared<AMclose>();
349+
}
350+
351+
void Parser::skip_whitespace(std::string_view& source, offset_t& offset) {
352+
offset_t local_offset = 0;
353+
while (local_offset < source.length() && std::isspace(source[local_offset])) {
354+
local_offset++;
355+
}
356+
source = source.substr(local_offset);
357+
offset += local_offset;
358+
}
359+
279360
offset_t Parser::parse_g_code(const std::string_view& gerber, const location_t& index) {
280361
std::cmatch match;
281362

0 commit comments

Comments
 (0)