diff --git a/Source/.idea/.idea.Furesoft.PrattParser/.idea/.gitignore b/Source/.idea/.idea.Furesoft.PrattParser/.idea/.gitignore
deleted file mode 100644
index 20f1115..0000000
--- a/Source/.idea/.idea.Furesoft.PrattParser/.idea/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Rider ignored files
-/projectSettingsUpdater.xml
-/contentModel.xml
-/modules.xml
-/.idea.Furesoft.PrattParser.iml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/Source/.idea/.idea.Furesoft.PrattParser/.idea/.name b/Source/.idea/.idea.Furesoft.PrattParser/.idea/.name
deleted file mode 100644
index 2abca0e..0000000
--- a/Source/.idea/.idea.Furesoft.PrattParser/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-Furesoft.PrattParser
\ No newline at end of file
diff --git a/Source/.idea/.idea.Furesoft.PrattParser/.idea/encodings.xml b/Source/.idea/.idea.Furesoft.PrattParser/.idea/encodings.xml
deleted file mode 100644
index df87cf9..0000000
--- a/Source/.idea/.idea.Furesoft.PrattParser/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/Source/.idea/.idea.Furesoft.PrattParser/.idea/indexLayout.xml b/Source/.idea/.idea.Furesoft.PrattParser/.idea/indexLayout.xml
deleted file mode 100644
index 7b08163..0000000
--- a/Source/.idea/.idea.Furesoft.PrattParser/.idea/indexLayout.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Source/.idea/.idea.Furesoft.PrattParser/.idea/vcs.xml b/Source/.idea/.idea.Furesoft.PrattParser/.idea/vcs.xml
deleted file mode 100644
index 6c0b863..0000000
--- a/Source/.idea/.idea.Furesoft.PrattParser/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Source/Furesoft.PrattParser/Parser.DynamicHelper.cs b/Source/Furesoft.PrattParser/Parser.DynamicHelper.cs
new file mode 100644
index 0000000..e645bcd
--- /dev/null
+++ b/Source/Furesoft.PrattParser/Parser.DynamicHelper.cs
@@ -0,0 +1,130 @@
+
+using System.Collections.Generic;
+using Furesoft.PrattParser.Nodes;
+using Furesoft.PrattParser.Parselets;
+using Furesoft.PrattParser.Parselets.Builder;
+using Furesoft.PrattParser.Parselets.Builder.Elements;
+
+namespace Furesoft.PrattParser;
+
+public partial class Parser
+{
+ /// Add a dynamic parselet to parse an expression based on a declarative definition
+ public void ExprBuilder(SyntaxElement definition)
+ where TNode : AstNode
+ {
+ Builder(definition, NodeType.Expression);
+ }
+
+ /// Add a dynamic parselet to parse a statement based on a declarative definition
+ public void StmtBuilder(SyntaxElement definition)
+ where TNode : AstNode
+ {
+ Builder(definition, NodeType.Statement);
+ }
+
+ private static void GetKeywordsFromDefinition(SyntaxElement definition, List result)
+ {
+ if (definition is KeywordElement kw)
+ {
+ result.Add(kw.Keyword);
+
+ return;
+ }
+
+ if (definition is BinaryElement and)
+ {
+ GetKeywordsFromDefinition(and.First, result);
+ GetKeywordsFromDefinition(and.Second, result);
+ }
+ }
+
+ private static bool TryMatchUnaryOperatorKind(SyntaxElement definition, out TFirst first, out TSecond second)
+ {
+ if (definition is AndElement andElement)
+ {
+ if (andElement.First is TFirst firstElement && andElement.Second is TSecond secondElement)
+ {
+ first = firstElement;
+ second = secondElement;
+
+ return true;
+ }
+ }
+
+ first = default;
+ second = default;
+
+ return false;
+ }
+
+ protected void Operator(SyntaxElement definition, string precedenceName = null)
+ {
+ if (TryMatchUnaryOperatorKind(definition, out var prefixKw, out var prefixExpr))
+ {
+ _lexer.AddSymbol(prefixKw.Keyword);
+ Prefix(prefixKw.Keyword, precedenceName ?? "Prefix");
+ }
+ else if (TryMatchUnaryOperatorKind(definition, out var postfixExpr, out var postfixKw))
+ {
+ _lexer.AddSymbol(postfixKw.Keyword);
+ Postfix(postfixKw.Keyword, precedenceName ?? "Postfix");
+ }
+ }
+
+ private void Builder(SyntaxElement definition, NodeType type)
+ where TNode : AstNode
+ {
+ AddSymbolsFromBuilderToLexer(definition);
+
+ var parselet = new BuilderParselet(BindingPowers.Get("Product"), definition); //Todo: enable custom binding power
+
+ if (definition is AndElement andElement && andElement.First is KeywordElement kw && andElement.Second is ExprElement)
+ {
+ Prefix(kw.Keyword);
+ }
+
+ var recognitionKeywords = new List();
+ GetRecognitionKeywords(definition, recognitionKeywords);
+
+ foreach (var keyword in recognitionKeywords)
+ {
+ switch (type)
+ {
+ default:
+ case NodeType.Expression:
+ Register(keyword, (IPrefixParselet)parselet);
+ break;
+ case NodeType.Statement:
+ Register(keyword, (IStatementParselet)parselet);
+ break;
+ }
+ }
+ }
+
+ private void AddSymbolsFromBuilderToLexer(SyntaxElement definition)
+ {
+ var allSymbols = new List();
+ GetKeywordsFromDefinition(definition, allSymbols);
+
+ _lexer.AddSymbols([.. allSymbols]);
+ }
+
+ static void GetRecognitionKeywords(SyntaxElement element, List keywords)
+ {
+ if (element is KeywordElement keywordElement)
+ {
+ keywords.Add(keywordElement.Keyword);
+ }
+
+ if (element is AndElement and)
+ {
+ GetRecognitionKeywords(and.First, keywords);
+ }
+ else if (element is OrElement or)
+ {
+ GetRecognitionKeywords(or.First, keywords);
+ GetRecognitionKeywords(or.Second, keywords);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Furesoft.PrattParser/Parser.cs b/Source/Furesoft.PrattParser/Parser.cs
index 0ada12d..3c2fce1 100644
--- a/Source/Furesoft.PrattParser/Parser.cs
+++ b/Source/Furesoft.PrattParser/Parser.cs
@@ -61,125 +61,6 @@ public void Block(Symbol start, Symbol terminator, Symbol seperator = null, bool
Register(start, new BlockParselet(terminator, seperator, wrapExpressions));
}
- /// Add a dynamic parselet to parse an expression based on a declarative definition
- public void ExprBuilder(SyntaxElement definition)
- where TNode : AstNode
- {
- Builder(definition, NodeType.Expression);
- }
-
- /// Add a dynamic parselet to parse a statement based on a declarative definition
- public void StmtBuilder(SyntaxElement definition)
- where TNode : AstNode
- {
- Builder(definition, NodeType.Statement);
- }
-
- private static void GetKeywordsFromDefinition(SyntaxElement definition, List result)
- {
- if (definition is KeywordElement kw)
- {
- result.Add(kw.Keyword);
-
- return;
- }
-
- if (definition is BinaryElement and)
- {
- GetKeywordsFromDefinition(and.First, result);
- GetKeywordsFromDefinition(and.Second, result);
- }
- }
-
- private static bool TryMatchOperatorKind(SyntaxElement definition, out TFirst first, out TSecond second)
- {
- if (definition is AndElement andElement)
- {
- if (andElement.First is TFirst firstElement && andElement.Second is TSecond secondElement)
- {
- first = firstElement;
- second = secondElement;
-
- return true;
- }
- }
-
- first = default;
- second = default;
-
- return false;
- }
-
- protected void Operator(SyntaxElement definition, string precedenceName = null)
- {
- if (TryMatchOperatorKind(definition, out var prefixKw, out var prefixExpr))
- {
- _lexer.AddSymbol(prefixKw.Keyword);
- Prefix(prefixKw.Keyword, precedenceName ?? "Prefix");
- }
- else if (TryMatchOperatorKind(definition, out var postfixExpr, out var postfixKw))
- {
- _lexer.AddSymbol(postfixKw.Keyword);
- Postfix(postfixKw.Keyword, precedenceName ?? "Postfix");
- }
- }
-
- private void Builder(SyntaxElement definition, NodeType type)
- where TNode : AstNode
- {
- AddSymbolsFromBuilderToLexer(definition);
-
- var parselet = new BuilderParselet(BindingPowers.Get("Product"), definition); //Todo: enable custom binding power
-
- if (definition is AndElement andElement && andElement.First is KeywordElement kw && andElement.Second is ExprElement)
- {
- Prefix(kw.Keyword);
- }
-
- var recognitionKeywords = new List();
- GetRecognitionKeywords(definition, recognitionKeywords);
-
- foreach (var keyword in recognitionKeywords)
- {
- switch (type)
- {
- default:
- case NodeType.Expression:
- Register(keyword, (IPrefixParselet)parselet);
- break;
- case NodeType.Statement:
- Register(keyword, (IStatementParselet)parselet);
- break;
- }
- }
- }
-
- private void AddSymbolsFromBuilderToLexer(SyntaxElement definition)
- {
- var allSymbols = new List();
- GetKeywordsFromDefinition(definition, allSymbols);
-
- _lexer.AddSymbols([.. allSymbols]);
- }
-
- static void GetRecognitionKeywords(SyntaxElement element, List keywords)
- {
- if (element is KeywordElement keywordElement)
- {
- keywords.Add(keywordElement.Keyword);
- }
-
- if (element is AndElement and)
- {
- GetRecognitionKeywords(and.First, keywords);
- }
- else if (element is OrElement or)
- {
- GetRecognitionKeywords(or.First, keywords);
- GetRecognitionKeywords(or.Second, keywords);
- }
- }
-
public AstNode ParseStatement(bool wrapExpressions = false)
{
var token = LookAhead(0);