bsnes/nall/string/eval/literal.hpp
Tim Allen 0b923489dd Update to 20160106 OS X Preview for Developers release.
byuu says:

New update. Most of the work today went into eliminating hiro::Image
from all objects in all ports, replacing with nall::image. That took an
eternity.

Changelog:
- fixed crashing bug when loading games [thanks endrift!!]
- toggling "show status bar" option adjusts window geometry (not
  supposed to recenter the window, though)
- button sizes improved; icon-only button icons no longer being cut off
2016-01-07 19:17:15 +11:00

100 lines
2.6 KiB
C++

#pragma once
namespace nall { namespace Eval {
inline auto isLiteral(const char*& s) -> bool {
char n = s[0];
return (n >= 'A' && n <= 'Z')
|| (n >= 'a' && n <= 'z')
|| (n >= '0' && n <= '9')
|| (n == '%' || n == '$' || n == '_' || n == '.')
|| (n == '\'' || n == '\"');
}
inline auto literalNumber(const char*& s) -> string {
const char* p = s;
//binary
if(p[0] == '%' || (p[0] == '0' && p[1] == 'b')) {
unsigned prefix = 1 + (p[0] == '0');
p += prefix;
while(p[0] == '\'' || p[0] == '0' || p[0] == '1') p++;
if(p - s <= prefix) throw "invalid binary literal";
string result = slice(s, 0, p - s);
s = p;
return result;
}
//octal
if(p[0] == '0' && p[1] == 'o') {
unsigned prefix = 1 + (p[0] == '0');
p += prefix;
while(p[0] == '\'' || (p[0] >= '0' && p[0] <= '7')) p++;
if(p - s <= prefix) throw "invalid octal literal";
string result = slice(s, 0, p - s);
s = p;
return result;
}
//hex
if(p[0] == '$' || (p[0] == '0' && p[1] == 'x')) {
unsigned prefix = 1 + (p[0] == '0');
p += prefix;
while(p[0] == '\'' || (p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F') || (p[0] >= 'a' && p[0] <= 'f')) p++;
if(p - s <= prefix) throw "invalid hex literal";
string result = slice(s, 0, p - s);
s = p;
return result;
}
//decimal
while(p[0] == '\'' || (p[0] >= '0' && p[0] <= '9')) p++;
if(p[0] != '.') {
string result = slice(s, 0, p - s);
s = p;
return result;
}
//floating-point
p++;
while(p[0] == '\'' || (p[0] >= '0' && p[0] <= '9')) p++;
string result = slice(s, 0, p - s);
s = p;
return result;
}
inline auto literalString(const char*& s) -> string {
const char* p = s;
char escape = *p++;
while(p[0] && p[0] != escape) p++;
if(*p++ != escape) throw "unclosed string literal";
string result = slice(s, 0, p - s);
s = p;
return result;
}
inline auto literalVariable(const char*& s) -> string {
const char* p = s;
while(p[0] == '_' || p[0] == '.' || (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || (p[0] >= '0' && p[0] <= '9')) p++;
string result = slice(s, 0, p - s);
s = p;
return result;
}
inline auto literal(const char*& s) -> string {
const char* p = s;
if(p[0] >= '0' && p[0] <= '9') return literalNumber(s);
if(p[0] == '%' || p[0] == '$') return literalNumber(s);
if(p[0] == '\'' || p[0] == '\"') return literalString(s);
if(p[0] == '_' || p[0] == '.' || (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) return literalVariable(s);
throw "invalid literal";
}
}}