1 // =================================
 2 // Copyright (c) 2021 Seppo Laakko
 3 // Distributed under the MIT license
 4 // =================================
 5 
 6 [hpp]#include <sngcm/cmparser/ParserApi.hpp>
 7 [hpp]#include <vector>
 8 [hpp]#include <string>
 9 [cpp]#include <soulng/lexer/TrivialLexer.hpp>
10 [cpp]#include <soulng/parser/Range.hpp>
11 
12 using namespace soulng::lexer;
13 
14 parser api(SNGCM_PARSER_API) CommandLineParser
15 {
16     uselexer TrivialLexer;
17     main;
18 
19     CommandLine(var std::vector value) : std::vector
20         ::= (Spaces:spc1? Argument:first{ value.push_back(first); } (Spaces:spc2 Argument:next{ value.push_back(next); })* Spaces:spc3? '\n'){ return value; }
21         ;
22 
23     Spaces
24         ::= "[\t ]"+
25         ;
26 
27     Argument(var std::string value) : std::string
28         ::= ((ArgElement:element{ value.append(element); })+){ return value; }
29         ;
30 
31     ArgElement(var std::string value) : std::string
32         ::= OddBackslashesAndLiteralQuotationMark:o{ return o; }
33         |   EvenBackslashesAndQuotationMark:s{ value.append(s); } (StringChar:sc{ value.append(sc); })* EvenBackslashesAndQuotationMark:e{ value.append(e); return value; }
34         |   "[^\t\n\r ]"{ value.append(ToUtf8(lexer.GetMatch(span))); return value; }
35         ;
36 
37     OddBackslashesAndLiteralQuotationMark(var Span s, var std::string value) : std::string
38         ::= "[\\]"{ s = span; } "[\\]"* '"'
39         {
40             s.end = span.end;
41             std::u32string bs = lexer.GetMatch(s);
42             int n = bs.length() - 1; 
43             pass = n % 2 == 1;
44             if (pass)
45             {
46                 value = std::string(n / 2, '\\');
47                 value.append(1, '"');
48                 return value;
49             }
50         }
51         ;
52 
53     EvenBackslashesAndQuotationMark(var Span s, var std::string value) : std::string
54         ::= empty{ s = span; } "[\\]"* '"'
55         { 
56             s.end = span.end; 
57             std::u32string bs = lexer.GetMatch(s); 
58             int n = bs.length() - 1; 
59             pass = n % 2 == 0; 
60             if (pass) 
61             {
62                 value = std::string(n / 2, '\\');
63                 return value;
64             }
65         }
66         ;
67 
68     StringChar(var Span s) : std::string
69         ::= OddBackslashesAndLiteralQuotationMark:o{ return o; }
70         |   (("[^\n\r]"{ s = span; }) - EvenBackslashesAndQuotationMark:m){ return ToUtf8(lexer.GetMatch(s)); }
71         ;
72 }