1 module ddc.lexer.textsource;
2 
3 private import std.utf;
4 private import std.array;
5 
6 /**
7 * Source file information.
8 * Even if contains only file name, it's better to use it instead of string - object reference size is twice less than array ref.
9 */
10 class SourceFile {
11 	protected string _filename;
12 	@property string filename() { return _filename; }
13     public this(string filename) {
14         _filename = filename;
15     }
16     override @property string toString() {
17         return _filename;
18     }
19 }
20 
21 /// source lines for tokenizer
22 interface SourceLines {
23     /// source file
24 	@property SourceFile file();
25     /// last read line
26 	@property uint line();
27     /// source encoding
28 	//@property EncodingType encoding() { return _encoding; }
29     /// error code
30 	@property int errorCode();
31     /// error message
32 	@property string errorMessage();
33     /// error line
34 	@property int errorLine();
35     /// error position
36 	@property int errorPos();
37     /// end of file reached
38     @property bool eof();
39 
40     /// read line, return null if EOF reached or error occured
41     dchar[] readLine();
42 }
43 
44 const TEXT_SOURCE_ERROR_EOF = 1;
45 
46 /// Simple text source based on array
47 class ArraySourceLines : SourceLines {
48     protected SourceFile _file;
49     protected uint _line;
50     protected uint _firstLine;
51     protected dstring[] _lines;
52     static __gshared protected dchar[] _emptyLine = ""d.dup;
53 
54     this() {
55     }
56 
57     this(dstring[] lines, SourceFile file, uint firstLine = 0) {
58         init(lines, file, firstLine);
59     }
60 
61     this(string code, string filename) {
62         _lines = (toUTF32(code)).split("\n");
63         _file = new SourceFile(filename);
64     }
65 
66     void close() {
67         _lines = null;
68         _line = 0;
69         _firstLine = 0;
70         _file = null;
71     }
72 
73     void init(dstring[] lines, SourceFile file, uint firstLine = 0) {
74         _lines = lines;
75         _firstLine = firstLine;
76         _line = 0;
77         _file = file;
78     }
79 
80     bool reset(int line) {
81         _line = line;
82         return true;
83     }
84 
85     /// end of file reached
86     override @property bool eof() {
87         return _line >= _lines.length;
88     }
89     /// source file
90     override @property SourceFile file() { return _file; }
91     /// last read line
92 	override @property uint line() { return _line + _firstLine; }
93     /// source encoding
94 	//@property EncodingType encoding() { return _encoding; }
95     /// error code
96 	override @property int errorCode() { return 0; }
97     /// error message
98 	override @property string errorMessage() { return ""; }
99     /// error line
100 	override @property int errorLine() { return 0; }
101     /// error position
102 	override @property int errorPos() { return 0; }
103 
104     /// read line, return null if EOF reached or error occured
105     override dchar[] readLine() {
106         if (_line < _lines.length) {
107             if (_lines[_line])
108                 return cast(dchar[])_lines[_line++];
109             _line++;
110             return _emptyLine;
111         }
112         return null; // EOF
113     }
114 }