examples: annotate examples
[nit.git] / lib / parser_base.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
9 # another product.
10
11 # Simple base for hand-made parsers of all kinds
12 module parser_base
13
14 import serialization
15
16 # Basic facilities for common parser operations on String sources
17 class StringProcessor
18 # Source document to parse
19 protected var src: String
20
21 # Length of the source document
22 protected var len: Int is noinit
23
24 # Current position in `src`
25 protected var pos = 0
26
27 # Position at which current line started
28 protected var line_start = 0
29
30 # Current line in `src`
31 protected var line = 1
32
33 # Offset in the current line
34 protected fun line_offset: Int do return pos - line_start + 1
35
36 init do
37 _len = src.length
38 end
39
40 # Gives the current location in the `src`
41 fun current_location: Location do return new Location(line, line_offset)
42
43 # Advances in `src` until a non-whitespace character is encountered
44 protected fun ignore_whitespaces do
45 var srclen = _len
46 var p = _pos
47 if p >= srclen then return
48 var c = src[p]
49 while c.is_whitespace do
50 p += 1
51 if p >= srclen then break
52 if c == '\n' then
53 _line += 1
54 _line_start = p
55 end
56 c = src[p]
57 end
58 _pos = p
59 return
60 end
61
62 # Reads characters until pattern `s` is found
63 protected fun ignore_until(s: String): Int do
64 if s.length == 0 then return _pos
65 var srclen = _len
66 var p = _pos
67 if p >= srclen then return -1
68 loop
69 var c = s[0]
70 var src_c = src[p]
71 while src_c != c do
72 p += 1
73 if p >= srclen then
74 _pos = p
75 return -1
76 end
77 if src_c == '\n' then
78 line += 1
79 line_start= pos
80 end
81 src_c = src[p]
82 end
83 var relpos = p
84 var fnd = true
85 for i in s do
86 if relpos >= srclen then
87 fnd = false
88 break
89 end
90 if src[relpos] != i then
91 p += 1
92 fnd = false
93 break
94 end
95 relpos += 1
96 end
97 if fnd then
98 _pos = p
99 return p
100 end
101 end
102 end
103
104 # Ignores any printable character until a whitespace is encountered
105 protected fun ignore_until_whitespace: Int do
106 while src.length > pos and not src[pos].is_whitespace do pos += 1
107 return pos
108 end
109
110 # Returns the current location as a `Location` object
111 protected fun hot_location: Location do return new Location(line, line_offset)
112
113 # Is `pos` at the end of the source?
114 protected fun eof: Bool do return pos >= src.length
115 end
116
117 # Information about the location of an entity in a source document
118 class Location
119 serialize
120
121 # Line in which the element is described
122 var line: Int
123 # Offset in the line at which the element is positioned
124 var offset: Int
125
126 redef fun to_s do return "line {line}, position {offset}"
127 end