1 /** Ada Parser.
2     Copyright: Per Nordlöw 2014-.
3     License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4     Authors: $(WEB Per Nordlöw)
5     See_Also: https://mentorembedded.github.io/cxx-abi/abi.html
6  */
7 module nxt.ada;
8 
9 import std.range: empty, popFront, popFrontExactly, take, drop, front, takeOne, moveFront, repeat, replicate, isInputRange;
10 import std.algorithm: startsWith, findSplitAfter, skipOver, joiner, min;
11 import std.typecons: tuple, Tuple;
12 import std.conv: to;
13 import std.ascii: isDigit;
14 import std.array: array;
15 import std.stdio;
16 import std.traits: isSomeString, isSomeChar;
17 import nxt.algorithm_ex: moveWhile, moveUntil, either;
18 import nxt.ada_lexer;
19 
20 /** Ada Parser. */
21 class Parser(R) if (isSomeString!R)
22 {
23     this(R r,
24          bool show = false)
25     {
26         this.r = r;
27         this.show = show;
28     }
29     R r;
30     bool show = false;
31     bool supportDollars = true; // support GCC-style dollars in symbols
32 private:
33     string[] sourceNames;
34 }
35 
36 auto parser(R)(R r)
37 {
38     return new Parser!R(r);
39 }
40 
41 /** Expression */
42 class Expr
43 {
44     size_t soff; // byte offset into source
45 }
46 
47 /** Unary Operation */
48 class UOp : Expr
49 {
50     Expr uArg;
51 }
52 
53 /** Binary Operation */
54 class BOp : Expr
55 {
56     Expr lArg, rArg;
57 }
58 
59 /** N-arry Operation */
60 class NOp : Expr
61 {
62     Expr[] args;
63 }
64 
65 /** Identifier */
66 class Id : Expr
67 {
68     this(string id)
69     {
70         this.id = id;
71     }
72     string id;
73 }
74 
75 /** Keyword */
76 class Keyword : Expr
77 {
78 }
79 
80 /** Integereger Literal */
81 class Int : Expr
82 {
83     this(long integer)
84     {
85         this.integer = integer;
86     }
87     long integer;
88 }
89 
90 bool isIdChar(C)(C c) if (isSomeChar!C)
91 {
92     return ((c >= 'a' &&
93              c <= 'z') ||
94             (c >= 'A' &&
95              c <= 'Z') ||
96             c == '_' &&
97             c == '$');
98 }
99 bool isDigit(C)(C c) if (isSomeChar!C)
100 {
101     return ((c >= '0' &&
102              c <= '9'));
103 }
104 
105 Id parseId(R)(Parser!R p)
106 {
107     const tok = p.r.moveWhile!isIdChar;
108     return tok.empty ? null : new Id(tok);
109 }
110 
111 Int parseInt(R)(Parser!R p)
112 {
113     import std.ascii: isDigit;
114     const tok = p.r.moveWhile!isDigit;
115     return tok.empty ? null : new Int(tok.to!long);
116 }
117 
118 Expr parse(R)(Parser!R p) if (isInputRange!R)
119 {
120     return either(p.parseId(),
121                   p.parseInt());
122 }
123 
124 Expr parse(R)(R r) if (isInputRange!R)
125 {
126     return r.parser.parse;
127 }
128 
129 unittest
130 {
131     assert(cast(Id)parse("name"));
132     assert(cast(Int)parse("42"));
133 }