Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .github/workflows/cs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,8 @@ jobs:
fail-fast: false
matrix:
include:
- { dotnet: 2.1.x, framework: netcoreapp2.1 }
- { dotnet: 2.2.x, framework: netcoreapp2.2 }
- { dotnet: 3.0.x, framework: netcoreapp3.0 }
- { dotnet: 3.1.x, framework: netcoreapp3.1 }
- { dotnet: 5.0.x, framework: net5.0 }
- { dotnet: 6.0.x, framework: net6.0 }
- { dotnet: 7.0.x, framework: net7.0 }
- { dotnet: 8.0.x, framework: net8.0 }
name: ${{ matrix.dotnet }}
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ test/cs/obj
test/java/target

.jekyll-cache

.vscode
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ test-all: test-java test-js test-python test-ruby
test-java: $(test_grammars:%.peg=%/Grammar.java)
cd test/java && mvn clean test

DOTNET_SDK?=netcoreapp3.1
DOTNET_SDK?=net6.0
test-cs: $(test_grammars:%.peg=%/Grammar.cs)
cd test/cs && dotnet test --framework ${DOTNET_SDK}

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Canopy

Canopy is a parser compiler targeting Java, JavaScript, Python and Ruby. It
Canopy is a parser compiler targeting C#, Java, JavaScript, Python and Ruby. It
takes a file describing a [parsing expression grammar][1] and compiles it into a
parser module in the target language. The generated parsers have no runtime
dependency on Canopy itself.
Expand Down
55 changes: 24 additions & 31 deletions src/builders/cs.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const Base = require('./base')

const TYPES = {
address: 'TreeNode',
chunk: 'String',
chunk: 'string',
elements: 'List<TreeNode>',
index: 'int',
max: 'int'
Expand Down Expand Up @@ -54,37 +54,36 @@ class Builder extends Base {
package_ (name, actions, block) {
this._grammarName = name

this._newBuffer('cs', 'Actions')
this._template('cs', 'Actions.cs', { actions, namespace: this._namespace })
let bufferName = name.replace(/\./g, '')
this._newBuffer('cs', bufferName)

this._newBuffer('cs', 'CacheRecord')
this._template('cs', 'CacheRecord.cs', { namespace: this._namespace })
// some pragmas to kill warnings
this.pragma("warning disable CS1717")

this._line('using System')
this._line('using System.Collections')
this._line('using System.Collections.Generic')
this._line('using System.Text.RegularExpressions')
this._newline()

this._line(`namespace ${this._namespace} {`, false)

this._template('cs', 'Actions.cs', { actions })
this._template('cs', 'CacheRecord.cs')

block()

this._line('}', false)
}

syntaxNodeClass_ () {
let name = 'TreeNode'

this._newBuffer('cs', name)
this._template('cs', 'TreeNode.cs', { name, namespace: this._namespace })
this._template('cs', 'TreeNode.cs', { name })

return name
}

grammarModule_ (block) {
this._newBuffer('cs', 'Grammar')

// some pragmas to kill warnings
this.pragma("warning disable CS1717")

this._line('using System')
this._line('using System.Collections')
this._line('using System.Collections.Generic')
this._line('using System.Text.RegularExpressions')
this._newline()

this._line('namespace ' + this._namespace + ' {', false)
this._indent(() => {
this._line('public abstract class Grammar {', false)
this._indent(() => {
Expand Down Expand Up @@ -112,8 +111,8 @@ class Builder extends Base {
this._newline()
block()
})
this._line('}',false)
})
this._line('}}', false)
}

compileRegex_ (charClass, name) {
Expand All @@ -125,29 +124,23 @@ class Builder extends Base {
}

parserClass_ (root) {
this._newBuffer('cs', 'ParseError')
this._template('cs', 'ParseError.cs', { namespace: this._namespace })

let grammar = this._quote(this._grammarName)
let name = this._grammarName.replace(/\./g, '')
this._newBuffer('cs', name)
this._template('cs', 'Parser.cs', { grammar, root, name, namespace: this._namespace })

let labels = [...this._labels].sort()
this._template('cs', 'Parser.cs', { grammar, root, name })
this._template('cs', 'ParseError.cs')

this._newBuffer('cs', 'Label')
this._template('cs', 'Label.cs', { labels, namespace: this._namespace })
let labels = [...this._labels].sort()
this._template('cs', 'Label.cs', { labels })
}

class_ (name, parent, block) {
this._newline()
this._line('namespace ' + this._namespace + ' {', false)
this._indent(() => {
this._line('class ' + name + ' : ' + parent + ' {', false)
this._scope(block, name)
this._line('}', false)
})
this._line('}', false)
}

constructor_ (args, block) {
Expand Down
2 changes: 1 addition & 1 deletion src/canopy.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const Compiler = require('./compiler')

module.exports = {
builders: {
cs: require('./builders/cs'),
java: require('./builders/java'),
cs: require('./builders/cs'),
javascript: require('./builders/javascript'),
python: require('./builders/python'),
ruby: require('./builders/ruby')
Expand Down
8 changes: 2 additions & 6 deletions templates/cs/Actions.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
using System.Collections.Generic;
using System;

namespace {{namespace}} {
public interface Actions {
{{#each actions}}
public TreeNode {{this}}(String input, int start, int end, List<TreeNode> elements);
public TreeNode {{this}}(string input, int start, int end, List<TreeNode> elements);
{{/each}}
}
}

3 changes: 0 additions & 3 deletions templates/cs/CacheRecord.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
namespace {{namespace}} {

public class CacheRecord {
public TreeNode node;
public int tail;
Expand All @@ -9,4 +7,3 @@ public CacheRecord(TreeNode node, int tail) {
this.tail = tail;
}
}
}
3 changes: 1 addition & 2 deletions templates/cs/Label.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace {{namespace}} {
public enum Label {
{{#each labels}}
{{this}}{{#unless @last}},{{/unless}}
{{/each}}
}
}

7 changes: 2 additions & 5 deletions templates/cs/ParseError.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using System;

namespace {{namespace}} {
public class ParseError : Exception {
public ParseError(String message) : base(message) {
public ParseError(string message) : base(message) {
}
}
}

28 changes: 11 additions & 17 deletions templates/cs/Parser.cs
Original file line number Diff line number Diff line change
@@ -1,45 +1,40 @@
using System.Collections.Generic;
using System.Collections;
using System;

namespace {{namespace}} {
public class {{name}} : Grammar {
public {{name}}(String input, Actions actions) {
public {{name}}(string input, Actions actions) {
this.input = input;
this.inputSize = input.Length;
this.actions = actions;
this.offset = 0;
this.cache = new Dictionary<Label, Dictionary<int, CacheRecord>>();
this.failure = 0;
this.expected = new List<String[]>();
this.expected = new List<string[]>();
}

public static TreeNode parse(String input, Actions actions) {
public static TreeNode parse(string input, Actions actions) {
{{name}} parser = new {{name}}(input, actions);
return parser.parse();
}

public static TreeNode parse(String input){
public static TreeNode parse(string input){
return parse(input, null);
}

private static String formatError(String input, int offset, List<String[]> expected) {
String[] lines = input.Split('\n');
private static string formatError(string input, int offset, List<string[]> expected) {
string[] lines = input.Split('\n');
int lineNo = 0, position = 0;

while (position <= offset) {
position += lines[lineNo].Length + 1;
lineNo += 1;
}

String line = lines[lineNo - 1];
String message = "Line " + lineNo + ": expected one of:\n\n";
string line = lines[lineNo - 1];
string message = "Line " + lineNo + ": expected one of:\n\n";

foreach (String[] pair in expected) {
foreach (string[] pair in expected) {
message += " - " + pair[1] + " from " + pair[0] + "\n";
}

String number = "" + lineNo;
string number = "" + lineNo;
while (number.Length < 6) number = " " + number;
message += "\n" + number + " | " + line + "\n";

Expand All @@ -59,9 +54,8 @@ private TreeNode parse(){
}
if (expected.Count <= 0) {
failure = offset;
expected.Add(new String[] { {{{grammar}}}, "<EOF>" });
expected.Add(new string[] { {{{grammar}}}, "<EOF>" });
}
throw new ParseError(formatError(input, failure, expected));
}
}
}
10 changes: 2 additions & 8 deletions templates/cs/TreeNode.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
using System.Collections.Generic;
using System.Collections;
using System;

namespace {{namespace}} {
public class {{name}} : IEnumerable<{{name}}> {
public String text;
public string text;
public int offset;
public List<{{name}}> elements;

public Dictionary<Label, {{name}}> labelled;

public {{name}}() : this("", -1, new List<{{name}}>(0)) {}

public {{name}}(String text, int offset, List<{{name}}> elements) {
public {{name}}(string text, int offset, List<{{name}}> elements) {
this.text = text;
this.offset = offset;
this.elements = elements;
Expand Down Expand Up @@ -41,4 +36,3 @@ IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
}
43 changes: 1 addition & 42 deletions test/cs/canopy.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;netstandard2.1;net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<IsPackable>false</IsPackable>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
Expand All @@ -12,52 +12,11 @@
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />

<Compile Include="../grammars/choices/Actions.cs" />
<Compile Include="../grammars/choices/CacheRecord.cs" />
<Compile Include="../grammars/choices/Grammar.cs" />
<Compile Include="../grammars/choices/Label.cs" />
<Compile Include="../grammars/choices/ParseError.cs" />
<Compile Include="../grammars/choices/TreeNode.cs" />
<Compile Include="../grammars/choices/Choices.cs" />

<Compile Include="../grammars/node_actions/Actions.cs" />
<Compile Include="../grammars/node_actions/CacheRecord.cs" />
<Compile Include="../grammars/node_actions/Grammar.cs" />
<Compile Include="../grammars/node_actions/Label.cs" />
<Compile Include="../grammars/node_actions/ParseError.cs" />
<Compile Include="../grammars/node_actions/TreeNode.cs" />
<Compile Include="../grammars/node_actions/NodeActions.cs" />

<Compile Include="../grammars/predicates/Actions.cs" />
<Compile Include="../grammars/predicates/CacheRecord.cs" />
<Compile Include="../grammars/predicates/Grammar.cs" />
<Compile Include="../grammars/predicates/Label.cs" />
<Compile Include="../grammars/predicates/ParseError.cs" />
<Compile Include="../grammars/predicates/TreeNode.cs" />
<Compile Include="../grammars/predicates/Predicates.cs" />

<Compile Include="../grammars/quantifiers/Actions.cs" />
<Compile Include="../grammars/quantifiers/CacheRecord.cs" />
<Compile Include="../grammars/quantifiers/Grammar.cs" />
<Compile Include="../grammars/quantifiers/Label.cs" />
<Compile Include="../grammars/quantifiers/ParseError.cs" />
<Compile Include="../grammars/quantifiers/TreeNode.cs" />
<Compile Include="../grammars/quantifiers/Quantifiers.cs" />

<Compile Include="../grammars/sequences/Actions.cs" />
<Compile Include="../grammars/sequences/CacheRecord.cs" />
<Compile Include="../grammars/sequences/Grammar.cs" />
<Compile Include="../grammars/sequences/Label.cs" />
<Compile Include="../grammars/sequences/ParseError.cs" />
<Compile Include="../grammars/sequences/TreeNode.cs" />
<Compile Include="../grammars/sequences/Sequences.cs" />

<Compile Include="../grammars/terminals/Actions.cs" />
<Compile Include="../grammars/terminals/CacheRecord.cs" />
<Compile Include="../grammars/terminals/Grammar.cs" />
<Compile Include="../grammars/terminals/Label.cs" />
<Compile Include="../grammars/terminals/ParseError.cs" />
<Compile Include="../grammars/terminals/TreeNode.cs" />
<Compile Include="../grammars/terminals/Terminals.cs" />

</ItemGroup>
Expand Down