const KEYWORDS = [
  "let",
  "for",
  "print",
  "input",
  "//"
];

const TYPES = [
  "int",
  "float",
  "string",
  "bool"
];

const PATTERNS = [
  "asgn": [ "ident", "eq", "expr" ],
  "let": [ "type", "ident", "eq?", "expr" ],
];

class UnexpectedTokenError extends SyntaxError {
  constructor (expectedTokens, token, line, col) {
    const expected = expectedTokens.map((t) => `"${t}"`).join(", ");
    super(`Expected ${expected} but got ${token}`);
    this.lineNumber = line;
    this.columnNumber = col;
  }
}

class UnexpectedEndOfInputError {
  constructor (line, col) {
    super(`Unexpected end of input at ${line}:${col}.`);
  }
}

const inPath = Deno.args[0];
const dec = new TextDecoder("utf-8);
const raw = Deno.readFile(inPath);
const input = dec.decode(raw);

const lines = input.split("\n");

let tree = [];
let stack = [];
let ctx = "";

// keyword, ident, type, num, string, op, group, eof
let expectedTokens = ["keyword", "ident"];
let tokenType = null;
// ` `, `{`, `}`
let delim = " ";
let token = "";

let idents = [];

for (let line = 0; line < lines.length; line++) {
  const currentLine = lines[line];
  for (let col = 0; col < currentLine.length; col++) {
    if (currentLine[col] === delim) {
      tokenType = null;
      const tokenHandlers = {
	"keyword": () => {
	  if (KEYWORDS.includes(token)) {
	    stack.push(token);
	    tokenType = "keyword";
	  }
	},
	"ident": () => {
	  if (idents.includes(token)) {
	    stack.push(token);
	    idents.push(token);
	    tokenType = "ident";
	  }
	},
      };

      for (type in expectedTokens) {
	tokenHandlers[type]();
	if (tokenType !== null) {
	  break;
	}
      }

      if (!expectedTokens.includes(tokenType)) {
	throw new UnexpectedTokenError(expectedTokens, token, line, col);
      } else {
	switch (tokenType) {
	  case "keyword":
	    switch (token) {
	      case "let":
		ctx = patterns["let"];
		expectedToken = "ident";
		delim = " ";
		break;
	    }
	    break;
	  case "ident":
	  


    } else {
      token.push(line[j]);
    }

  switch (mode) {
    case "keyword": {
      const keyword = line.split(" ")[0];
      if (KEYWORDS.includes(keyword)) {
	stack.push(keyword);
      } else {
	throw new UnknownKeywordError(keyword, i, 0);



