Skip to content

Commit 60b9be9

Browse files
authored
Add struct expression (#25)
1 parent a7dcd8d commit 60b9be9

25 files changed

+13063
-7369
lines changed

.tree-sitter-config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"directories": [
3+
"."
4+
]
5+
}

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "tree-sitter-inference"
33
description = "Inference grammar for tree-sitter"
4-
version = "0.0.32"
4+
version = "0.0.33"
55
authors = [
66
"Georgii Plotnikov <[email protected]>"
77
]

Makefile

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

debug.inf

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
fn foo() {
2-
assume {
3-
let x: u32 = @;
4-
forall {
5-
let y: u32 = @;
6-
foobar(param1 : @, param2: 5);
7-
///<do some checking for x and y>
8-
}
1+
fn type_check(exprs : [Expr]) -> () {
2+
let env : Binding = Binding { a: "", b: 0, c: [] };
3+
let mut i : i32 = 0;
4+
loop exprs.len {
5+
check_expr(exprs[i], env);
6+
i = i + 1;
97
}
108
}

grammar.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ module.exports = grammar({
4747

4848
extras: $ => [
4949
/\s/,
50-
$._comment,
50+
$.comment,
5151
],
5252

5353
rules: {
@@ -159,6 +159,7 @@ module.exports = grammar({
159159
$._literal,
160160
$.binary_expression,
161161
$.function_call_expression,
162+
$.struct_expression,
162163
$.prefix_unary_expression,
163164
$.parenthesized_expression,
164165
$.uzumaki_keyword
@@ -189,10 +190,19 @@ module.exports = grammar({
189190
field('function', $._lval_expression),
190191
optional(field('type_parameters', alias($.type_argument_list, $.type_parameters))),
191192
'(',
192-
optional(sep1(seq(optional(seq(field('argument_name', $._name), ':')), field('argument', $._expression)), ',')),
193+
optional(sep1(seq(optional(seq(field('argument_name', $._name), $._typedef_symbol)), field('argument', $._expression)), ',')),
193194
')',
194195
)),
195196

197+
struct_expression: $ => seq(
198+
field('name', $._name),
199+
$._lcb_symbol,
200+
optional(sep1(
201+
seq(field('field_name', $._name), $._typedef_symbol, field('field_value', $._expression)),
202+
$._comma_symbol)),
203+
$._rcb_symbol,
204+
),
205+
196206
expression_statement: $ => seq(
197207
$._expression,
198208
$._terminal_symbol
@@ -299,11 +309,11 @@ module.exports = grammar({
299309

300310
struct_definition: $ => seq(
301311
'struct',
302-
field('struct_name', $.identifier),
312+
field('name', $.identifier),
303313
$._lcb_symbol,
304314
repeat(choice(
305315
seq(field('field', $.struct_field), ';'),
306-
field('method', $.function_definition),
316+
field('value', $.function_definition),
307317
)),
308318
$._rcb_symbol,
309319
),
@@ -485,7 +495,7 @@ module.exports = grammar({
485495

486496
string_literal: $ => seq(
487497
'"',
488-
$._string_literal_content,
498+
optional($._string_literal_content),
489499
'"',
490500
),
491501

@@ -497,10 +507,10 @@ module.exports = grammar({
497507

498508
array_literal: $ => seq(
499509
'[',
500-
sep1(
510+
optional(sep1(
501511
$._expression,
502512
',',
503-
),
513+
)),
504514
']',
505515
),
506516

@@ -561,6 +571,7 @@ module.exports = grammar({
561571
$._reserved_identifier,
562572
),
563573

564-
_comment: _ => token(seq('///', /[^\n\r]*/)),
574+
// Comments start with '///'
575+
comment: _ => token(seq('///', /[^\n\r]*/)),
565576
},
566577
});

highlight.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/usr/bin/env node
2+
3+
// Simple regex-based syntax highlighter for Inference language
4+
const fs = require('fs');
5+
const path = require('path');
6+
7+
const args = process.argv.slice(2);
8+
if (args.length !== 1) {
9+
console.error(`Usage: node ${path.basename(process.argv[1])} <file.inf>`);
10+
process.exit(1);
11+
}
12+
const file = args[0];
13+
let src;
14+
try {
15+
src = fs.readFileSync(file, 'utf8');
16+
} catch (e) {
17+
console.error(`Error reading file ${file}:`, e.message);
18+
process.exit(1);
19+
}
20+
21+
// Escape HTML
22+
function escapeHtml(s) {
23+
return s.replace(/&/g, '&amp;')
24+
.replace(/</g, '&lt;')
25+
.replace(/>/g, '&gt;');
26+
}
27+
28+
// Define token patterns and classes
29+
const patterns = [
30+
{cls: 'comment', re: /^\/\/\/.*(?:\r?\n|$)/},
31+
{cls: 'string', re: /^"(?:\\.|[^"\\])*"/},
32+
{cls: 'type', re: /^(?:\b(?:i8|i16|i32|i64|u8|u16|u32|u64|bool)\b|\(\))/},
33+
{cls: 'keyword', re: /^(?:\b(?:fn|forall|exists|assume|unique|loop|if|else|break|return|let|const|type|enum|struct|use|spec|external)\b)/},
34+
{cls: 'boolean', re: /^(?:\b(?:true|false)\b)/},
35+
{cls: 'number', re: /^-?\d+(?:\.\d+)?/},
36+
{cls: 'operator', re: /^(?:->|::|\*\*|==|!=|<=|>=|&&|\|\||<<|>>|[=+\-*/%&|^<>])/},
37+
{cls: 'punctuation', re: /^[{}\[\]();,]/},
38+
{cls: 'identifier', re: /^\b[A-Za-z_]\w*\b/},
39+
{cls: 'whitespace', re: /^\s+/},
40+
{cls: 'text', re: /^./}
41+
];
42+
43+
// Highlight
44+
let out = '';
45+
let pos = 0;
46+
while (pos < src.length) {
47+
let matched = false;
48+
for (const {cls, re} of patterns) {
49+
const m = re.exec(src.slice(pos));
50+
if (!m) continue;
51+
const tok = m[0];
52+
const esc = escapeHtml(tok);
53+
if (cls === 'whitespace' || cls === 'text') {
54+
out += esc;
55+
} else {
56+
out += `<span class="${cls}">${esc}</span>`;
57+
}
58+
pos += tok.length;
59+
matched = true;
60+
break;
61+
}
62+
if (!matched) { out += escapeHtml(src[pos]); pos++; }
63+
}
64+
65+
// Wrap in pre/code
66+
process.stdout.write('<pre><code>' + out + '</code></pre>');

index.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const path = require('path');
2+
const binding = require('./bindings/node');
3+
// Load node type information (prefer the generated src/node-types.json)
4+
let staticData;
5+
try {
6+
staticData = require(path.join(__dirname, 'src', 'node-types.json'));
7+
} catch (e) {
8+
try {
9+
staticData = require(path.join(__dirname, 'node-types.json'));
10+
} catch {
11+
staticData = [];
12+
}
13+
}
14+
15+
// Attach the two properties that tree-sitter-highlight needs
16+
// Expose node type names and types for tree-sitter-highlight (if used)
17+
binding.nodeTypeNamesById = Array.isArray(staticData) ? staticData.map(e => e.type) : [];
18+
binding.types = staticData;
19+
// Prevent tree-sitter JS from re-initializing node subclasses (avoids version checks)
20+
binding.nodeSubclasses = [];
21+
22+
// Export the binding object (with .language) so tree-sitter JS can unwrap it properly
23+
module.exports = binding;

0 commit comments

Comments
 (0)