Fixed invalid characters in the identifier string. (Closes #7)
Some checks failed
continuous-integration/appveyor/branch AppVeyor build failed
Some checks failed
continuous-integration/appveyor/branch AppVeyor build failed
This commit is contained in:
parent
093b4455a6
commit
c9b9438519
@ -1,4 +1,7 @@
|
||||
using System;
|
||||
/* Dempsey-Jensen, Brychan, 14299890, Assignment 1, 159.341 */
|
||||
/* Parses and interprets a simple programming language line-by-line */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@ -9,7 +12,7 @@ namespace Assignment_1
|
||||
class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags to set object properties.
|
||||
/// Flags to set symbol properties
|
||||
/// </summary>
|
||||
[Flags]
|
||||
enum VariableFlags
|
||||
@ -17,27 +20,17 @@ namespace Assignment_1
|
||||
Empty = 0,
|
||||
Reserved = 1,
|
||||
NoPrint = 2,
|
||||
Static = 4,
|
||||
Undef = 8
|
||||
Static = 4
|
||||
}
|
||||
/// <summary>
|
||||
/// Characters that cannot appear in a normal string
|
||||
/// </summary>
|
||||
static readonly List<char> ForbiddenChars = new List<char>()
|
||||
{
|
||||
'$',
|
||||
'\\',
|
||||
'\"',
|
||||
'\''
|
||||
};
|
||||
static readonly int ConsoleWidthLimit = 80;
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("┌──────────────────────────────────────────┐");
|
||||
Console.WriteLine("│ 159.341 2021 Semester 1, Assignment 1 │");
|
||||
Console.WriteLine("│ Submitted by Brychan Dempsey, 14299890 │");
|
||||
Console.WriteLine("└──────────────────────────────────────────┘");
|
||||
// Parse the source from the memory stream
|
||||
Console.WriteLine(CenterString("┌──────────────────────────────────────────┐", ConsoleWidthLimit));
|
||||
Console.WriteLine(CenterString("│ 159.341 2021 Semester 1, Assignment 1 │", ConsoleWidthLimit));
|
||||
Console.WriteLine(CenterString("│ Submitted by Brychan Dempsey, 14299890 │", ConsoleWidthLimit));
|
||||
Console.WriteLine(CenterString("└──────────────────────────────────────────┘", ConsoleWidthLimit));
|
||||
bool loadedFromFile = false;
|
||||
bool exit = false;
|
||||
while (!exit)
|
||||
{
|
||||
@ -45,33 +38,29 @@ namespace Assignment_1
|
||||
Parser parser = new Parser();
|
||||
bool dynamicInput = false;
|
||||
// From https://stackoverflow.com/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected
|
||||
// Reading from pipes is equivalent to reading user input, though the input is redirected
|
||||
if (Console.IsInputRedirected)
|
||||
// Reading from pipes is equivalent to reading user input, but the input is redirected
|
||||
if (Console.IsInputRedirected || loadedFromFile)
|
||||
{
|
||||
// To simplify reading, we read all input bytes from the piped input to the stream.
|
||||
// Not the best way to do it; we don't need to keep any data that has already been read.
|
||||
// Whilst the stream could be copied excluding already parsed data at each input step, this would rely
|
||||
// on GC to cleanup afterwards
|
||||
// Not the best way to do it; we don't need to keep any data that has already been read and parsed successfully.
|
||||
sourceStream.Write(Encoding.UTF8.GetBytes(Console.In.ReadToEnd()));
|
||||
// Dispose will close a piped input, or piped file in further iterations of the program
|
||||
Console.In.Dispose();
|
||||
Console.SetIn(new StreamReader(Console.OpenStandardInput()));
|
||||
Console.OpenStandardInput();
|
||||
sourceStream.Position = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//sourceStream.Write(Encoding.UTF8.GetBytes("{ \r\n"));
|
||||
sourceStream.Position = 0;
|
||||
dynamicInput = true;
|
||||
}
|
||||
parser.StartParsing(sourceStream, dynamicInput);
|
||||
Console.WriteLine(Environment.NewLine + new string('─', 40));
|
||||
// Not strictly required, but could have problems if we try loading a large program immediately after unloading the last
|
||||
// NB: parser is out-of-scope from now
|
||||
GC.Collect();
|
||||
Console.WriteLine("\nProgram parsing complete.");
|
||||
if (dynamicInput == false)
|
||||
Console.WriteLine("\nProgram Parsed Successfully!");
|
||||
|
||||
if (Console.IsInputRedirected)
|
||||
{
|
||||
Thread.Sleep(2000);
|
||||
Thread.Sleep(3000);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
ConsoleKeyInfo ck = new ConsoleKeyInfo();
|
||||
@ -90,13 +79,14 @@ namespace Assignment_1
|
||||
ck = new ConsoleKeyInfo();
|
||||
while (ck.Key != ConsoleKey.Y && ck.Key != ConsoleKey.N)
|
||||
{
|
||||
Console.WriteLine("\nWould you like to pipe data from source file? Y/n:");
|
||||
Console.WriteLine("\nWould you like to pipe data from a source file? Y/n:");
|
||||
ck = Console.ReadKey(true);
|
||||
}
|
||||
if (ck.Key == ConsoleKey.N)
|
||||
{
|
||||
// Set the input to standard input stream
|
||||
Console.SetIn(Console.In);
|
||||
loadedFromFile = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -107,6 +97,7 @@ namespace Assignment_1
|
||||
try
|
||||
{
|
||||
Console.SetIn(File.OpenText(sourcePath));
|
||||
loadedFromFile = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -315,12 +306,17 @@ namespace Assignment_1
|
||||
{
|
||||
throw new ParserException("Key not found", 0, source.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Symbols.ContainsKey(key) && Symbols[key].Item2.HasFlag(VariableFlags.Reserved))
|
||||
else if (Symbols.ContainsKey(key) && Symbols[key].Item2.HasFlag(VariableFlags.Reserved))
|
||||
{
|
||||
throw new ParserException("Cannot assign a value to a reserved constant", 0, keyEndPos - (key.Length + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
int indx = Array.FindIndex(key.ToCharArray(), (c) => (c > 122 || c > 90 && c < 97 && c != '_' || c > 57 && c < 65 || c < 48)); // If the overall result is good, move until one isn't
|
||||
if (indx > -1)
|
||||
{
|
||||
throw new ParserException(string.Format("Character \'{0}\' is not valid for an identifier",key[indx]), 0, keyEndPos-key.Length + indx);
|
||||
}
|
||||
source.Position = keyEndPos;
|
||||
}
|
||||
return key;
|
||||
@ -377,13 +373,13 @@ namespace Assignment_1
|
||||
/// <param name="printUnprint">List values normally excluded from printing</param>
|
||||
Action List(bool printUnprint = false)
|
||||
{
|
||||
int keyWidth = 21;
|
||||
int valueWidth = 50;
|
||||
int flagWidth = 9;
|
||||
int flagWidth = Math.Max(Enum.GetNames(typeof(VariableFlags)).Length, "Flags".Length);
|
||||
int keyWidth = (int)((ConsoleWidthLimit - flagWidth) * 0.2); // 20% - flag width
|
||||
int valueWidth = (int)((ConsoleWidthLimit - flagWidth) * 0.8); // 80% - flag width
|
||||
|
||||
StringBuilder consoleOutput = new StringBuilder();
|
||||
consoleOutput.Append(string.Format("┌" + new string('─', keyWidth) + "┬" + new string('─', valueWidth) + "┬" + new string('─', flagWidth) + "┐\n"));
|
||||
consoleOutput.Append(string.Format("│{0}│{1}│{2}│\n", CenterString("Symbol", keyWidth), CenterString("Value", valueWidth), CenterString("Flags", flagWidth)));
|
||||
// Figure out how many symbols are eligible for printing
|
||||
List<string> eligibleKeys = new List<string>(Symbols.Count);
|
||||
foreach (var item in Symbols.Keys)
|
||||
{
|
||||
@ -392,7 +388,6 @@ namespace Assignment_1
|
||||
eligibleKeys.Add(item);
|
||||
}
|
||||
}
|
||||
// Control printing based on how many keys are available
|
||||
if (eligibleKeys.Count > 0)
|
||||
{
|
||||
consoleOutput.Append(string.Format("├" + new string('─', keyWidth) + "┼" + new string('─', valueWidth) + "┼" + new string('─', flagWidth) + "┤\n"));
|
||||
@ -404,7 +399,7 @@ namespace Assignment_1
|
||||
|
||||
for (int j = 0; j < (keyLines.Count > valueLines.Count ? keyLines.Count : valueLines.Count); j++)
|
||||
{
|
||||
consoleOutput.Append(string.Format(entryFormat, j >= keyLines.Count ? "" : keyLines[j], j >= valueLines.Count ? "" : valueLines[j], j == 0 ? Convert.ToString((byte)Symbols[eligibleKeys[i]].Item2, 2).PadLeft(8, '0'): ""));
|
||||
consoleOutput.Append(string.Format(entryFormat, j >= keyLines.Count ? "" : keyLines[j], j >= valueLines.Count ? "" : valueLines[j], j == 0 ? Convert.ToString((byte)Symbols[eligibleKeys[i]].Item2, 2).PadLeft(flagWidth, '0'): ""));
|
||||
}
|
||||
if (i + 1 < eligibleKeys.Count)
|
||||
{
|
||||
@ -413,12 +408,11 @@ namespace Assignment_1
|
||||
}
|
||||
}
|
||||
consoleOutput.Append(string.Format("└" + new string('─', keyWidth) + "┴" + new string('─', valueWidth) + "┴" + new string('─', flagWidth) + "┘\n"));
|
||||
|
||||
return () => Console.WriteLine(consoleOutput.ToString());
|
||||
}
|
||||
Action Exit(Stream source, long initialStreamLength, bool isDynamicInput=false)
|
||||
{
|
||||
Action exitAction = () =>
|
||||
void exitAction()
|
||||
{
|
||||
if (source.Length != initialStreamLength && isDynamicInput)
|
||||
{
|
||||
@ -436,8 +430,6 @@ namespace Assignment_1
|
||||
if (path != "")
|
||||
{
|
||||
path = Path.Combine(Environment.CurrentDirectory, path);
|
||||
// insert the final closing bracket
|
||||
//source.WriteByte((byte)'}');
|
||||
source.Position = 0;
|
||||
using (FileStream fs = File.OpenWrite(path))
|
||||
{
|
||||
@ -447,7 +439,7 @@ namespace Assignment_1
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return exitAction;
|
||||
}
|
||||
Action Print(Stream source, int mode = 0)
|
||||
@ -520,7 +512,6 @@ namespace Assignment_1
|
||||
}
|
||||
#endregion
|
||||
#region Data Handling
|
||||
// Data Handling
|
||||
/// <summary>
|
||||
/// Parses & evaluates the expression from the stream, moving the stream to the end of the last value
|
||||
/// </summary>
|
||||
@ -612,12 +603,12 @@ namespace Assignment_1
|
||||
}
|
||||
}
|
||||
|
||||
long FindIdentifier(Stream s, out string returnedKey)
|
||||
static long FindIdentifier(Stream s, out string returnedKey)
|
||||
{
|
||||
long wordEnd = FindNextWord(s, out returnedKey);
|
||||
return wordEnd;
|
||||
}
|
||||
long FindExistingIdentifier(Stream s, out string returnedKey)
|
||||
static long FindExistingIdentifier(Stream s, out string returnedKey)
|
||||
{
|
||||
long wordEnd = FindNextWord(s, out string identifier);
|
||||
if (identifier.Length > 1 && identifier.EndsWith(';'))
|
||||
@ -638,7 +629,7 @@ namespace Assignment_1
|
||||
/// <param name="s"></param>
|
||||
/// <param name="returnedLiteral"></param>
|
||||
/// <returns></returns>
|
||||
long FindLiteral(Stream s, out string returnedLiteral)
|
||||
static long FindLiteral(Stream s, out string returnedLiteral)
|
||||
{
|
||||
long pos = s.Position;
|
||||
// Is a literal. Now we must parse until we find the end of the literal
|
||||
|
@ -51,5 +51,5 @@ Would output:
|
||||
## Additional Parameters | Behaviours
|
||||
* The option `list;` may be augmented with the parameter `all` (i.e. `list all;`), which will additionally list the constant/global symbols.
|
||||
* It is possible to save the command list on `exit;`; this is prompted and guided.
|
||||
* The program instances its operation; at `exit;` you will have the option to load a new file or write a new program
|
||||
* A quick help option is available by using the command `h` (semi-colon not required)
|
||||
* The program instances its operation; at `exit;` you will have the option to load a new file or write a new program.
|
||||
* A quick help option is available by using the command `h` (semi-colon not required).
|
||||
|
Loading…
x
Reference in New Issue
Block a user