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 	assert(cast(Id)parse("name"));
131 	assert(cast(Int)parse("42"));
132 }