/// <summary> /// Constructs a new <see cref="ByteCodeWriter"/> instance. /// </summary> /// <param name="lexer">The <see cref="LexicalAnalyzer"/> being used to parse /// the program.</param> public ByteCodeWriter(LexicalAnalyzer lexer) { // Bytecode size must not change (won't be able to read saved compiled data) Debug.Assert(sizeof(ByteCode) == sizeof(Int32)); ByteCodeEntries = new List <ByteCodeEntry>(); Counters = new List <int>(); Lexer = lexer ?? throw new ArgumentNullException(nameof(lexer)); Reset(); }
/// <summary> /// Constructs a new <see cref="Compiler"/> instance. /// </summary> public Compiler() { IntrinsicFunctions = new OrderedDictionary <string, IntrinsicFunction>(StringComparer.OrdinalIgnoreCase); IntrinsicVariables = new OrderedDictionary <string, Variable>(StringComparer.OrdinalIgnoreCase); MaxErrors = 45; CreateLogFile = false; LogFile = null; EnableLineNumbers = true; EnableInternalFunctions = true; Functions = new OrderedDictionary <string, Function>(StringComparer.OrdinalIgnoreCase); Variables = new OrderedDictionary <string, Variable>(StringComparer.OrdinalIgnoreCase); Literals = new List <Variable>(); Lexer = new LexicalAnalyzer(); Lexer.Error += Lexer_Error; Writer = new ByteCodeWriter(Lexer); Errors = new List <Error>(); }
/// <summary> /// Constructs a TextParse instance. /// </summary> /// <param name="text">Text to be parsed.</param> public LexicalHelper(LexicalAnalyzer lexer, string?text = null) { Lexer = lexer; Reset(text); }
public bool Compile(string path, out CompiledProgram program) { Functions = new OrderedDictionary <string, Function>(StringComparer.OrdinalIgnoreCase); Variables = new OrderedDictionary <string, Variable>(StringComparer.OrdinalIgnoreCase); Literals = new List <Variable>(); Lexer = new LexicalAnalyzer(this); Lexer.Error += Lexer_Error; Writer = new ByteCodeWriter(Lexer); InHeader = true; CurrentFunction = null; Errors = new List <Error>(); program = null; // Add intrinsic functions to function collection foreach (var function in IntrinsicFunctions.Values) { Functions.Add(function.Name, function); } // Add intrinsic variables to variable collection foreach (var pair in IntrinsicVariables.GetKeyValuePairs()) { Variables.Add(pair.Key, pair.Value); } // Add internal functions and variables if (EnableInternalFunctions) { InternalFunctions.AddInternalFunctionsAndVariables(Functions, Variables); } try { // Load file and initialize lexer Lexer.Reset(File.ReadAllText(path)); // Write bytecodes to call function main. // Also causes error if main function is not defined Writer.Write(ByteCode.ExecFunction, GetFunctionId(Function.Main)); // Parse statements while (ParseStatement()) { ; } // Verify end of file Token token = Lexer.GetNext(); if (token.Type != TokenType.EndOfFile) { Error(ErrorCode.UnexpectedToken, token); } // Check for undefined functions foreach (var funcInfo in Functions.GetKeyValuePairs()) { if (funcInfo.Value == null) { if (funcInfo.Key.Equals(Function.Main, StringComparison.CurrentCultureIgnoreCase)) { Error(ErrorCode.MainNotDefined, Function.Main.MakeQuoted()); } else { Error(ErrorCode.FunctionNotDefined, funcInfo.Key.MakeQuoted()); } } } } catch (TooManyErrorsException) { // Already handled } catch (Exception ex) { Error(ErrorCode.InternalError, ex.Message, ErrorLevel.FatalError); } // Done if compile failed if (Errors.Count > 0) { return(false); } // Implement logging if (CreateLogFile) { Writer.WriteLogFile(path, Path.ChangeExtension(path, "log")); } // Return compiled data program = new CompiledProgram { ByteCodes = Writer.GetBytecodes(), Functions = Functions.Values.Select(f => (f is CompileTimeUserFunction userFunction) ? new UserFunction(userFunction) : f).ToArray(), Variables = Variables.Values.ToArray(), Literals = Literals.ToArray(), LineNumbers = EnableLineNumbers ? Writer.GetLineNumbers() : null, }; return(true); }