1 module ctpg.dsl.typed.combinators;
2 
3 import ctpg : parse;
4 
5 import ctpg.for_unittest;
6 import ctpg.is_wrapper : isSameType;
7 import ctpg.caller : Caller;
8 import ctpg.input : Input;
9 import ctpg.macro_ : MAKE_RESULT;
10 import ctpg.parse_result : ParseResult, getParseResultType;
11 import ctpg.parser_kind : ParserKind;
12 
13 import ctpg.dsl.typed.token : Token, TokenType;
14 import ctpg.dsl.typed.node : Node;
15 
16 import parsers = ctpg.parsers;
17 import combinators = ctpg.combinators;
18 
19 import compile_time_unittest : enableCompileTimeUnittest;
20 mixin enableCompileTimeUnittest;
21 
22 
23 // 自動でnodeのlineとfileをセットするようにするコンビネータ
24 template setInfo(alias parser)
25 {
26     template build(alias kind, SrcType)
27     {
28         static if(isSameType!(getParseResultType!(parser.build!(kind, SrcType)), Node))
29         {
30             mixin MAKE_RESULT!q{ Node };
31 
32             Result parse(Input!SrcType input, in Caller caller)
33             {
34                 return combinators.convert!
35                 (
36                     combinators.sequence!
37                     (
38                         parsers.getLine!(),
39                         parsers.getCallerLine!(),
40                         parsers.getCallerFile!(),
41                         parser
42                     ),
43                     (size_t line, size_t callerLine, string callerFile, Node node)
44                     {
45                         node.line = callerLine + line + 1;
46                         node.file = callerFile;
47 
48                         return node;
49                     }
50                 ).build!(kind, SrcType).parse(input, caller);
51             }
52         }
53         else
54         {
55             static assert(false);
56         }
57     }
58 }
59 
60 debug(ctpg) unittest
61 {
62     with(parse!(setInfo!(TestParser!(Node())), ParserKind!(true, true))(""))
63     {
64         assert(match == true);
65         assert(value.line == __LINE__ - 2);
66         assert(value.file == __FILE__);
67         assert(nextInput.source == "");
68     }
69 }
70 
71 
72 // パーサが返した文字列と、引数のtokenTypeを使ってNodeを作るコンビネータ
73 template makeNode(alias parser, TokenType tokenType)
74 {
75     template build(alias kind, SrcType)
76     {
77         mixin MAKE_RESULT!q{ Node };
78 
79         Result parse(Input!SrcType input, in Caller caller)
80         {
81             return setInfo!
82             (
83                 combinators.convert!
84                 (
85                     parser,
86                     (string token) => Node(Token(tokenType, token))
87                 )
88             ).build!(kind, SrcType).parse(input, caller);
89         }
90     }
91 }
92 
93 debug(ctpg) unittest
94 {
95     with(parse!(makeNode!(TestParser!"hoge", TokenType.UNDEFINED), ParserKind!(true, true))(""))
96     {
97         assert(match == true);
98         assert(value.token == Token(TokenType.UNDEFINED, "hoge"));
99         assert(value.line == __LINE__ - 3);
100         assert(value.file == __FILE__);
101         assert(nextInput.source == "");
102     }
103 }