///|
fn Cursor::identifier(self : Cursor) -> Node raise ParseFailure {
let start = self.index
if !is_id_start(self.current()) {
raise ParseFailure("E0004", [Some("a-zA-Z")])
}
ignore(self.next())
while is_id_char(self.current()) {
ignore(self.next())
}
Node::with_span(Identifier(self.slice(start, self.index)), start, self.index)
}
///|
fn Cursor::digits(self : Cursor) -> String raise ParseFailure {
let start = self.index
while is_digit(self.current()) {
ignore(self.next())
}
if self.index == start {
raise ParseFailure("E0004", [Some("0-9")])
}
self.slice(start, self.index)
}
///|
fn Cursor::number(self : Cursor) -> Node raise ParseFailure {
let start = self.index
if self.current() == Some('-') {
ignore(self.next())
}
ignore(self.digits())
if self.current() == Some('.') {
ignore(self.next())
ignore(self.digits())
}
Node::with_span(
NumberLiteral(self.slice(start, self.index)),
start,
self.index,
)
}
///|
fn Cursor::escape(self : Cursor) -> String raise ParseFailure {
match self.current() {
Some('\\') | Some('"') => {
let ch = self.current().unwrap()
ignore(self.next())
"\\" + ch.to_string()
}
Some('u') | Some('U') => {
let u = self.current().unwrap()
ignore(self.next())
let digits = if u == 'u' { 4 } else { 6 }
let buf = StringBuilder()
buf.write_char('\\')
buf.write_char(u)
for _ in 0.. c.to_string()
None => "None"
}
raise ParseFailure("E0026", [Some(buf.to_string() + last)])
}
buf.write_char(self.current().unwrap())
ignore(self.next())
}
buf.to_string()
}
ch => raise ParseFailure("E0025", [ch.map(c => c.to_string())])
}
}
///|
fn Cursor::string_literal(self : Cursor) -> Node raise ParseFailure {
let start = self.index
let buf = StringBuilder()
self.expect('"')
while true {
match self.current() {
Some('"') => {
ignore(self.next())
break
}
Some('\n') => raise ParseFailure("E0020", [])
None => {
self.expect('"')
break
}
Some('\\') => {
ignore(self.next())
buf.write_string(self.escape())
}
Some(ch) => {
buf.write_char(ch)
ignore(self.next())
}
}
}
Node::with_span(StringLiteral(buf.to_string()), start, self.index)
}
///|
fn Cursor::literal(self : Cursor) -> Node raise ParseFailure {
if self.is_number_start() {
return self.number()
}
if self.current() == Some('"') {
return self.string_literal()
}
raise ParseFailure("E0014", [])
}
///|
fn identifier_name(node : Node) -> String {
match node.kind {
Identifier(name) => name
_ => ""
}
}
///|
fn uppercase_function(name : String) -> Bool {
let chars = name.to_array()
if chars.is_empty() || chars[0] < 'A' || chars[0] > 'Z' {
return false
}
for c in chars {
if !((c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '_' ||
c == '-') {
return false
}
}
true
}