Improve number printing to make it more symmetrical with parsing
[applesoft_basic.git] / applesoft_basic.y
1 /*
2  * Copyright (C) 2018 Nick Downing <nick@ndcode.org>
3  * SPDX-License-Identifier: GPL-2.0-only
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the Free
7  * Software Foundation; version 2.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 51
16  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 %{
20   import t_def
21   import sys
22 %}
23
24 %locations
25
26 %token KEYWORD_ABS
27 %token KEYWORD_AND
28 %token KEYWORD_ASC
29 %token KEYWORD_AT
30 %token KEYWORD_ATN
31 %token KEYWORD_CALL
32 %token KEYWORD_CHR_DOLLAR
33 %token KEYWORD_CLEAR
34 %token KEYWORD_COLOR_EQUAL
35 %token KEYWORD_CONT
36 %token KEYWORD_COS
37 %token KEYWORD_DATA
38 %token KEYWORD_DEF
39 %token KEYWORD_DEL
40 %token KEYWORD_DIM
41 %token KEYWORD_DRAW
42 %token KEYWORD_END
43 %token KEYWORD_EXP
44 %token KEYWORD_FLASH
45 %token KEYWORD_FN
46 %token KEYWORD_FOR
47 %token KEYWORD_FRE
48 %token KEYWORD_GET
49 %token KEYWORD_GO
50 %token KEYWORD_GOTO
51 %token KEYWORD_GR
52 %token KEYWORD_HCOLOR_EQUAL
53 %token KEYWORD_HGR
54 %token KEYWORD_HGR2
55 %token KEYWORD_HIMEM_COLON
56 %token KEYWORD_HLIN
57 %token KEYWORD_HOME
58 %token KEYWORD_HPLOT
59 %token KEYWORD_HTAB
60 %token KEYWORD_IF
61 %token KEYWORD_IN_NUMBER
62 %token KEYWORD_INPUT
63 %token KEYWORD_INT
64 %token KEYWORD_INVERSE
65 %token KEYWORD_LEFT_DOLLAR
66 %token KEYWORD_LEN
67 %token KEYWORD_LET
68 %token KEYWORD_LIST
69 %token KEYWORD_LOAD
70 %token KEYWORD_LOG
71 %token KEYWORD_LOMEM_COLON
72 %token KEYWORD_MID_DOLLAR
73 %token KEYWORD_NEW
74 %token KEYWORD_NEXT
75 %token KEYWORD_NORMAL
76 %token KEYWORD_NOT
77 %token KEYWORD_NOTRACE
78 %token KEYWORD_ON
79 %token KEYWORD_ONERR
80 %token KEYWORD_OR
81 %token KEYWORD_PDL
82 %token KEYWORD_PEEK
83 %token KEYWORD_PLOT
84 %token KEYWORD_POKE
85 %token KEYWORD_POP
86 %token KEYWORD_POS
87 %token KEYWORD_PR_NUMBER
88 %token KEYWORD_PRINT
89 %token KEYWORD_READ
90 %token KEYWORD_RECALL
91 %token KEYWORD_REM
92 %token KEYWORD_RESTORE
93 %token KEYWORD_RESUME
94 %token KEYWORD_RETURN
95 %token KEYWORD_RIGHT_DOLLAR
96 %token KEYWORD_SAVE
97 %token KEYWORD_SCALE_EQUAL
98 %token KEYWORD_SCRN_LPAREN
99 %token KEYWORD_SGN
100 %token KEYWORD_SHLOAD
101 %token KEYWORD_SIN
102 %token KEYWORD_SPC_LPAREN
103 %token KEYWORD_SPEED_EQUAL
104 %token KEYWORD_SQR
105 %token KEYWORD_STEP
106 %token KEYWORD_STOP
107 %token KEYWORD_STORE
108 %token KEYWORD_STR_DOLLAR
109 %token KEYWORD_TAB_LPAREN
110 %token KEYWORD_TAN
111 %token KEYWORD_TEXT
112 %token KEYWORD_THEN
113 %token KEYWORD_TO
114 %token KEYWORD_TRACE
115 %token KEYWORD_USR
116 %token KEYWORD_VAL
117 %token KEYWORD_VLIN
118 %token KEYWORD_VTAB
119 %token KEYWORD_WAIT
120 %token KEYWORD_XDRAW
121 %token KEYWORD_XPLOT
122 %token INT_LITERAL
123 %token FLOAT_LITERAL
124 %token OPERATOR_GE
125 %token OPERATOR_LE
126 %token OPERATOR_NE
127 %token STR_LITERAL
128 %token VARIABLE
129
130 %left KEYWORD_OR
131 %left KEYWORD_AND
132 %left '<' '=' '>' OPERATOR_GE OPERATOR_LE OPERATOR_NE
133 %left '+' '-'
134 %left '*' '/'
135 %left '^'
136 %right UNARY KEYWORD_NOT
137
138 %%
139
140 program
141   :
142   | program %space (?E{t_def.NodeLine}INT_LITERAL statement_list) '\n'
143   | error '\n' {
144     yyerror('Syntax error\n')
145     yyerrok()
146   }
147   ;
148
149 statement_list
150   : statement_opt
151   | statement_list ':' statement_opt
152   ;
153
154 statement_opt
155   :
156   | %space (?E{t_def.NodeStatementLet}VARIABLE '=' expression)
157   | %space (?E{t_def.NodeStatementLet}KEYWORD_LET VARIABLE '=' expression)
158   | %space (?E{t_def.NodeStatementPrint, semicolon = False}KEYWORD_PRINT print_expression_list0)
159   | %space (?E{t_def.NodeStatementPrint, semicolon = True}KEYWORD_PRINT print_expression_list1)
160   | %space (?E{t_def.NodeStatementGoto}KEYWORD_GOTO INT_LITERAL)
161   | %space (?E{t_def.NodeStatementIf}KEYWORD_IF expression KEYWORD_THEN) statement_opt
162   | %space (?E{t_def.NodeStatementIf}KEYWORD_IF expression KEYWORD_THEN) %space (?E{t_def.NodeStatementGoto}INT_LITERAL)
163   | %space (?E{t_def.NodeStatementEnd}KEYWORD_END)
164   ;
165
166 print_expression_list0
167   :
168   | print_expression_list0 expression
169   | print_expression_list1 expression
170   ;
171
172 print_expression_list1
173   : print_expression_list0 ';'
174   | print_expression_list1 ';'
175   ;
176
177 expression
178   : %space (?E{t_def.NodeExpressionOr}expression KEYWORD_OR expression)
179   | %space (?E{t_def.NodeExpressionAnd}expression KEYWORD_AND expression)
180   | %space (?E{t_def.NodeExpressionLT}expression '<' expression)
181   | %space (?E{t_def.NodeExpressionEqual}expression '=' expression)
182   | %space (?E{t_def.NodeExpressionGT}expression '>' expression)
183   | %space (?E{t_def.NodeExpressionGE}expression OPERATOR_GE expression)
184   | %space (?E{t_def.NodeExpressionLE}expression OPERATOR_LE expression)
185   | %space (?E{t_def.NodeExpressionNE}expression OPERATOR_NE expression)
186   | %space (?E{t_def.NodeExpressionAdd}expression '+' expression)
187   | %space (?E{t_def.NodeExpressionSubtract}expression '-' expression)
188   | %space (?E{t_def.NodeExpressionMultiply}expression '*' expression)
189   | %space (?E{t_def.NodeExpressionDivide}expression '/' expression)
190   | %space (?E{t_def.NodeExpressionPower}expression '^' expression)
191   | %space (?E{t_def.NodeExpressionSign, sign = -1}'-' expression) %prec UNARY
192   | %space (?E{t_def.NodeExpressionSign, sign = 1}'+' expression) %prec UNARY
193   | %space (?E{t_def.NodeExpressionNot}KEYWORD_NOT expression)
194   | '(' expression ')'
195   | %space (?E{t_def.NodeExpressionIntLiteral}INT_LITERAL)
196   | %space (?E{t_def.NodeExpressionFloatLiteral}FLOAT_LITERAL)
197   | %space (?E{t_def.NodeExpressionStrLiteral}STR_LITERAL)
198   | %space (?E{t_def.NodeExpressionVariable}VARIABLE)
199   ;
200 %%
201
202 def yyerror(s):
203   sys.stdout.write('{0:s}\n'.format(s))
204   sys.exit(1)