|
|
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.IO;
- using System.Text.RegularExpressions;
-
- namespace SuperBASIC
- {
- class Parser
- {
-
- [Serializable]
- public class ParseException : Exception
- {
- public ParseException() { }
- public ParseException(string message) : base(message) { }
- public ParseException(string message, Exception inner) : base(message, inner) { }
- protected ParseException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
- }
-
- readonly Library library;
- readonly Runtime runtime;
- public Parser(Runtime rt)
- {
- runtime = rt;
- library = rt.lib;
- }
-
- public Bytecode ParseFile(string filepath)
- {
- Bytecode c = new Bytecode();
- string[] sourceLines = File.ReadAllLines(filepath);
- Regex lws = new Regex(@"\s+");
- Regex leadings = new Regex(@"^\s+");
- Regex trailings = new Regex(@"\s+$");
- List<string> codeLines = new List<string>();
- List<int> lineSpans = new List<int>();
-
- int a = 0;
- foreach (string line in sourceLines)
- {
- a++;
- string l = lws.Replace(line, " ");
- l = leadings.Replace(l, "");
- l = trailings.Replace(l, "");
-
- if(l != String.Empty)
- {
- lineSpans.Add(a);
- a = 0;
- codeLines.Add(l);
- }
- }
-
- for(int idx = 0; idx < codeLines.Count; idx++)
- {
- string line = codeLines[idx];
- var components = line.Split(' ');
-
- if(!library.nameResolution.ContainsKey(components[0]))
- {
- int lineIndex = 0;
- foreach (int cnt in lineSpans.GetRange(0, idx)) lineIndex += cnt;
- throw new ParseException($"Unknown operation \"{components[0]}\"\n\tat line {lineIndex}");
- }
-
- int opcode = library.nameResolution[components[0]];
- int arity = library.arities[opcode];
-
- if(arity != components.Length-1)
- {
- int lineIndex = 0;
- foreach (int cnt in lineSpans.GetRange(0, idx)) lineIndex += cnt;
- throw new ParseException($"Operation {components[0]} was provided with the wrong number of arguments\n\tExpected {arity} found {components.Length-1}\n\tat line {lineIndex}");
- }
-
- c.bytecode.Add(new BasicNumber(runtime, opcode));
- foreach (string elem in components.AsSpan(1))
- {
- if (elem != "$")
- {
- c.bytecode.Add(new BasicNumber(runtime, float.Parse(elem)));
- }
- else
- {
- c.bytecode.Add(new BasicNumber(runtime));
- }
- }
- }
-
- return c;
- }
- }
- }
|