-
Notifications
You must be signed in to change notification settings - Fork 1
/
fundy.grammar
115 lines (86 loc) · 3.39 KB
/
fundy.grammar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#
# Copyright 2009 Benjamin Mellor
#
# This file is part of Fundy.
#
# Fundy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ignore whitespace or continuation or #comment
IGNORE: "[ \t]+|\\\n|(#[^\n]*)";
NUMBER: "[0-9]+";
IDENT: "([a-zA-Z_][a-zA-Z_0-9]*)|([.+\-*/=!@$%\^&\|]+)";
STRING: "\"([ a-zA-Z0-9!@\#$%\^&*\(\)\-=_+\|\[\]\{\}'\;:,.<>/\?`~]|\\\"|\\n|\\t|\\b|\\v|\\0|\\\\)*\"";
CHAR: "'([ a-zA-Z0-9!@\#$%\^&*\(\)\-=_+\|\[\]\{\}\"\;:,.<>/\?`~]|\\'|\\n|\\t|\\b|\\v|\\0|\\\\)'";
LINEBREAK: "\n[ \t\n]*";
MISSING: "\?[a-zA-Z_0-9+\-*/=!@$%\&\|\?]+";
TERM: ";";
BEGIN: ":";
# NOTE: Have tried putting the required TERMs in here instead of at the end of
# every concrete statement, but that causes statement to recognise "foo = 1"
# as starting with an io_statement (a print with an elided "print" keyword),
# that it commits to, and then treat the "=" as a parse error. With the TERM at
# the end of print_statement, the z cannot be treated as a complete
# print_statement, so parsing does backtrack to try assign_statement.
program: [TERM]* ( statement [TERM]* )* [EOF] ;
statement: <io_statement>
| <bind_statement>
;
# statements that do IO, and therefore cannot be allowed inside a function
io_statement: <print_statement>
#!if not for_translation
# this statement is only implemented when we are running untranslated
| <show_statement>
#!endif
;
print_statement: ["print"]? expr ( [","] expr )* [TERM] ;
show_statement: ["show"] ( expr ( [","] expr )* )? [TERM] ;
# statements that bind names, which can be allowed inside a function
bind_statement: <assign_statement>
| <type_statement>
;
# the short form binds an expression to a name
# the def keyword form does the same thing, but the expression is replaced by
# a block, which returns an expression after an arbitrary number of local
# definitions
assign_statement: IDENT param* ["="] expr [TERM]
| ["def"] IDENT param* block [TERM]
;
param: IDENT ;
block: [BEGIN] bind_statement* ["return"] expr [TERM] ;
type_statement: ["data"] IDENT ["="] >constructor_list< [TERM] ;
constructor_list: constructor ( ["|"] constructor )* ;
constructor: IDENT IDENT* ;
expr: >chain< ;
term: <IDENT>
| <MISSING>
| <literal>
| <paren>
| <typeswitch>
;
paren: "(" <expr> ")" ;
chain: term+;
typeswitch: ["typeswitch"] expr >caseblock< ;
caseblock: [BEGIN] switchcase+ ;
switchcase: ["case"] expr ["return"] expr [TERM] ;
literal: <NUMBER>
| <list>
| <tuple>
| <STRING>
| <CHAR>
;
list: [ "[" ] ( expr ( [","] expr )* tail? )? [ "]" ] ;
tail: [ BEGIN ] expr ;
tuple: ["{"] ( expr ( [","] expr )+ )? ["}"]
| ["{"] expr [","] ["}"]
;