yukigo-mini-parser 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/grammar.ne CHANGED
@@ -1,127 +1,132 @@
1
- @{%
2
- import { MiniLexer } from "./lexer.js"
3
- import {
4
- SimpleType,
5
- Assignment,
6
- Variable,
7
- ListPrimitive,
8
- ListType,
9
- ArithmeticBinaryOperation,
10
- SymbolPrimitive,
11
- NumberPrimitive,
12
- ComparisonOperation,
13
- BooleanPrimitive,
14
- StringPrimitive,
15
- ParameterizedType,
16
- Sequence,
17
- UnguardedBody,
18
- If,
19
- While,
20
- VariablePattern,
21
- Equation,
22
- Procedure,
23
- TypeSignature,
24
- CharPrimitive,
25
- NilPrimitive,
26
- Return
27
- } from "yukigo-ast"
28
- %}
29
-
30
- @preprocessor typescript
31
- @lexer MiniLexer
32
-
33
- program -> statement:+ _ %EOF {% (d) => d[0].flat(Infinity) %}
34
-
35
- # Statements
36
-
37
- statement -> (assignment | variable_statement | function_statement | return_statement | if_statement | while_statement) _ ";" _ {% (d) => d[0][0] %}
38
-
39
- variable_statement -> type __ variable (_ ":=" _ expression):? {% (d) => new Variable(d[2], d[3] ? d[3][3] : new NilPrimitive(null), d[0]) %}
40
-
41
- return_statement -> "return" _ expression {% (d) => new Return(d[2]) %}
42
-
43
- while_statement -> "while" _ condition _ statement_list {% d => new While(d[2], d[4]) %}
44
-
45
- if_statement -> "if" _ condition _ statement_list _ "else" _ statement_list {% d => new If(d[2], d[4], d[8]) %}
46
-
47
- condition -> "(" _ expression _ ")" {% (d) => d[2] %}
48
-
49
- statement_list -> "{" _ statement:* _ "}" {% d => new Sequence(d[2]) %}
50
-
51
- assignment -> variable _ ":=" _ expression {% (d) => new Assignment(d[0], d[4]) %}
52
-
53
- ## Function rules
54
-
55
- function_statement -> type __ variable ("(" _ param_list:? _ ")" _ "{" _ body _ "}") {% (d) => {
56
- const paramTypeList = []
57
- const patternList = []
58
- if(d[3][2]) {
59
- for(const [paramType, paramPattern] of d[3][2]) {
60
- paramTypeList.push(paramType);
61
- patternList.push(paramPattern);
62
- }
63
- }
64
- const signatureType = new ParameterizedType(paramTypeList, d[0], [])
65
-
66
- const signature = new TypeSignature(d[2], signatureType);
67
- const procedure = new Procedure(d[2], [new Equation(patternList, d[3][8])])
68
- return [signature, procedure]
69
- }%}
70
-
71
- param_list -> param (_ "," _ param):* {% d => [d[0], ...d[1].map(x => x[3])] %}
72
-
73
- param -> type __ variable {% d => [d[0], new VariablePattern(d[2])] %}
74
-
75
- body -> statement:* {% (d) => new UnguardedBody(new Sequence(d[0])) %}
76
-
77
- # Expressions
78
-
79
- expression -> comparison {% (d) => d[0] %}
80
-
81
- comparison ->
82
- addition _ comparison_operator _ addition {% (d) => new ComparisonOperation(d[2], d[0], d[4]) %}
83
- | addition {% (d) => d[0] %}
84
-
85
- addition ->
86
- addition _ "+" _ multiplication {% (d) => new ArithmeticBinaryOperation("Plus", d[0], d[4]) %}
87
- | addition _ "-" _ multiplication {% (d) => new ArithmeticBinaryOperation("Minus", d[0], d[4]) %}
88
- | multiplication {% (d) => d[0] %}
89
-
90
- multiplication ->
91
- multiplication _ "*" _ primary {% (d) => new ArithmeticBinaryOperation("Multiply", d[0], d[4]) %}
92
- | multiplication _ "/" _ primary {% (d) => new ArithmeticBinaryOperation("Divide", d[0], d[4]) %}
93
- | primary {% (d) => d[0] %}
94
-
95
- primary ->
96
- variable {% (d) => d[0] %}
97
- | "(" _ expression _ ")" {% (d) => d[2] %}
98
- | primitive {% (d) => d[0] %}
99
-
100
- primitive ->
101
- %number {% (d) => new NumberPrimitive(Number(d[0].value)) %}
102
- | %char {% (d) => new CharPrimitive(d[0].value) %}
103
- | %string {% (d) => new StringPrimitive(d[0].value) %}
104
- | %bool {% (d) => new BooleanPrimitive(d[0].value) %}
105
- | variable {% (d) => d[0] %}
106
- | list_primitive {% d => d[0] %}
107
-
108
- type ->
109
- variable {% (d) => new SimpleType(d[0].value, []) %}
110
- | type "[" "]" {% (d) => new ListType(d[0], []) %}
111
-
112
- list_primitive -> "[" _ expression_list _ "]" {% (d) => new ListPrimitive(d[2]) %}
113
-
114
- expression_list -> expression _ ("," _ expression _):* {% (d) => ([d[0], ...d[2].map(x => x[2])]) %}
115
-
116
- variable -> %variable {% (d) => new SymbolPrimitive(d[0].value) %}
117
-
118
- comparison_operator ->
119
- %equal {% d => "Equal" %}
120
- | %notEqual {% d => "NotEqual" %}
121
- | %lt {% d => "LessThan" %}
122
- | %lte {% d => "LessOrEqualThan" %}
123
- | %gt {% d => "GreaterThan" %}
124
- | %gte {% d => "GreaterOrEqualThan" %}
125
-
126
- _ -> %WS:* {% d => null %}
1
+ @{%
2
+ import { MiniLexer } from "./lexer.js"
3
+ import {
4
+ SimpleType,
5
+ Assignment,
6
+ Variable,
7
+ ListPrimitive,
8
+ ListType,
9
+ ArithmeticBinaryOperation,
10
+ SymbolPrimitive,
11
+ NumberPrimitive,
12
+ ComparisonOperation,
13
+ BooleanPrimitive,
14
+ StringPrimitive,
15
+ ParameterizedType,
16
+ Sequence,
17
+ UnguardedBody,
18
+ If,
19
+ While,
20
+ VariablePattern,
21
+ Equation,
22
+ Procedure,
23
+ TypeSignature,
24
+ CharPrimitive,
25
+ NilPrimitive,
26
+ Return
27
+ } from "yukigo-ast"
28
+ %}
29
+
30
+ @preprocessor typescript
31
+ @lexer MiniLexer
32
+
33
+ program -> _ statements _ %EOF {% (d) => d[1].flat(Infinity) %}
34
+
35
+ statements ->
36
+ statement {% (d) => [d[0]] %}
37
+ | statements _ statement {% (d) => [...d[0], d[2]] %}
38
+
39
+ # Statements
40
+
41
+ statement -> (assignment | variable_statement | function_statement | return_statement | if_statement | while_statement) _ ";" {% (d) => d[0][0] %}
42
+
43
+ variable_statement -> type __ variable (_ ":=" _ expression):? {% (d) => new Variable(d[2], d[3] ? d[3][3] : new NilPrimitive(null), d[0]) %}
44
+
45
+ return_statement -> "return" _ expression {% (d) => new Return(d[2]) %}
46
+
47
+ while_statement -> "while" _ condition _ statement_list {% d => new While(d[2], d[4]) %}
48
+
49
+ if_statement -> "if" _ condition _ statement_list _ "else" _ statement_list {% d => new If(d[2], d[4], d[8]) %}
50
+
51
+ condition -> "(" _ expression _ ")" {% (d) => d[2] %}
52
+
53
+ statement_list -> "{" _ body _ "}" {% d => d[2] %}
54
+ body ->
55
+ statements {% (d) => new Sequence(d[0].flat(Infinity)) %}
56
+ | null {% () => new Sequence([]) %}
57
+
58
+ assignment -> variable _ ":=" _ expression {% (d) => new Assignment(d[0], d[4]) %}
59
+
60
+ ## Function rules
61
+
62
+ function_statement -> type __ variable ("(" _ param_list:? _ ")" _ statement_list) {% (d) => {
63
+ const paramTypeList = []
64
+ const patternList = []
65
+ if(d[3][2]) {
66
+ for(const [paramType, paramPattern] of d[3][2]) {
67
+ paramTypeList.push(paramType);
68
+ patternList.push(paramPattern);
69
+ }
70
+ }
71
+ const signatureType = new ParameterizedType(paramTypeList, d[0], [])
72
+
73
+ const signature = new TypeSignature(d[2], signatureType);
74
+ const procedure = new Procedure(d[2], [new Equation(patternList, new UnguardedBody(d[3][6]))])
75
+ return [signature, procedure]
76
+ }%}
77
+
78
+ param_list -> param (_ "," _ param):* {% d => [d[0], ...d[1].map(x => x[3])] %}
79
+
80
+ param -> type __ variable {% d => [d[0], new VariablePattern(d[2])] %}
81
+
82
+
83
+ # Expressions
84
+
85
+ expression -> comparison {% (d) => d[0] %}
86
+
87
+ comparison ->
88
+ addition _ comparison_operator _ addition {% (d) => new ComparisonOperation(d[2], d[0], d[4]) %}
89
+ | addition {% (d) => d[0] %}
90
+
91
+ addition ->
92
+ addition _ "+" _ multiplication {% (d) => new ArithmeticBinaryOperation("Plus", d[0], d[4]) %}
93
+ | addition _ "-" _ multiplication {% (d) => new ArithmeticBinaryOperation("Minus", d[0], d[4]) %}
94
+ | multiplication {% (d) => d[0] %}
95
+
96
+ multiplication ->
97
+ multiplication _ "*" _ primary {% (d) => new ArithmeticBinaryOperation("Multiply", d[0], d[4]) %}
98
+ | multiplication _ "/" _ primary {% (d) => new ArithmeticBinaryOperation("Divide", d[0], d[4]) %}
99
+ | primary {% (d) => d[0] %}
100
+
101
+ primary ->
102
+ "(" _ expression _ ")" {% (d) => d[2] %}
103
+ | primitive {% (d) => d[0] %}
104
+
105
+ primitive ->
106
+ %number {% (d) => new NumberPrimitive(Number(d[0].value)) %}
107
+ | %char {% (d) => new CharPrimitive(d[0].value) %}
108
+ | %string {% (d) => new StringPrimitive(d[0].value) %}
109
+ | %bool {% (d) => new BooleanPrimitive(d[0].value) %}
110
+ | variable {% (d) => d[0] %}
111
+ | list_primitive {% d => d[0] %}
112
+
113
+ type ->
114
+ variable {% (d) => new SimpleType(d[0].value, []) %}
115
+ | type "[" "]" {% (d) => new ListType(d[0], []) %}
116
+
117
+ list_primitive -> "[" _ expression_list _ "]" {% (d) => new ListPrimitive(d[2]) %}
118
+
119
+ expression_list -> expression _ ("," _ expression):* {% (d) => ([d[0], ...d[2].map(x => x[2])]) %}
120
+
121
+ variable -> %variable {% (d) => new SymbolPrimitive(d[0].value) %}
122
+
123
+ comparison_operator ->
124
+ %equal {% d => "Equal" %}
125
+ | %notEqual {% d => "NotEqual" %}
126
+ | %lt {% d => "LessThan" %}
127
+ | %lte {% d => "LessOrEqualThan" %}
128
+ | %gt {% d => "GreaterThan" %}
129
+ | %gte {% d => "GreaterOrEqualThan" %}
130
+
131
+ _ -> %WS:* {% d => null %}
127
132
  __ -> %WS:+ {% d => null %}
package/src/grammar.ts CHANGED
@@ -74,16 +74,16 @@ interface Grammar {
74
74
  const grammar: Grammar = {
75
75
  Lexer: MiniLexer,
76
76
  ParserRules: [
77
- {"name": "program$ebnf$1", "symbols": ["statement"]},
78
- {"name": "program$ebnf$1", "symbols": ["program$ebnf$1", "statement"], "postprocess": (d) => d[0].concat([d[1]])},
79
- {"name": "program", "symbols": ["program$ebnf$1", "_", (MiniLexer.has("EOF") ? {type: "EOF"} : EOF)], "postprocess": (d) => d[0].flat(Infinity)},
77
+ {"name": "program", "symbols": ["_", "statements", "_", (MiniLexer.has("EOF") ? {type: "EOF"} : EOF)], "postprocess": (d) => d[1].flat(Infinity)},
78
+ {"name": "statements", "symbols": ["statement"], "postprocess": (d) => [d[0]]},
79
+ {"name": "statements", "symbols": ["statements", "_", "statement"], "postprocess": (d) => [...d[0], d[2]]},
80
80
  {"name": "statement$subexpression$1", "symbols": ["assignment"]},
81
81
  {"name": "statement$subexpression$1", "symbols": ["variable_statement"]},
82
82
  {"name": "statement$subexpression$1", "symbols": ["function_statement"]},
83
83
  {"name": "statement$subexpression$1", "symbols": ["return_statement"]},
84
84
  {"name": "statement$subexpression$1", "symbols": ["if_statement"]},
85
85
  {"name": "statement$subexpression$1", "symbols": ["while_statement"]},
86
- {"name": "statement", "symbols": ["statement$subexpression$1", "_", {"literal":";"}, "_"], "postprocess": (d) => d[0][0]},
86
+ {"name": "statement", "symbols": ["statement$subexpression$1", "_", {"literal":";"}], "postprocess": (d) => d[0][0]},
87
87
  {"name": "variable_statement$ebnf$1$subexpression$1", "symbols": ["_", {"literal":":="}, "_", "expression"]},
88
88
  {"name": "variable_statement$ebnf$1", "symbols": ["variable_statement$ebnf$1$subexpression$1"], "postprocess": id},
89
89
  {"name": "variable_statement$ebnf$1", "symbols": [], "postprocess": () => null},
@@ -92,13 +92,13 @@ const grammar: Grammar = {
92
92
  {"name": "while_statement", "symbols": [{"literal":"while"}, "_", "condition", "_", "statement_list"], "postprocess": d => new While(d[2], d[4])},
93
93
  {"name": "if_statement", "symbols": [{"literal":"if"}, "_", "condition", "_", "statement_list", "_", {"literal":"else"}, "_", "statement_list"], "postprocess": d => new If(d[2], d[4], d[8])},
94
94
  {"name": "condition", "symbols": [{"literal":"("}, "_", "expression", "_", {"literal":")"}], "postprocess": (d) => d[2]},
95
- {"name": "statement_list$ebnf$1", "symbols": []},
96
- {"name": "statement_list$ebnf$1", "symbols": ["statement_list$ebnf$1", "statement"], "postprocess": (d) => d[0].concat([d[1]])},
97
- {"name": "statement_list", "symbols": [{"literal":"{"}, "_", "statement_list$ebnf$1", "_", {"literal":"}"}], "postprocess": d => new Sequence(d[2])},
95
+ {"name": "statement_list", "symbols": [{"literal":"{"}, "_", "body", "_", {"literal":"}"}], "postprocess": d => d[2]},
96
+ {"name": "body", "symbols": ["statements"], "postprocess": (d) => new Sequence(d[0].flat(Infinity))},
97
+ {"name": "body", "symbols": [], "postprocess": () => new Sequence([])},
98
98
  {"name": "assignment", "symbols": ["variable", "_", {"literal":":="}, "_", "expression"], "postprocess": (d) => new Assignment(d[0], d[4])},
99
99
  {"name": "function_statement$subexpression$1$ebnf$1", "symbols": ["param_list"], "postprocess": id},
100
100
  {"name": "function_statement$subexpression$1$ebnf$1", "symbols": [], "postprocess": () => null},
101
- {"name": "function_statement$subexpression$1", "symbols": [{"literal":"("}, "_", "function_statement$subexpression$1$ebnf$1", "_", {"literal":")"}, "_", {"literal":"{"}, "_", "body", "_", {"literal":"}"}]},
101
+ {"name": "function_statement$subexpression$1", "symbols": [{"literal":"("}, "_", "function_statement$subexpression$1$ebnf$1", "_", {"literal":")"}, "_", "statement_list"]},
102
102
  {"name": "function_statement", "symbols": ["type", "__", "variable", "function_statement$subexpression$1"], "postprocess": (d) => {
103
103
  const paramTypeList = []
104
104
  const patternList = []
@@ -111,7 +111,7 @@ const grammar: Grammar = {
111
111
  const signatureType = new ParameterizedType(paramTypeList, d[0], [])
112
112
 
113
113
  const signature = new TypeSignature(d[2], signatureType);
114
- const procedure = new Procedure(d[2], [new Equation(patternList, d[3][8])])
114
+ const procedure = new Procedure(d[2], [new Equation(patternList, new UnguardedBody(d[3][6]))])
115
115
  return [signature, procedure]
116
116
  }},
117
117
  {"name": "param_list$ebnf$1", "symbols": []},
@@ -119,9 +119,6 @@ const grammar: Grammar = {
119
119
  {"name": "param_list$ebnf$1", "symbols": ["param_list$ebnf$1", "param_list$ebnf$1$subexpression$1"], "postprocess": (d) => d[0].concat([d[1]])},
120
120
  {"name": "param_list", "symbols": ["param", "param_list$ebnf$1"], "postprocess": d => [d[0], ...d[1].map(x => x[3])]},
121
121
  {"name": "param", "symbols": ["type", "__", "variable"], "postprocess": d => [d[0], new VariablePattern(d[2])]},
122
- {"name": "body$ebnf$1", "symbols": []},
123
- {"name": "body$ebnf$1", "symbols": ["body$ebnf$1", "statement"], "postprocess": (d) => d[0].concat([d[1]])},
124
- {"name": "body", "symbols": ["body$ebnf$1"], "postprocess": (d) => new UnguardedBody(new Sequence(d[0]))},
125
122
  {"name": "expression", "symbols": ["comparison"], "postprocess": (d) => d[0]},
126
123
  {"name": "comparison", "symbols": ["addition", "_", "comparison_operator", "_", "addition"], "postprocess": (d) => new ComparisonOperation(d[2], d[0], d[4])},
127
124
  {"name": "comparison", "symbols": ["addition"], "postprocess": (d) => d[0]},
@@ -131,7 +128,6 @@ const grammar: Grammar = {
131
128
  {"name": "multiplication", "symbols": ["multiplication", "_", {"literal":"*"}, "_", "primary"], "postprocess": (d) => new ArithmeticBinaryOperation("Multiply", d[0], d[4])},
132
129
  {"name": "multiplication", "symbols": ["multiplication", "_", {"literal":"/"}, "_", "primary"], "postprocess": (d) => new ArithmeticBinaryOperation("Divide", d[0], d[4])},
133
130
  {"name": "multiplication", "symbols": ["primary"], "postprocess": (d) => d[0]},
134
- {"name": "primary", "symbols": ["variable"], "postprocess": (d) => d[0]},
135
131
  {"name": "primary", "symbols": [{"literal":"("}, "_", "expression", "_", {"literal":")"}], "postprocess": (d) => d[2]},
136
132
  {"name": "primary", "symbols": ["primitive"], "postprocess": (d) => d[0]},
137
133
  {"name": "primitive", "symbols": [(MiniLexer.has("number") ? {type: "number"} : number)], "postprocess": (d) => new NumberPrimitive(Number(d[0].value))},
@@ -144,7 +140,7 @@ const grammar: Grammar = {
144
140
  {"name": "type", "symbols": ["type", {"literal":"["}, {"literal":"]"}], "postprocess": (d) => new ListType(d[0], [])},
145
141
  {"name": "list_primitive", "symbols": [{"literal":"["}, "_", "expression_list", "_", {"literal":"]"}], "postprocess": (d) => new ListPrimitive(d[2])},
146
142
  {"name": "expression_list$ebnf$1", "symbols": []},
147
- {"name": "expression_list$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "expression", "_"]},
143
+ {"name": "expression_list$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "expression"]},
148
144
  {"name": "expression_list$ebnf$1", "symbols": ["expression_list$ebnf$1", "expression_list$ebnf$1$subexpression$1"], "postprocess": (d) => d[0].concat([d[1]])},
149
145
  {"name": "expression_list", "symbols": ["expression", "_", "expression_list$ebnf$1"], "postprocess": (d) => ([d[0], ...d[2].map(x => x[2])])},
150
146
  {"name": "variable", "symbols": [(MiniLexer.has("variable") ? {type: "variable"} : variable)], "postprocess": (d) => new SymbolPrimitive(d[0].value)},
package/src/index.ts CHANGED
@@ -1,24 +1,39 @@
1
- import { YukigoParser } from "yukigo-ast";
2
- import nearley from "nearley";
3
- import grammar from "./grammar.js";
4
-
5
- export class YukigoMiniParser implements YukigoParser {
6
- public errors: string[] = [];
7
-
8
- public parse(code: string) {
9
- const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));
10
- try {
11
- parser.feed(code);
12
- parser.finish();
13
- } catch (error) {
14
- const token = error.token;
15
- const message = `Unexpected '${token.type}' token '${token.value}' at line ${token.line} col ${token.col}.`;
16
- this.errors.push(message)
17
- }
18
- const results = parser.results
19
- if(results.length > 1)
20
- throw Error(`Ambiguous grammar. The parser generated ${results.length} ASTs`)
21
-
22
- return results[0]
23
- }
24
- }
1
+ import { AST, Expression, YukigoParser } from "yukigo-ast";
2
+ import nearley from "nearley";
3
+ import grammar from "./grammar.js";
4
+ import { Token } from "moo";
5
+
6
+ class UnexpectedToken extends Error {
7
+ constructor(token: Token) {
8
+ super(
9
+ `Parser: Unexpected '${token.type}' token '${token.value}' at line ${token.line} col ${token.col}.`
10
+ );
11
+ }
12
+ }
13
+
14
+ export class YukigoMiniParser implements YukigoParser {
15
+ public errors: string[] = [];
16
+
17
+ public parse(code: string): AST {
18
+ return this.feedParser(code);
19
+ }
20
+ public parseExpression(code: string): Expression {
21
+ return this.feedParser(code);
22
+ }
23
+ private feedParser(code: string): any {
24
+ const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));
25
+ try {
26
+ parser.feed(code);
27
+ parser.finish();
28
+ } catch (error) {
29
+ if ("token" in error) throw new UnexpectedToken(error.token);
30
+ throw error
31
+ }
32
+ const results = parser.results;
33
+ if (results.length > 1)
34
+ throw Error(
35
+ `Ambiguous grammar. The parser generated ${results.length} ASTs`
36
+ );
37
+ return results[0];
38
+ }
39
+ }
package/src/lexer.ts CHANGED
@@ -1,49 +1,49 @@
1
- import moo from "moo";
2
- import { makeLexer } from "moo-ignore";
3
-
4
- const keywords = [
5
- "return",
6
- "if",
7
- "else"
8
- ]
9
-
10
- export const MiniLexerConfig = {
11
- EOF: "*__EOF__*",
12
- wildcard: "_",
13
- WS: /[ \t]+/,
14
- comment: /--.*?$|{-[\s\S]*?-}/,
15
- number:
16
- /0[xX][0-9a-fA-F]+|0[bB][01]+|0[oO][0-7]+|(?:\d*\.\d+|\d+)(?:[eE][+-]?\d+)?/,
17
- char: /'(?:\\['\\bfnrtv0]|\\u[0-9a-fA-F]{4}|[^'\\\n\r])?'/,
18
- string: /"(?:\\["\\bfnrtv0]|\\u[0-9a-fA-F]{4}|[^"\\\n\r])*"/,
19
- bool: {
20
- match: ["True", "False"],
21
- },
22
- semicolon: ";",
23
- assign: ":=",
24
- notEqual: "!=",
25
- equal: "==",
26
- gte: ">=",
27
- gt: ">",
28
- lte: "<=",
29
- lt: "<",
30
- lparen: "(",
31
- rparen: ")",
32
- lsquare: "[",
33
- rsquare: "]",
34
- lbracket: "{",
35
- rbracket: "}",
36
- comma: ",",
37
- operator: /\+|\*/,
38
- variable: {
39
- match: /[a-z_][a-zA-Z0-9_']*/,
40
- type: moo.keywords({
41
- keyword: keywords,
42
- }),
43
- },
44
- NL: { match: /\r?\n/, lineBreaks: true },
45
- };
46
-
47
- export const MiniLexer = makeLexer(MiniLexerConfig, ["NL", "comment"], {
48
- eof: true,
49
- });
1
+ import moo from "moo";
2
+ import { makeLexer } from "moo-ignore";
3
+
4
+ const keywords = [
5
+ "return",
6
+ "if",
7
+ "else"
8
+ ]
9
+
10
+ export const MiniLexerConfig = {
11
+ EOF: "*__EOF__*",
12
+ wildcard: "_",
13
+ WS: /[ \t]+/,
14
+ comment: /--.*?$|{-[\s\S]*?-}/,
15
+ number:
16
+ /0[xX][0-9a-fA-F]+|0[bB][01]+|0[oO][0-7]+|(?:\d*\.\d+|\d+)(?:[eE][+-]?\d+)?/,
17
+ char: /'(?:\\['\\bfnrtv0]|\\u[0-9a-fA-F]{4}|[^'\\\n\r])?'/,
18
+ string: /"(?:\\["\\bfnrtv0]|\\u[0-9a-fA-F]{4}|[^"\\\n\r])*"/,
19
+ bool: {
20
+ match: ["True", "False"],
21
+ },
22
+ semicolon: ";",
23
+ assign: ":=",
24
+ notEqual: "!=",
25
+ equal: "==",
26
+ gte: ">=",
27
+ gt: ">",
28
+ lte: "<=",
29
+ lt: "<",
30
+ lparen: "(",
31
+ rparen: ")",
32
+ lsquare: "[",
33
+ rsquare: "]",
34
+ lbracket: "{",
35
+ rbracket: "}",
36
+ comma: ",",
37
+ operator: /\+|\*/,
38
+ variable: {
39
+ match: /[a-z_][a-zA-Z0-9_']*/,
40
+ type: moo.keywords({
41
+ keyword: keywords,
42
+ }),
43
+ },
44
+ NL: { match: /\r?\n/, lineBreaks: true },
45
+ };
46
+
47
+ export const MiniLexer = makeLexer(MiniLexerConfig, ["NL", "comment"], {
48
+ eof: true,
49
+ });
package/src/parse.ts CHANGED
@@ -1,18 +1,18 @@
1
- import { YukigoMiniParser } from "./index.js";
2
-
3
- const parser = new YukigoMiniParser()
4
-
5
- const code = `int n
6
- int result
7
-
8
- n := 5
9
- result := 1
10
-
11
- while n > 0 do
12
- result := result * n
13
- n := n - 1
14
- endwhile
15
-
16
- print result # This should print 120`
17
-
1
+ import { YukigoMiniParser } from "./index.js";
2
+
3
+ const parser = new YukigoMiniParser()
4
+
5
+ const code = `int n
6
+ int result
7
+
8
+ n := 5
9
+ result := 1
10
+
11
+ while n > 0 do
12
+ result := result * n
13
+ n := n - 1
14
+ endwhile
15
+
16
+ print result # This should print 120`
17
+
18
18
  console.log(parser.parse(code))