///|
fn unescape_step_escape(text : String, index : Int) -> (Char, Int)? {
match text.get_char(index) {
Some('\\') => Some(('\\', index + 1))
Some('"') => Some(('"', index + 1))
Some('n') => Some(('\n', index + 1))
Some('r') => Some(('\r', index + 1))
Some('t') => Some(('\t', index + 1))
Some('X') =>
if index + 3 < text.length() && text.get_char(index + 1) is Some('2') {
let hex = text[index + 2:index + 4].to_owned()
match parse_hex_byte(hex) {
Some(value) =>
match value.to_int().to_char() {
Some(character) => Some((character, index + 4))
None => None
}
None => None
}
} else {
None
}
_ => None
}
}
///|
fn parse_hex_digit(character : Char) -> Int? {
match character {
'0'..='9' => Some(character.to_int() - '0'.to_int())
'a'..='f' => Some(character.to_int() - 'a'.to_int() + 10)
'A'..='F' => Some(character.to_int() - 'A'.to_int() + 10)
_ => None
}
}
///|
fn parse_hex_byte(text : String) -> Byte? {
if text.length() != 2 {
return None
}
match (text.get_char(0), text.get_char(1)) {
(Some(a), Some(b)) =>
match (parse_hex_digit(a), parse_hex_digit(b)) {
(Some(high), Some(low)) => Some((high * 16 + low).to_byte())
_ => None
}
_ => None
}
}
///|
fn decode_step_string(text : String) -> String {
let output = StringBuilder()
let mut index = 0
for ;; {
match text.get_char(index) {
None => break
Some('\\') =>
match unescape_step_escape(text, index + 1) {
Some((character, next)) => {
output.write_char(character)
index = next
}
None => {
output.write_char('\\')
index += 1
}
}
Some(character) => {
output.write_char(character)
index += 1
}
}
}
output.to_string()
}
///|
fn parse_int64(
text : String,
position : SourcePosition,
) -> Int64 raise ParseError {
@strconv.from_str(text) catch {
_ => raise ParseError::InvalidNumber(position~, text~)
}
}
///|
fn parse_double(
text : String,
position : SourcePosition,
) -> Double raise ParseError {
@strconv.from_str(text) catch {
_ => raise ParseError::InvalidNumber(position~, text~)
}
}
///|
fn value_to_string(value : Value) -> String {
match value {
Null => "$".to_string()
Omitted => "*".to_string()
Integer(number) => number.to_string()
Real(number) => number.to_string()
String(text) => step_quote(text)
Enumeration(text) => "." + text + "."
Reference(id) => "#" + id.to_string()
Binary(text) => "\"" + text + "\""
Typed(name~, value~) => name + "(" + value_to_string(value) + ")"
List(values) => "(" + values.map(value_to_string).join(",") + ")"
}
}
///|
pub fn Value::to_step(self : Value) -> String {
value_to_string(self)
}