Skip to content

Instantly share code, notes, and snippets.

@somebody1234
Created May 4, 2019 14:22
Show Gist options
  • Save somebody1234/88b8d71c3461c5a56aa72ca2cc9b86db to your computer and use it in GitHub Desktop.
Save somebody1234/88b8d71c3461c5a56aa72ca2cc9b86db to your computer and use it in GitHub Desktop.
vscode-snippet-parser
/**
* SnippetParser.re
*
* Module for parsing snippets???
*/
open CharCode;
module TokenType = {
let dollar = 0;
let colon = 1;
let comma = 2;
let curlyOpen = 4;
let curlyClose = 5;
let backslash = 6;
let forwardslash = 7;
let pipe = 8;
let int = 9;
let variableName = 10;
let format = 11;
let plus = 12;
let dash = 13;
let questionMark = 14;
let EOF = 15;
};
module Token = {
type t = {
/* originally called `type` but that's a keyword */
tokenType: int,
pos: int,
len: int
};
};
/* TODO: make this actually ok */
module Scanner = {
/* private static */
let _table = (ch: int) => {
if (ch < 255) {
switch (char_of_int(ch)) {
| '$' => Some(TokenType.dollar)
| ':' => Some(TokenType.colon)
| ',' => Some(TokenType.comma)
| '{' => Some(TokenType.curlyOpen)
| '}' => Some(TokenType.curlyClose)
| int_of_char('\\') => Some(TokenType.backslash)
| '/' => Some(TokenType.forwardslash)
| '|' => Some(TokenType.pipe)
| '+' => Some(TokenType.plus)
| '-' => Some(TokenType.dash)
| '?' => Some(TokenType.questionMark)
| _ => None
};
} else {
None;
};
};
let isDigitCharacter = (ch: int) => {
ch >= int_of_char('0') && ch <= int_of_char('9')
};
let isVariableCharacter = (ch: int) => {
ch === int_of_char('_')
|| (ch >= int_of_char('a') && ch <= int_of_char('z'))
|| (ch >= int_of_char('A') && ch <= int_of_char('Z'));
};
type t = {
value: string,
mutable pos: int
};
/* useless constructor? */
let text = (value: string) => {
{value, pos: 0};
};
let tokenText = (v: t, token: Token.t) => {
/* TODO: return a view instead of a copy? */
String.sub(v.value, token.pos, token.len)
};
let next = (v: t) => {
if (v.pos > String.length(v.value)) {
{type: TokenType.EOF, pos: this.pos, len: 0};
} else {
let pos = v.pos;
let len = v.len;
/* TODO: unicode */
let ch = v[pos];
let chlen = 1;
/* TODO: any way to declare type but not value? */
let optionType = ref(Some(0));
let type = ref(0);
/* static types */
type := Scanner._table(ch);
switch (type^) {
| Some(n) => {
v.pos = v.pos + 1;
{type, pos, len: 1};
}
| None => {
/* number */
if (Scanner.isDigitCharacter(ch)) {
type := TokenType.int;
let newLen = ref(len);
let newCh = ref(ch);
while (Scanner.isDigitCharacter(newCh^)) {
newLen := newLen^ + 1;
/* TODO: unicode */
newCh := v.value.[pos + newLen^];
}
v.pos = v.pos + newLen^;
return {type: type^, pos, len: newLen^};
}
/* variable name */
if (Scanner.isVariableCharacter(ch)) {
type := TokenType.variableName;
let newLen = ref(len);
let newCh = ref(ch);
while (Scanner.isVariableCharacter(ch) || Scanner.isDigitCharacter(newCh^)) {
newLen := newLen^ + 1;
/* TODO: unicode */
newCh := v.value.[pos + newLen^];
}
v.pos = v.pos + newLen^;
return {type: type^, pos, len: newLen^};
}
/* format */
type := TokenType.format;
/* TODO is the first iteration also guaranteed to meet the conditions */
let newLen = ref(len + 1);
/* TODO: unicode */
let newCh = v.value.[pos + newLen^];
/* TODO: isNaN */
while (
!isNaN(ch)
&& Scanner._table(ch) === None /* not static token */
&& !Scanner.isDigitCharacter(ch) /* not number */
&& !Scanner.isVariableCharacter(ch) /* not variable */
) {
let newLen = ref(len + 1);
let newCh = v.value.[pos + newLen^];
}
v.pos = v.pos + newLen^;
return {type: type^, pos, len: newLen^};
}
}
};
}
};
module Marker = {
type t = {
_markerBrand: int, /* TODO: uhh it's never actually used */
parent: marker,
_children: array(marker)
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment