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 }