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", "list", "param", "return",
27 "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("doc: 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 CommentCommand(string
)
106 if name
== "list" then return new ListCommand(string
)
107 if name
== "param" then return new ParamCommand(string
)
108 if name
== "return" then return new ReturnCommand(string
)
109 if name
== "new" then return new NewCommand(string
)
110 if name
== "call" then return new CallCommand(string
)
111 if name
== "code" then return new CodeCommand(string
)
112 if name
== "graph" then return new GraphCommand(string
)
116 # Errors and warnings from last call to `parse`
117 var errors
= new Array[DocMessage]
120 fun error
(message
: String, col
: nullable Int) do
121 errors
.add
new DocMessage(1, message
, col
)
125 fun warning
(message
: String, col
: nullable Int) do
126 errors
.add
new DocMessage(2, message
, col
)
130 # A message generated by the DocCommandParser
139 # Message explanatory string
142 # Related column in original string if any
143 var col
: nullable Int
146 var str
= new FlatBuffer
150 str
.append
"Warning: "
155 str
.append
" (col: {col})"
157 return str
.write_to_string
162 # Read `self` as raw text until `nend` and append it to the `out` buffer.
163 private fun read_until
(out
: FlatBuffer, start
: Int, nend
: Char...): Int do
165 while pos
< length
do
167 var end_reached
= false
174 if end_reached
then break
182 # A command aimed at a documentation tool like `nitdoc` or `nitx`.
184 # `DocCommand` are generally of the form `command: arg | opt1: val1, opt2: val2`.
185 abstract class DocCommand
187 # Original command string.
191 var name
: String is noinit
194 var arg
: String is noinit
, writable
197 var opts
= new HashMap[String, String] is writable
200 if opts
.is_empty
then
201 return "{name}: {arg}"
203 return "{name}: {arg} | {opts.join(", ", ": ")}"
207 # A `DocCommand` that includes the documentation article of a `MEntity`.
209 # Syntax: `doc: MEntity::name`.
213 redef var name
= "doc"
216 # A `DocCommand` that includes a list of something.
218 # Syntax: `list:kind: <arg>`.
222 redef var name
= "list"
225 # A `DocCommand` that includes the list of methods tanking a `MType` as parameter.
227 # Syntax: `param: MType`.
231 redef var name
= "param"
234 # A `DocCommand` that includes the list of methods returning a `MType` as parameter.
236 # Syntax: `return: MType`.
240 redef var name
= "return"
243 # A `DocCommand` that includes the list of methods creating new instances of a specific `MType`
245 # Syntax: `new: MType`.
249 redef var name
= "new"
252 # A `DocCommand` that includes the list of methods calling a specific `MProperty`.
254 # Syntax: `call: MEntity::name`.
258 redef var name
= "call"
261 # A `DocCommand` that includes the source code of a `MEntity`.
264 # * `code: MEntity::name`
265 # * `./src/file.nit` to include source code from a file.
266 # * `./src/file.nit:1,2--3,4` to select code between positions.
270 redef var name
= "code"
273 # A `DocCommand` that display an graph for a `MEntity`.
276 # * `graph: MEntity::name`
280 redef var name
= "graph"