Add constructors to scanner, parser and parserTools (#3185)
* Add constructors to scanner, parser and parserTools Добавил конструкторы, чтобы код был почище * Change type of keywords in Scanner * Make cast explicit * Rebuild ABCPascal.cs
This commit is contained in:
parent
ca141804c7
commit
35c7bc5877
|
|
@ -25,7 +25,7 @@ namespace PascalABCCompiler.ParserTools
|
|||
}
|
||||
}
|
||||
|
||||
// Класс глобальных описаний и статических методов
|
||||
// Класс глобальных описаний и общих методов
|
||||
// для использования различными подсистемами парсера и сканера
|
||||
public abstract class BaseParserTools
|
||||
{
|
||||
|
|
@ -38,13 +38,21 @@ namespace PascalABCCompiler.ParserTools
|
|||
public string currentFileName;
|
||||
public List<compiler_directive> compilerDirectives;
|
||||
|
||||
public static Dictionary<string, string> tokenNum; // строки, соответствующие терминалам, для вывода ошибок - SSM
|
||||
public abstract Dictionary<string, string> TokenNum { get; protected set; } // строки, соответствующие терминалам, для вывода ошибок - SSM
|
||||
|
||||
public IParser ParserRef { get; private set; }
|
||||
public Dictionary<string, DirectiveInfo> ValidDirectives { get; private set; }
|
||||
|
||||
protected BaseParserTools(IParser parserRef)
|
||||
protected BaseParserTools(List<Error> errors, List<CompilerWarning> warnings,
|
||||
Dictionary<string, DirectiveInfo> validDirectives, bool buildTreeForFormatter, bool buildTreeForFormatterStrings,
|
||||
string currentFileName, List<compiler_directive> compilerDirectives)
|
||||
{
|
||||
this.ParserRef = parserRef;
|
||||
this.errors = errors;
|
||||
this.warnings = warnings;
|
||||
this.ValidDirectives = validDirectives;
|
||||
this.buildTreeForFormatter = buildTreeForFormatter;
|
||||
this.buildTreeForFormatterStrings = buildTreeForFormatterStrings;
|
||||
this.currentFileName = currentFileName;
|
||||
this.compilerDirectives = compilerDirectives;
|
||||
}
|
||||
|
||||
public SourceContext ToSourceContext(LexLocation loc)
|
||||
|
|
@ -57,8 +65,8 @@ namespace PascalABCCompiler.ParserTools
|
|||
public string ConvertToHumanName(string s)
|
||||
{
|
||||
var v = s;
|
||||
if (tokenNum.ContainsKey(v))
|
||||
v = tokenNum[v];
|
||||
if (TokenNum.ContainsKey(v))
|
||||
v = TokenNum[v];
|
||||
else if (v.StartsWith("tk"))
|
||||
v = v.Remove(0, 2).ToLower();
|
||||
|
||||
|
|
@ -204,7 +212,7 @@ namespace PascalABCCompiler.ParserTools
|
|||
string paramsString = directiveText.Substring(directiveText.IndexOf(directiveName) + directiveName.Length);
|
||||
|
||||
// если кавычки используются как специальные символы (для объединения нескольких слов в одно)
|
||||
if (ParserRef.ValidDirectives[directiveName].quotesAreSpecialSymbols)
|
||||
if (ValidDirectives[directiveName].quotesAreSpecialSymbols)
|
||||
{
|
||||
directiveParams = SplitDirectiveParamsWithQuotesAsSpecialSymbols(paramsString);
|
||||
}
|
||||
|
|
@ -229,7 +237,7 @@ namespace PascalABCCompiler.ParserTools
|
|||
}
|
||||
|
||||
// проверка имени директивы
|
||||
if (!ParserRef.ValidDirectives.ContainsKey(directiveName))
|
||||
if (!ValidDirectives.ContainsKey(directiveName))
|
||||
{
|
||||
AddErrorFromResource("UNKNOWN_DIRECTIVE{0}", location, directiveName);
|
||||
return;
|
||||
|
|
@ -246,7 +254,7 @@ namespace PascalABCCompiler.ParserTools
|
|||
/// </summary>
|
||||
public void ValidateDirectiveParams(string directiveName, List<string> directiveParams, SourceContext loc)
|
||||
{
|
||||
var directiveInfo = ParserRef.ValidDirectives[directiveName];
|
||||
var directiveInfo = ValidDirectives[directiveName];
|
||||
|
||||
if (directiveInfo.checkParamsNumNeeded)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -136,19 +136,25 @@ namespace Languages.Pascal.Frontend.Core
|
|||
|
||||
#region user code
|
||||
public PascalParserTools parserTools;
|
||||
private PascalABCCompiler.Parsers.BaseKeywords keywords;
|
||||
public PascalABCKeywords keywords;
|
||||
public List<string> Defines = new List<string>();
|
||||
private Stack<BufferContext> buffStack = new Stack<BufferContext>();
|
||||
private Stack<string> fNameStack = new Stack<string>();
|
||||
private Stack<bool> IfDefInElseBranch = new Stack<bool>();
|
||||
private Stack<string> IfDefVar = new Stack<string>();
|
||||
public List<string> Defines = new List<string>();
|
||||
private int IfExclude;
|
||||
private string Pars;
|
||||
private LexLocation currentLexLocation;
|
||||
private bool HiddenIdents = false;
|
||||
private bool ExprMode = false;
|
||||
|
||||
public Scanner(PascalABCCompiler.Parsers.BaseKeywords keywords) { this.keywords = keywords; }
|
||||
public Scanner(string text, PascalParserTools parserTools, PascalABCCompiler.Parsers.BaseKeywords keywords, List<string> defines = null)
|
||||
{
|
||||
this.parserTools = parserTools;
|
||||
this.keywords = (PascalABCKeywords)keywords;
|
||||
if (defines != null)
|
||||
this.Defines.AddRange(defines);
|
||||
SetSource(text, 0);
|
||||
}
|
||||
#endregion user code
|
||||
|
||||
int state;
|
||||
|
|
@ -2187,7 +2193,7 @@ if (parserTools.buildTreeForFormatter)
|
|||
parserTools.ParseDirective(yytext, CurrentLexLocation, out var directiveName, out var directiveParams);
|
||||
var orgDirectiveName = directiveName;
|
||||
|
||||
if (directiveName == "") // Ñ<EFBFBD>лÑ?Ñ?ай пÑ?Ñ<>Ñ?ой диÑ?екÑ?ивÑ?
|
||||
if (directiveName == "") // сл<EFBFBD>?<3F>?ай п<>?с<>?ой ди<D0B4>?ек<D0B5>?ив<D0B8>?
|
||||
break;
|
||||
|
||||
directiveName = directiveName.ToUpper();
|
||||
|
|
@ -2284,7 +2290,7 @@ BEGIN(INITIAL);
|
|||
parserTools.ParseDirective(yytext, CurrentLexLocation, out directiveName, out directiveParams);
|
||||
orgDirectiveName = directiveName;
|
||||
|
||||
if (directiveName == "") // Ñ<EFBFBD>лÑ?Ñ?ай пÑ?Ñ<>Ñ?ой диÑ?екÑ?ивÑ?
|
||||
if (directiveName == "") // сл<EFBFBD>?<3F>?ай п<>?с<>?ой ди<D0B4>?ек<D0B5>?ив<D0B8>?
|
||||
break;
|
||||
|
||||
directiveName = directiveName.ToUpper();
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
%{
|
||||
public PascalParserTools parserTools;
|
||||
private PascalABCCompiler.Parsers.BaseKeywords keywords;
|
||||
public PascalABCKeywords keywords;
|
||||
public List<string> Defines = new List<string>();
|
||||
private Stack<BufferContext> buffStack = new Stack<BufferContext>();
|
||||
private Stack<string> fNameStack = new Stack<string>();
|
||||
private Stack<bool> IfDefInElseBranch = new Stack<bool>();
|
||||
private Stack<string> IfDefVar = new Stack<string>();
|
||||
public List<string> Defines = new List<string>();
|
||||
private int IfExclude;
|
||||
private string Pars;
|
||||
private LexLocation currentLexLocation;
|
||||
private bool HiddenIdents = false;
|
||||
private bool ExprMode = false;
|
||||
|
||||
public Scanner(PascalABCCompiler.Parsers.BaseKeywords keywords) { this.keywords = keywords; }
|
||||
public Scanner(string text, PascalParserTools parserTools, PascalABCCompiler.Parsers.BaseKeywords keywords, List<string> defines = null)
|
||||
{
|
||||
this.parserTools = parserTools;
|
||||
this.keywords = (PascalABCKeywords)keywords;
|
||||
if (defines != null)
|
||||
this.Defines.AddRange(defines);
|
||||
SetSource(text, 0);
|
||||
}
|
||||
%}
|
||||
|
||||
%namespace Languages.Pascal.Frontend.Core
|
||||
|
|
|
|||
|
|
@ -7,11 +7,14 @@
|
|||
|
||||
public syntax_tree_node root; // Корневой узел синтаксического дерева
|
||||
|
||||
public int maxErrors = 10;
|
||||
public PascalParserTools parserTools;
|
||||
public ParserLambdaHelper lambdaHelper = new ParserLambdaHelper();
|
||||
// private int maxErrors = 10;
|
||||
private PascalParserTools parserTools;
|
||||
private ParserLambdaHelper lambdaHelper = new ParserLambdaHelper();
|
||||
|
||||
public GPPGParser(AbstractScanner<PascalABCCompiler.ParserTools.Union, LexLocation> scanner) : base(scanner) { }
|
||||
public GPPGParser(AbstractScanner<PascalABCCompiler.ParserTools.Union, LexLocation> scanner, PascalParserTools parserTools) : base(scanner)
|
||||
{
|
||||
this.parserTools = parserTools;
|
||||
}
|
||||
%}
|
||||
|
||||
%output=ABCPascalYacc.cs
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ using System.Collections.Generic;
|
|||
using PascalABCCompiler.SyntaxTree;
|
||||
using System.Linq;
|
||||
using PascalABCCompiler.ParserTools;
|
||||
using PascalABCCompiler.Parsers;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.Errors;
|
||||
using PascalABCCompiler.ParserTools.Directives;
|
||||
|
||||
namespace Languages.Pascal.Frontend.Core
|
||||
{
|
||||
|
|
@ -20,54 +20,62 @@ namespace Languages.Pascal.Frontend.Core
|
|||
public List<var_def_statement> pascalABCVarStatements;
|
||||
public List<type_declaration> pascalABCTypeDeclarations;
|
||||
|
||||
static PascalParserTools()
|
||||
public override Dictionary<string, string> TokenNum { get; protected set; }
|
||||
|
||||
private void InitializeTokenNum()
|
||||
{
|
||||
tokenNum = new Dictionary<string, string>();
|
||||
TokenNum = new Dictionary<string, string>()
|
||||
{
|
||||
["tkStatement"] = StringResources.Get("OPERATOR"),
|
||||
["tkExpression"] = StringResources.Get("EXPR"),
|
||||
["EOF"] = StringResources.Get("EOF1"),
|
||||
["tkIdentifier"] = StringResources.Get("TKIDENTIFIER"),
|
||||
["tkStringLiteral"] = StringResources.Get("TKSTRINGLITERAL"),
|
||||
["tkAmpersend"] = "'",
|
||||
["tkColon"] = "':'",
|
||||
["tkDotDot"] = "'..'",
|
||||
["tkPoint"] = "'.'",
|
||||
["tkRoundOpen"] = "'('",
|
||||
["tkRoundClose"] = "')'",
|
||||
["tkSemiColon"] = "','",
|
||||
["tkSquareOpen"] = "'['",
|
||||
["tkSquareClose"] = "']'",
|
||||
["tkQuestion"] = "'?'",
|
||||
|
||||
tokenNum["tkStatement"] = StringResources.Get("OPERATOR");
|
||||
tokenNum["tkExpression"] = StringResources.Get("EXPR");
|
||||
tokenNum["EOF"] = StringResources.Get("EOF1");
|
||||
tokenNum["tkIdentifier"] = StringResources.Get("TKIDENTIFIER");
|
||||
tokenNum["tkStringLiteral"] = StringResources.Get("TKSTRINGLITERAL");
|
||||
tokenNum["tkAmpersend"] = "'";
|
||||
tokenNum["tkColon"] = "':'";
|
||||
tokenNum["tkDotDot"] = "'..'";
|
||||
tokenNum["tkPoint"] = "'.'";
|
||||
tokenNum["tkRoundOpen"] = "'('";
|
||||
tokenNum["tkRoundClose"] = "')'";
|
||||
tokenNum["tkSemiColon"] = "';'";
|
||||
tokenNum["tkSquareOpen"] = "'['";
|
||||
tokenNum["tkSquareClose"] = "']'";
|
||||
tokenNum["tkQuestion"] = "'?'";
|
||||
|
||||
tokenNum["tkComma"] = "','";
|
||||
tokenNum["tkAssign"] = "':='";
|
||||
tokenNum["tkPlusEqual"] = "'+='";
|
||||
tokenNum["tkMinusEqual"] = "'-='";
|
||||
tokenNum["tkMultEqual"] = "'*='";
|
||||
tokenNum["tkDivEqual"] = "'/='";
|
||||
tokenNum["tkMinus"] = "'-'";
|
||||
tokenNum["tkPlus"] = "'+'";
|
||||
tokenNum["tkSlash"] = "'//'";
|
||||
tokenNum["tkStar"] = "'*'";
|
||||
tokenNum["tkEqual"] = "'='";
|
||||
tokenNum["tkGreater"] = "'>'";
|
||||
tokenNum["tkGreaterEqual"] = "'>='";
|
||||
tokenNum["tkLower"] = "'<'";
|
||||
tokenNum["tkLowerEqual"] = "'<='";
|
||||
tokenNum["tkNotEqual"] = "'<>'";
|
||||
tokenNum["tkArrow"] = "'->'";
|
||||
tokenNum["tkAddressOf"] = "'@'";
|
||||
tokenNum["tkDeref"] = "'^'";
|
||||
tokenNum["tkStarStar"] = "'**'";
|
||||
["tkComma"] = "','",
|
||||
["tkAssign"] = "':='",
|
||||
["tkPlusEqual"] = "'+='",
|
||||
["tkMinusEqual"] = "'-='",
|
||||
["tkMultEqual"] = "'*='",
|
||||
["tkDivEqual"] = "'/='",
|
||||
["tkMinus"] = "'-'",
|
||||
["tkPlus"] = "'+'",
|
||||
["tkSlash"] = "'//'",
|
||||
["tkStar"] = "'*'",
|
||||
["tkEqual"] = "'='",
|
||||
["tkGreater"] = "'>'",
|
||||
["tkGreaterEqual"] = "'>='",
|
||||
["tkLower"] = "'<'",
|
||||
["tkLowerEqual"] = "'<='",
|
||||
["tkNotEqual"] = "'<>'",
|
||||
["tkArrow"] = "'->'",
|
||||
["tkAddressOf"] = "'@'",
|
||||
["tkDeref"] = "'^'",
|
||||
["tkStarStar"] = "'**'"
|
||||
};
|
||||
}
|
||||
|
||||
public PascalParserTools(IParser parserRef) : base(parserRef)
|
||||
public PascalParserTools(List<Error> errors, List<CompilerWarning> warnings,
|
||||
Dictionary<string, DirectiveInfo> validDirectives, bool buildTreeForFormatter = false, bool buildTreeForFormatterStrings = false,
|
||||
string currentFileName = null, List<compiler_directive> compilerDirectives = null)
|
||||
: base(errors, warnings, validDirectives, buildTreeForFormatter, buildTreeForFormatterStrings, currentFileName, compilerDirectives)
|
||||
{
|
||||
NodesStack = new System.Collections.Stack();
|
||||
pascalABCLambdaDefinitions = new List<function_lambda_definition>();
|
||||
pascalABCVarStatements = new List<var_def_statement>();
|
||||
pascalABCTypeDeclarations = new List<type_declaration>();
|
||||
|
||||
InitializeTokenNum();
|
||||
}
|
||||
|
||||
protected override string ExtractDirectiveTextWithoutSpecialSymbols(string directive)
|
||||
|
|
|
|||
|
|
@ -63,11 +63,14 @@ public partial class GPPGParser: ShiftReduceParser<PascalABCCompiler.ParserTools
|
|||
|
||||
public syntax_tree_node root; // <20>?о<>?невой <20>?зел син<D0B8>?акси<D181>?еского де<D0B4>?ева
|
||||
|
||||
public int maxErrors = 10;
|
||||
public PascalParserTools parserTools;
|
||||
public ParserLambdaHelper lambdaHelper = new ParserLambdaHelper();
|
||||
// private int maxErrors = 10;
|
||||
private PascalParserTools parserTools;
|
||||
private ParserLambdaHelper lambdaHelper = new ParserLambdaHelper();
|
||||
|
||||
public GPPGParser(AbstractScanner<PascalABCCompiler.ParserTools.Union, LexLocation> scanner) : base(scanner) { }
|
||||
public GPPGParser(AbstractScanner<PascalABCCompiler.ParserTools.Union, LexLocation> scanner, PascalParserTools parserTools) : base(scanner)
|
||||
{
|
||||
this.parserTools = parserTools;
|
||||
}
|
||||
// End verbatim content from ABCPascal.y
|
||||
|
||||
#pragma warning disable 649
|
||||
|
|
|
|||
|
|
@ -150,22 +150,13 @@ namespace Languages.Pascal.Frontend.Wrapping
|
|||
#endif
|
||||
#endif
|
||||
|
||||
PascalParserTools parserTools = new PascalParserTools(this); // контекст сканера и парсера
|
||||
parserTools.errors = Errors;
|
||||
parserTools.warnings = Warnings;
|
||||
parserTools.compilerDirectives = CompilerDirectives;
|
||||
parserTools.currentFileName = Path.GetFullPath(fileName);
|
||||
PascalParserTools parserTools = new PascalParserTools(Errors, Warnings, ValidDirectives,
|
||||
buildTreeForFormatter, false,
|
||||
Path.GetFullPath(fileName), CompilerDirectives); // контекст сканера и парсера
|
||||
|
||||
Scanner scanner = new Scanner(Text, parserTools, Keywords, definesList);
|
||||
|
||||
Scanner scanner = new Scanner(Keywords);
|
||||
scanner.SetSource(Text, 0);
|
||||
scanner.parserTools = parserTools; // передали parserTools в объект сканера
|
||||
if (definesList != null)
|
||||
scanner.Defines.AddRange(definesList);
|
||||
|
||||
GPPGParser parser = new GPPGParser(scanner);
|
||||
parserTools.buildTreeForFormatter = buildTreeForFormatter;
|
||||
parser.parserTools = parserTools; // передали parserTools в объект парсера
|
||||
GPPGParser parser = new GPPGParser(scanner, parserTools);
|
||||
|
||||
if (!parser.Parse())
|
||||
if (Errors.Count == 0)
|
||||
|
|
|
|||
|
|
@ -396,27 +396,25 @@ namespace Languages.Pascal.Frontend.Core
|
|||
return lcl;
|
||||
}
|
||||
|
||||
public expression ParseExpression(string Text, int line, int col)
|
||||
/// <summary>
|
||||
/// Создает вторую версию парсера с целью применения части грамматики, связанной с нетерминалом expr.
|
||||
/// </summary>
|
||||
public expression ParseExpression(string Text)
|
||||
{
|
||||
PascalParserTools parserTools = new PascalParserTools(this.parserTools.ParserRef); // контекст сканера и парсера
|
||||
parserTools.errors = new List<Error>();
|
||||
parserTools.warnings = new List<CompilerWarning>();
|
||||
parserTools.currentFileName = System.IO.Path.GetFullPath(this.parserTools.currentFileName);
|
||||
parserTools.buildTreeForFormatterStrings = true;
|
||||
Scanner scanner = new Scanner(this.parserTools.ParserRef.Keywords);
|
||||
scanner.SetSource("<<expression>>"+Text, 0);
|
||||
scanner.parserTools = parserTools;// передали parserTools в объект сканера
|
||||
GPPGParser parser = new GPPGParser(scanner);
|
||||
parserTools.buildTreeForFormatter = false;
|
||||
parser.lambdaHelper = this.lambdaHelper;
|
||||
parser.parserTools = parserTools;
|
||||
PascalParserTools parserTools = new PascalParserTools(new List<Error>(), new List<CompilerWarning>(),
|
||||
this.parserTools.ValidDirectives, false, true, this.parserTools.currentFileName); // контекст сканера и парсера
|
||||
|
||||
Scanner scanner = new Scanner("<<expression>>" + Text, parserTools, ((Scanner)this.scanner).keywords);
|
||||
|
||||
GPPGParser parser = new GPPGParser(scanner, parserTools);
|
||||
parser.lambdaHelper = lambdaHelper;
|
||||
|
||||
if (!parser.Parse())
|
||||
if (parserTools.errors.Count == 0)
|
||||
parserTools.AddError("Неопознанная синтаксическая ошибка!", null);
|
||||
foreach (Error err in parserTools.errors)
|
||||
{
|
||||
this.parserTools.errors.Add(err);
|
||||
}
|
||||
|
||||
this.parserTools.errors.AddRange(parserTools.errors);
|
||||
|
||||
return parser.root as expression;
|
||||
}
|
||||
|
||||
|
|
@ -510,7 +508,10 @@ namespace Languages.Pascal.Frontend.Core
|
|||
for (int i = 0; i < vars.Count; i++)
|
||||
{
|
||||
string s = vars[i];
|
||||
var expr = ParseExpression(new string('\n', str.source_context.begin_position.line_num - 1) + new string(' ', str.source_context.begin_position.column_num + var_offsets[i] + 2) + s, str.source_context.begin_position.line_num, str.source_context.begin_position.column_num + var_offsets[i] + 2);
|
||||
|
||||
// Применяем здесь еще одну версию парсера вследствие ручной реализации разбора интерполированной строки
|
||||
var expr = ParseExpression(new string('\n', str.source_context.begin_position.line_num - 1) + new string(' ', str.source_context.begin_position.column_num + var_offsets[i] + 2) + s); //, str.source_context.begin_position.line_num, str.source_context.begin_position.column_num + var_offsets[i] + 2);
|
||||
|
||||
if (expr == null)
|
||||
{
|
||||
var err = parserTools.errors[0] as LocatedError;
|
||||
|
|
|
|||
Loading…
Reference in a new issue