@@ -39,11 +39,16 @@ Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _sou
39
39
{
40
40
m_sourceStream = std::istringstream (_source);
41
41
m_sourceName = std::move (_sourceName);
42
- Json codeJSON = Json::array ();
43
42
m_lineNumber = 0 ;
44
43
45
- if (!m_line.has_value ())
46
- advanceLine ();
44
+ advanceLine ();
45
+ return parseAssembly (0 );
46
+ }
47
+
48
+ Json PlainAssemblyParser::parseAssembly (size_t _nestingLevel)
49
+ {
50
+ Json assemblyJSON = {{" .code" , Json::array ()}};
51
+ Json& codeJSON = assemblyJSON[" .code" ];
47
52
48
53
while (m_line.has_value ())
49
54
{
@@ -52,6 +57,25 @@ Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _sou
52
57
advanceLine ();
53
58
continue ;
54
59
}
60
+
61
+ size_t newLevel = parseNestingLevel ();
62
+ if (newLevel > _nestingLevel)
63
+ BOOST_THROW_EXCEPTION (std::runtime_error (formatError (" Indentation does not match the current subassembly nesting level." )));
64
+
65
+ if (newLevel < _nestingLevel)
66
+ return assemblyJSON;
67
+
68
+ if (currentToken ().value == " .sub" )
69
+ {
70
+ advanceLine ();
71
+
72
+ std::string nextDataIndex = std::to_string (assemblyJSON[" .data" ].size ());
73
+ assemblyJSON[" .data" ][nextDataIndex] = parseAssembly (_nestingLevel + 1 );
74
+ continue ;
75
+ }
76
+ else if (assemblyJSON.contains (" .data" ))
77
+ BOOST_THROW_EXCEPTION (std::runtime_error (formatError (" The code of an assembly must be specified before its subassemblies." )));
78
+
55
79
if (c_instructions.contains (currentToken ().value ))
56
80
{
57
81
expectNoMoreArguments ();
@@ -91,7 +115,21 @@ Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _sou
91
115
92
116
advanceLine ();
93
117
}
94
- return {{" .code" , codeJSON}};
118
+
119
+ return assemblyJSON;
120
+ }
121
+
122
+ size_t PlainAssemblyParser::parseNestingLevel () const
123
+ {
124
+ std::string_view indentationString = indentation ();
125
+
126
+ if (indentationString != std::string (indentationString.size (), ' ' ))
127
+ BOOST_THROW_EXCEPTION (std::runtime_error (formatError (" Non-space characters used for indentation." )));
128
+
129
+ if (indentationString.size () % 4 != 0 )
130
+ BOOST_THROW_EXCEPTION (std::runtime_error (formatError (" Each indentation level must consist of 4 spaces." )));
131
+
132
+ return indentationString.size () / 4 ;
95
133
}
96
134
97
135
PlainAssemblyParser::Token const & PlainAssemblyParser::currentToken () const
@@ -106,6 +144,16 @@ PlainAssemblyParser::Token const& PlainAssemblyParser::nextToken() const
106
144
return m_lineTokens[m_tokenIndex + 1 ];
107
145
}
108
146
147
+ std::string_view PlainAssemblyParser::indentation () const
148
+ {
149
+ soltestAssert (m_line.has_value ());
150
+
151
+ if (m_lineTokens.empty ())
152
+ return *m_line;
153
+
154
+ return std::string_view (*m_line).substr (0 , m_lineTokens.at (0 ).position );
155
+ }
156
+
109
157
bool PlainAssemblyParser::advanceToken ()
110
158
{
111
159
if (!hasMoreTokens ())
0 commit comments