491abdccf19889e5e41d6a2a5087042ae4be0212
1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
11 # S-Expression parsing facilities
14 intrude import parser_base
16 # Any S-Expression entity
17 abstract class SExpEntity
19 # Location in the source document
20 var location
: nullable Location
23 # A full S-Expression, delimited by `(` and `)`
28 var content
= new Array[SExpEntity]
30 redef fun to_s
do return "({content.join(" ")})"
32 # Returns a pretty-printable version of self
34 # assert "( ( sp 12.3 ) \"DQString\")".to_sexp.as(SExp).pretty_to_s == "(\n\t(\n\t\tsp\n\t\t12.30\n\t)\n\t\"DQString\"\n)"
35 fun pretty_to_s
: String do return recurse_to_s
(0)
37 private fun recurse_to_s
(depth
: Int): String do
38 var s
= "{"\t" * depth}(\n"
41 s
+= i
.recurse_to_s
(depth
+ 1)
45 s
+= "\t" * (depth
+ 1)
49 return s
+ "{"\t" * depth})"
53 # A Double-quoted String
57 # Double-quoted string
60 redef fun to_s
do return content
67 # Floating-point value
70 redef fun to_s
do return content
.to_precision
(2)
73 # Any Identifier, non string and non-float
77 # S-Exp compatible identifier
80 redef fun to_s
do return content
83 # An error parsing S-Expressions
90 redef fun to_s
do return "S-Expression error: {message} at {location or else "unknown location"}"
93 # S-Expression processor
97 # Parses an S-Expression entity
98 fun parse_entity
: SExpEntity do
99 var srclen
= src
.length
100 var delims
= once
['(', ')', '"']
102 if pos
>= srclen
then return new SExpError("Empty S-Expression", location
= new Location(line
, line_offset
))
104 if pos
>= srclen
then return new SExpError("Empty S-Expression")
107 var loc
= new Location(line
, line_offset
)
109 while pos
< srclen
and src
[pos
] != ')' do
111 if p
isa SExpError then break
115 if pos
< srclen
and src
[pos
] == ')' then
119 return new SExpError("Incomplete S-Expression", location
= loc
)
121 else if c
== '"' then
127 return new SExpDQString(src.substring(stdq, endq - stdq))
130 while pos < srclen and not c.is_whitespace and not delims.has(c) do
134 if delims.has(c) or c.is_whitespace then pos -= 1
135 if pos >= srclen then return new SExpError("Invalid S-Expression
")
137 var cntstr = src.substring(stid, endid - stid)
139 if cntstr.is_numeric then
140 cnt = new SExpFloat(cntstr.to_f)
142 cnt = new SExpId(cntstr)
151 # Tries to parse `self` as an S-Expression
152 fun to_sexp: SExpEntity do return (new SExpProcessor(self.to_s)).parse_entity