1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Parsing of commands understood by documentation tools.
17 # This can be through:
18 # * `nitx` commands like `code: MEntity::name`
19 # * `nitdoc` wikilinks like `[[doc: MEntity::name]]`
23 class DocCommandParser
25 # List of allowed command names for this parser
26 var allowed_commands
: Array[String] = [ "doc", "comment", "list", "param",
27 "return", "new", "call", "code", "graph"] is writable
29 # Parse `string` as a DocCommand
31 # Returns `null` if the string cannot be parsed.
34 # var parser = new DocCommandParser
36 # var command = parser.parse("comment: core::Array")
37 # assert command isa CommentCommand
38 # assert command.arg == "core::Array"
40 # command = parser.parse(":") # syntax error
41 # assert command == null
42 # assert parser.errors.not_empty
44 fun parse
(string
: String): nullable DocCommand do
46 var tmp
= new FlatBuffer
50 pos
= string
.read_until
(tmp
, pos
, ':')
51 var name
= tmp
.write_to_string
.trim
53 # Check allowed commands
55 error
("empty command name", 0)
58 if not allowed_commands
.has
(name
) then
59 error
("unknown command name", 0)
64 var command
= new_command
(name
, string
)
65 if command
== null then
66 error
("unknown command name", 0)
72 pos
= string
.read_until
(tmp
, pos
+ 1, '|')
73 var arg
= tmp
.write_to_string
.trim
75 error
("empty command arg", pos
)
80 # Parse command options
81 while pos
< string
.length
do
84 pos
= string
.read_until
(tmp
, pos
+ 1, ':', ',')
85 var oname
= tmp
.write_to_string
.trim
87 if oname
.is_empty
then break
89 if pos
< string
.length
and string
[pos
] == ':' then
91 pos
= string
.read_until
(tmp
, pos
+ 1, ',')
92 oval
= tmp
.write_to_string
.trim
94 command
.opts
[oname
] = oval
101 # Init a new DocCommand from its `name`
103 # You must redefine this method to add new custom commands.
104 fun new_command
(name
, string
: String): nullable DocCommand do
105 if name
== "doc" then return new ArticleCommand(string
)
106 if name
== "comment" then return new CommentCommand(string
)
107 if name
== "list" then return new ListCommand(string
)
108 if name
== "param" then return new ParamCommand(string
)
109 if name
== "return" then return new ReturnCommand(string
)
110 if name
== "new" then return new NewCommand(string
)
111 if name
== "call" then return new CallCommand(string
)
112 if name
== "code" then return new CodeCommand(string
)
113 if name
== "graph" then return new GraphCommand(string
)
117 # Errors and warnings from last call to `parse`
118 var errors
= new Array[DocMessage]
121 fun error
(message
: String, col
: nullable Int) do
122 errors
.add
new DocMessage(1, message
, col
)
126 fun warning
(message
: String, col
: nullable Int) do
127 errors
.add
new DocMessage(2, message
, col
)
131 # A message generated by the DocCommandParser
140 # Message explanatory string
143 # Related column in original string if any
144 var col
: nullable Int
147 var str
= new FlatBuffer
151 str
.append
"Warning: "
156 str
.append
" (col: {col})"
158 return str
.write_to_string
163 # Read `self` as raw text until `nend` and append it to the `out` buffer.
164 private fun read_until
(out
: FlatBuffer, start
: Int, nend
: Char...): Int do
166 while pos
< length
do
168 var end_reached
= false
175 if end_reached
then break
183 # A command aimed at a documentation tool like `nitdoc` or `nitx`.
185 # `DocCommand` are generally of the form `command: arg | opt1: val1, opt2: val2`.
186 abstract class DocCommand
188 # Original command string.
192 var name
: String is noinit
195 var arg
: String is noinit
, writable
198 var opts
= new HashMap[String, String] is writable
201 if opts
.is_empty
then
202 return "{name}: {arg}"
204 return "{name}: {arg} | {opts.join(", ", ": ")}"
208 # A `DocCommand` that includes the documentation article of a `MEntity`.
210 # Syntax: `doc: MEntity::name`.
214 redef var name
= "doc"
217 # A `DocCommand` that includes the MDoc of a `MEntity`.
219 # Syntax: `comment: MEntity::name`.
223 redef var name
= "comment"
226 # A `DocCommand` that includes a list of something.
228 # Syntax: `list:kind: <arg>`.
232 redef var name
= "list"
235 # A `DocCommand` that includes the list of methods tanking a `MType` as parameter.
237 # Syntax: `param: MType`.
241 redef var name
= "param"
244 # A `DocCommand` that includes the list of methods returning a `MType` as parameter.
246 # Syntax: `return: MType`.
250 redef var name
= "return"
253 # A `DocCommand` that includes the list of methods creating new instances of a specific `MType`
255 # Syntax: `new: MType`.
259 redef var name
= "new"
262 # A `DocCommand` that includes the list of methods calling a specific `MProperty`.
264 # Syntax: `call: MEntity::name`.
268 redef var name
= "call"
271 # A `DocCommand` that includes the source code of a `MEntity`.
274 # * `code: MEntity::name`
275 # * `./src/file.nit` to include source code from a file.
276 # * `./src/file.nit:1,2--3,4` to select code between positions.
280 redef var name
= "code"
283 # A `DocCommand` that display an graph for a `MEntity`.
286 # * `graph: MEntity::name`
290 redef var name
= "graph"