2 * Copyright 2012-2013, Jakub Zawadzki <darkjames-ws@darkjames.pl>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 %option noyy_scan_buffer
25 %option noyy_scan_bytes
26 %option noyy_scan_string
29 %option never-interactive
31 %option case-insensitive
34 #define YY_DECL static token_type_t yylex(void)
111 TOKEN_UNSIGNED_NUMBER,
115 TOKEN_DISPLAY_FORMAT,
130 ID [_a-zA-Z][_a-zA-Z0-9]*
134 include return TOKEN_INCLUDE;
135 struct return TOKEN_STRUCT;
136 _struct return TOKEN_PRIVATE_STRUCT;
138 const return TOKEN_CONST;
139 protocol return TOKEN_PROTOCOL;
141 while return TOKEN_WHILE;
143 DynamicSwitch return TOKEN_DYNAMIC_SWITCH;
144 switch return TOKEN_SWITCH;
145 table return TOKEN_TABLE;
146 case return TOKEN_CASE;
147 default return TOKEN_DEFAULT;
149 Number return TOKEN_NUMBER;
150 UnsignedNumber return TOKEN_UNSIGNED_NUMBER;
151 Decimal return TOKEN_DECIMAL;
152 Time return TOKEN_TIME;
153 ByteOrder return TOKEN_BYTE_ORDER;
154 DisplayFormat return TOKEN_DISPLAY_FORMAT;
155 Size return TOKEN_SIZE;
157 "(" return TOKEN_LPAREN;
158 ")" return TOKEN_RPAREN;
159 "[" return TOKEN_LBRACKET;
160 "]" return TOKEN_RBRACKET;
161 "{" return TOKEN_LCURLY;
162 "}" return TOKEN_RCURLY;
164 and return TOKEN_ANDAND;
165 or return TOKEN_OROR;
167 "==" return TOKEN_EQUAL;
168 "!=" return TOKEN_NOTEQUAL;
169 "<>" return TOKEN_NOTEQUAL2;
171 ">=" return TOKEN_GEQUAL;
172 "<=" return TOKEN_LEQUAL;
174 "+=" return TOKEN_ASSIGN_PLUS;
175 "=" return TOKEN_ASSIGN;
176 "+" return TOKEN_PLUS;
177 "-" return TOKEN_MINUS;
178 "*" return TOKEN_MULTIPLY;
179 "/" return TOKEN_DIV;
180 "||" return TOKEN_LOGIC_OR;
182 "&&" return TOKEN_LOGIC_AND;
183 "&" return TOKEN_AND;
184 "!" return TOKEN_NOT;
185 "~" return TOKEN_NEG;
186 "^" return TOKEN_XOR;
187 "<<" return TOKEN_SHL;
188 ">>" return TOKEN_SHR;
189 "%" return TOKEN_PERCENT;
190 "$" return TOKEN_DOLLAR;
191 "?" return TOKEN_COND;
193 ";" return TOKEN_SEMICOLON;
194 "." return TOKEN_DOT;
195 "," return TOKEN_COMMA;
196 ":" return TOKEN_COLON;
198 "<" return TOKEN_LESS;
199 ">" return TOKEN_GREATER;
201 "'" yymore(); BEGIN(lch);
203 "'" BEGIN(INITIAL); return TOKEN_CHAR;
204 "\n" return TOKEN_ERROR;
208 "\"" yymore(); BEGIN(lstr);
210 "\"" BEGIN(INITIAL); return TOKEN_STR;
211 "\\" yymore(); BEGIN(lstrescape);
212 "\n" return TOKEN_ERROR;
217 "\n" return TOKEN_ERROR;
218 . yymore(); BEGIN(lstr);
221 "//" BEGIN(cppcomment);
233 /* XXX, can comments be nested? (can't be determinated by current example file set) */
238 if (last_ch == '*' && ch == '/')
241 if (last_ch == '/' && ch == '*')
252 {ID} return TOKEN_ID;
253 {DIGIT10}+"."{DIGIT10}* return TOKEN_FLOAT;
254 {DIGIT10}+ return TOKEN_DIGIT;
255 "0x"{DIGIT16}+ return TOKEN_DIGIT;
259 . return TOKEN_ERROR;
263 static const char *yyfilename;
266 static const char *token_name(token_type_t tok) {
270 case TOKEN_EOF: return "<<eof>>";
271 case TOKEN_ERROR: return "<<error>>";
286 case TOKEN_PRIVATE_STRUCT:
294 case TOKEN_DYNAMIC_SWITCH:
295 return "dynamic switch";
304 snprintf(buf, sizeof(buf), "<token #%d>", tok);
308 static jmp_buf parser_exception;
310 static void xfail(void) { longjmp(parser_exception, 1); }
312 static void next_token(void) { token = yylex(); }
314 static inline int is_token(token_type_t tok) { return (token == tok); }
316 static void _strange(int line) {
317 fprintf(stdout, "?!?!? %s:%d got: %d (%s) @%s:%d\n", __FILE__, line, token, yytext, yyfilename, yylineno);
319 #define strange() _strange(__LINE__)
321 static void _nomatch(int line) {
322 fprintf(stdout, "!!!! %s:%d got: %d (%s) @%s:%d\n", __FILE__, line, token, yytext, yyfilename, yylineno);
325 #define nomatch() _nomatch(__LINE__)
327 static void _accept(token_type_t tok, int line) {
329 fprintf(stdout, "%s:%d got: %d (%s) expected %s @%s:%d\n", __FILE__, line, token, yytext, token_name(tok), yyfilename, yylineno);
334 #define accept(tok) _accept(tok, __LINE__)
336 static int is_id(void) {
337 /* Some NPL files use keyword as ID (sucks...) */
339 is_token(TOKEN_PROTOCOL) ||
340 is_token(TOKEN_SIZE) ||
341 is_token(TOKEN_DEFAULT) ||
342 is_token(TOKEN_NUMBER) ||
343 is_token(TOKEN_DECIMAL) ||
344 is_token(TOKEN_TIME) ||
345 is_token(TOKEN_BYTE_ORDER) ||
346 is_token(TOKEN_OROR) || is_token(TOKEN_ANDAND) ||
347 is_token(TOKEN_STRUCT) || is_token(TOKEN_TABLE) ||
351 static char *_accept_id(int line) {
355 fprintf(stdout, "%s:%d got: %d (%s) expected %s @%s:%d\n", __FILE__, line, token, yytext, token_name(TOKEN_ID), yyfilename, yylineno);
359 id = xstrdup(yytext);
365 #define accept_id() _accept_id(__LINE__)
367 static unsigned int _accept_int(int line) {
370 if (token != TOKEN_DIGIT) {
371 fprintf(stdout, "%s:%d got: %d (%s) expected %s @%s:%d\n", __FILE__, line, token, yytext, token_name(TOKEN_DIGIT), yyfilename, yylineno);
375 if (yytext[0] == '0' && yytext[1] == 'x')
376 num = strtol(yytext + 2, NULL, 16);
378 num = strtol(yytext, NULL, 10);
385 #define accept_int() _accept_int(__LINE__)
388 static char *_accept_str(int line) {
392 if (token != TOKEN_STR) {
393 fprintf(stdout, "%s:%d got: %d (%s) expected %s @%s:%d\n", __FILE__, line, token, yytext, token_name(TOKEN_STR), yyfilename, yylineno);
397 len = strlen(yytext);
399 if (len < 2 || yytext[0] != '"' || yytext[len-1] != '"')
405 ptr = str = xmalloc(len-2+1);
406 for (i = 1; i < len-1; i++) {
407 if (yytext[i] == '\\') {
410 if (yytext[i] == '0' && yytext[i+1] == 'x') {
441 fprintf(stdout, "unrecog: %c @ %d\n", yytext[i], yylineno);
452 /* escaping is done almost like in C so don't unescape (cause it'd require escaping later...) */
453 str = xmalloc(len + 1);
454 memcpy(str, yytext + 1, len);
462 #define accept_str() _accept_str(__LINE__)
464 static int is_token_accept(token_type_t tok) {
472 static int is_params(void) { return is_token(TOKEN_LPAREN); }
475 parse_params(npl_params_t *p)
479 accept(TOKEN_LPAREN);
481 if (i == NPL_PARAMS_MAX) {
482 fprintf(stdout, "i == NPL_PARAMS_MAX");
486 p->args[i++] = accept_id();
488 } while (is_token_accept(TOKEN_COMMA));
489 accept(TOKEN_RPAREN);
494 static void parse_expression(npl_expression_t *expr);
495 static npl_expression_t *xparse_expression(void);
498 parse_primary(npl_expression_t *expr)
501 expr->type = EXPRESSION_ID;
502 expr->id.id = accept_id();
506 if (is_token(TOKEN_DIGIT)) {
507 expr->type = EXPRESSION_INT;
508 expr->num.digit = accept_int();
512 if (is_token(TOKEN_FLOAT)) {
519 if (is_token(TOKEN_CHAR)) {
526 if (is_token(TOKEN_STR)) {
527 expr->type = EXPRESSION_STR;
528 expr->str.str = accept_str();
532 if (is_token_accept(TOKEN_LPAREN)) {
533 parse_expression(expr);
534 accept(TOKEN_RPAREN);
541 /* ExpressionList = Expression, { ",", Expression } ; */
543 parse_expression_list(npl_expression_list_t **ptr)
546 npl_expression_list_t *cur = xnew(npl_expression_list_t);
550 cur->expr = xparse_expression();
552 } while (is_token_accept(TOKEN_COMMA));
558 parse_expression1(npl_expression_t *expr)
563 if (is_token_accept(TOKEN_LPAREN)) { /* foo() */
564 npl_expression_t *fun = xdup(npl_expression_t, expr);
565 npl_expression_list_t *args = NULL;
567 if (!is_token(TOKEN_RPAREN))
568 parse_expression_list(&args);
569 accept(TOKEN_RPAREN);
571 expr->type = EXPRESSION_CALL;
573 expr->call.args = args;
575 } else if (is_token_accept(TOKEN_DOLLAR)) { /* arr$[field1, field2, ...] */
576 npl_expression_t *base = xdup(npl_expression_t, expr);
577 npl_expression_list_t *indexes;
579 accept(TOKEN_LBRACKET);
580 parse_expression_list(&indexes);
581 accept(TOKEN_RBRACKET);
583 expr->type = EXPRESSION_MULTI_INDEX;
584 expr->aarr.base = base;
585 expr->aarr.indexes = indexes;
587 } else if (is_token_accept(TOKEN_LBRACKET)) { /* arr[10] */
588 npl_expression_t *base = xdup(npl_expression_t, expr);
589 npl_expression_t *idx;
591 idx = xparse_expression();
592 accept(TOKEN_RBRACKET);
594 expr->type = EXPRESSION_INDEX;
595 expr->arr.base = base;
596 expr->arr.index = idx;
598 } else if (is_token_accept(TOKEN_DOT)) {
599 npl_expression_t *base = xdup(npl_expression_t, expr);
604 expr->type = EXPRESSION_FIELD;
605 expr->fld.base = base;
606 expr->fld.field = field;
615 parse_expression2(npl_expression_t *expr)
621 (is_token_accept(TOKEN_MINUS)) ? OP1_MINUS :
622 (is_token_accept(TOKEN_NOT)) ? OP1_NOT :
623 (is_token_accept(TOKEN_NEG)) ? OP1_NEG :
626 if (op != OP1_INVALID) {
627 expr->type = EXPRESSION_UNARY;
628 expr->u.operator = op;
630 expr = expr->u.operand = xnew(npl_expression_t);
632 } while (op != OP1_INVALID);
634 parse_expression1(expr);
638 parse_expression3(npl_expression_t *expr)
642 parse_expression2(expr);
645 (is_token_accept(TOKEN_MULTIPLY)) ? OP2_MULTIPLY :
646 (is_token_accept(TOKEN_DIV)) ? OP2_DIV :
647 (is_token_accept(TOKEN_PERCENT)) ? OP2_MOD :
650 if (op != OP2_INVALID) {
651 npl_expression_t *operand = xdup(npl_expression_t, expr);
654 expr->b.operand2 = e = xnew(npl_expression_t);
655 parse_expression3(e);
657 expr->b.operator = op;
658 expr->b.operand1 = operand;
659 expr->type = EXPRESSION_BINARY;
665 parse_expression4(npl_expression_t *expr)
669 parse_expression3(expr);
672 (is_token_accept(TOKEN_PLUS)) ? OP2_PLUS :
673 (is_token_accept(TOKEN_MINUS)) ? OP2_MINUS :
676 if (op != OP2_INVALID) {
677 npl_expression_t *operand = xdup(npl_expression_t, expr);
680 expr->b.operand2 = e = xnew(npl_expression_t);
681 parse_expression4(e);
683 expr->b.operator = op;
684 expr->b.operand1 = operand;
685 expr->type = EXPRESSION_BINARY;
691 parse_expression5(npl_expression_t *expr)
695 parse_expression4(expr);
698 (is_token_accept(TOKEN_SHL)) ? OP2_SHL :
699 (is_token_accept(TOKEN_SHR)) ? OP2_SHR :
702 if (op != OP2_INVALID) {
703 npl_expression_t *operand = xdup(npl_expression_t, expr);
706 expr->b.operand2 = e = xnew(npl_expression_t);
707 parse_expression5(e);
709 expr->b.operator = op;
710 expr->b.operand1 = operand;
711 expr->type = EXPRESSION_BINARY;
717 parse_expression6(npl_expression_t *expr)
721 parse_expression5(expr);
724 (is_token_accept(TOKEN_LESS)) ? OP2_LESS :
725 (is_token_accept(TOKEN_GREATER)) ? OP2_GREATER :
726 (is_token_accept(TOKEN_LEQUAL)) ? OP2_LEQUAL :
727 (is_token_accept(TOKEN_GEQUAL)) ? OP2_GEQUAL :
730 if (op != OP2_INVALID) {
731 npl_expression_t *operand = xdup(npl_expression_t, expr);
734 expr->b.operand2 = e = xnew(npl_expression_t);
735 parse_expression6(e);
737 expr->b.operator = op;
738 expr->b.operand1 = operand;
739 expr->type = EXPRESSION_BINARY;
745 parse_expression7(npl_expression_t *expr)
749 parse_expression6(expr);
752 (is_token_accept(TOKEN_EQUAL)) ? OP2_EQUAL :
753 (is_token_accept(TOKEN_NOTEQUAL)) ? OP2_NOTEQUAL :
754 (is_token_accept(TOKEN_NOTEQUAL2)) ? OP2_NOTEQUAL :
757 if (op != OP2_INVALID) {
758 npl_expression_t *operand = xdup(npl_expression_t, expr);
761 expr->b.operand2 = e = xnew(npl_expression_t);
762 parse_expression7(e);
764 expr->b.operator = op;
765 expr->b.operand1 = operand;
766 expr->type = EXPRESSION_BINARY;
772 parse_expression8(npl_expression_t *expr)
774 parse_expression7(expr);
776 if (is_token_accept(TOKEN_AND)) {
777 npl_expression_t *operand = xdup(npl_expression_t, expr);
780 expr->b.operand2 = e = xnew(npl_expression_t);
781 parse_expression8(e);
783 expr->b.operator = OP2_AND;
784 expr->b.operand1 = operand;
785 expr->type = EXPRESSION_BINARY;
791 parse_expression9(npl_expression_t *expr)
793 parse_expression8(expr);
795 if (is_token_accept(TOKEN_XOR)) {
796 npl_expression_t *operand = xdup(npl_expression_t, expr);
799 expr->b.operand2 = e = xnew(npl_expression_t);
800 parse_expression9(e);
802 expr->b.operator = OP2_XOR;
803 expr->b.operand1 = operand;
804 expr->type = EXPRESSION_BINARY;
810 parse_expression10(npl_expression_t *expr)
812 parse_expression9(expr);
814 if (is_token_accept(TOKEN_OR)) {
815 npl_expression_t *operand = xdup(npl_expression_t, expr);
818 expr->b.operand2 = e = xnew(npl_expression_t);
819 parse_expression10(e);
821 expr->b.operator = OP2_OR;
822 expr->b.operand1 = operand;
823 expr->type = EXPRESSION_BINARY;
829 parse_expression11(npl_expression_t *expr)
833 parse_expression10(expr);
836 (is_token_accept(TOKEN_LOGIC_AND)) ? OP2_LOGIC_AND :
837 (is_token_accept(TOKEN_ANDAND)) ? OP2_LOGIC_AND :
840 if (op != OP2_INVALID) {
841 npl_expression_t *operand = xdup(npl_expression_t, expr);
844 expr->b.operand2 = e = xnew(npl_expression_t);
845 parse_expression11(e);
847 expr->b.operator = op;
848 expr->b.operand1 = operand;
849 expr->type = EXPRESSION_BINARY;
855 parse_expression12(npl_expression_t *expr)
859 parse_expression11(expr);
862 (is_token_accept(TOKEN_LOGIC_OR)) ? OP2_LOGIC_OR :
863 (is_token_accept(TOKEN_OROR)) ? OP2_LOGIC_OR :
866 if (op != OP2_INVALID) {
867 npl_expression_t *operand = xdup(npl_expression_t, expr);
870 expr->b.operand2 = e = xnew(npl_expression_t);
871 parse_expression12(e);
873 expr->b.operator = op;
874 expr->b.operand1 = operand;
875 expr->type = EXPRESSION_BINARY;
881 parse_expression13(npl_expression_t *expr)
883 parse_expression12(expr);
885 if (is_token_accept(TOKEN_COND)) {
886 npl_expression_t *operand = xdup(npl_expression_t, expr);
889 expr->c.test_expr = operand;
891 e = xnew(npl_expression_t);
893 expr->c.true_expr = e;
896 e = xnew(npl_expression_t);
897 parse_expression13(e);
898 expr->c.false_expr = e;
900 expr->type = EXPRESSION_COND;
904 static npl_expression_t *
905 xparse_expression(void)
907 npl_expression_t *expr = xnew(npl_expression_t);
909 parse_expression(expr);
914 parse_expression(npl_expression_t *expr)
918 parse_expression13(expr);
921 (is_token_accept(TOKEN_ASSIGN)) ? OP2_ASSIGN :
922 (is_token_accept(TOKEN_ASSIGN_PLUS)) ? OP2_ASSIGN_PLUS :
925 if (op != OP2_INVALID) {
926 npl_expression_t *operand = xdup(npl_expression_t, expr);
928 expr->b.operand2 = xparse_expression();
930 expr->b.operator = op;
931 expr->b.operand1 = operand;
932 expr->type = EXPRESSION_BINARY;
936 static int is_attribute(void) { return is_token(TOKEN_LBRACKET); }
938 static npl_attribute_list_t **
939 pparse_attributes(npl_attribute_list_t **ptr)
941 accept(TOKEN_LBRACKET);
944 npl_attribute_list_t *cur = xnew(npl_attribute_list_t);
948 cur->expr = xparse_expression();
950 if (is_token_accept(TOKEN_SEMICOLON))
952 else if (is_token_accept(TOKEN_COMMA))
955 while (!is_token(TOKEN_RBRACKET));
956 // while (is_token_accept(TOKEN_COMMA));
958 accept(TOKEN_RBRACKET);
963 parse_all_attributes(npl_attribute_list_t **attr_ptr)
965 while (is_attribute())
966 attr_ptr = pparse_attributes(attr_ptr);
970 static void parse_statement(npl_statement_t *st);
972 static npl_statement_t *
973 xparse_statement(void)
975 npl_statement_t *st = xnew(npl_statement_t);
982 parse_switch_body(npl_switch_t *sw)
984 struct npl_switch_case **ptr = &sw->cases;
986 while (is_token(TOKEN_CASE)) {
987 struct npl_switch_case *cur = xnew(struct npl_switch_case);
994 parse_expression(&cur->e);
997 if (!is_token(TOKEN_CASE) && !is_token(TOKEN_DEFAULT)) {
998 cur->st = xparse_statement();
999 is_token_accept(TOKEN_SEMICOLON);
1004 if (is_token_accept(TOKEN_DEFAULT)) {
1005 accept(TOKEN_COLON);
1006 sw->default_st = xparse_statement();
1011 parse_switch(npl_switch_t *sw)
1013 accept(TOKEN_SWITCH);
1015 if (is_token_accept(TOKEN_LPAREN)) {
1016 sw->switch_expr = xparse_expression();
1017 accept(TOKEN_RPAREN);
1020 accept(TOKEN_LCURLY);
1021 parse_switch_body(sw);
1022 accept(TOKEN_RCURLY);
1023 is_token_accept(TOKEN_SEMICOLON);
1027 parse_dynamic_switch(npl_switch_t *sw)
1029 accept(TOKEN_DYNAMIC_SWITCH);
1031 sw->switch_expr = xparse_expression();
1033 accept(TOKEN_LCURLY);
1034 parse_switch_body(sw);
1035 accept(TOKEN_RCURLY);
1036 is_token_accept(TOKEN_SEMICOLON);
1039 static int is_statement(void) {
1041 is_token(TOKEN_WHILE) ||
1042 is_token(TOKEN_TABLE) ||
1043 is_token(TOKEN_STRUCT) || is_token(TOKEN_PRIVATE_STRUCT) ||
1044 is_token(TOKEN_SWITCH) || is_token(TOKEN_DYNAMIC_SWITCH) ||
1045 is_id() || is_attribute() ||
1047 is_token(TOKEN_SEMICOLON) ||
1053 /* Statements = { Statement } ; */
1054 static struct _npl_statements *
1055 xparse_statements(void)
1057 struct _npl_statements *ret;
1058 struct _npl_statements **ptr = &ret;
1060 while (is_statement()) {
1061 struct _npl_statements *cur = xnew(struct _npl_statements);
1063 parse_statement(&cur->st);
1074 parse_while(npl_statement_t *st)
1076 accept(TOKEN_WHILE);
1079 st->w.id = accept_id();
1081 accept(TOKEN_LBRACKET);
1082 parse_expression(&st->w.expr);
1083 accept(TOKEN_RBRACKET);
1085 accept(TOKEN_LCURLY);
1086 st->w.sts = xparse_statements();
1087 accept(TOKEN_RCURLY);
1088 is_token_accept(TOKEN_SEMICOLON);
1091 static int is_formatting(void) { return is_token(TOKEN_ASSIGN); }
1093 /* Formatting = "=", Expression ; */
1094 static npl_expression_t *
1095 xparse_formatting(void)
1097 npl_expression_t *format;
1099 accept(TOKEN_ASSIGN);
1101 format = xnew(npl_expression_t);
1102 parse_expression(format);
1106 static void parse_table(npl_table_t *);
1107 static void parse_struct(npl_struct_t *s, int statement);
1110 parse_statement(npl_statement_t *st)
1112 parse_all_attributes(&st->attr_list);
1114 if (is_token(TOKEN_WHILE)) {
1116 st->type = STATEMENT_WHILE;
1120 if (is_token(TOKEN_TABLE)) {
1121 parse_table(&st->t.data);
1122 st->type = STATEMENT_TABLE;
1126 if (is_token(TOKEN_STRUCT) || is_token(TOKEN_PRIVATE_STRUCT)) {
1127 parse_struct(&st->s.data, 1);
1128 st->type = STATEMENT_STRUCT;
1132 if (is_token(TOKEN_SWITCH)) {
1133 parse_switch(&(st->sw.data));
1134 st->type = STATEMENT_SWITCH;
1138 if (is_token(TOKEN_DYNAMIC_SWITCH)) {
1139 parse_dynamic_switch(&(st->sw.data));
1140 st->type = STATEMENT_DYNAMIC_SWITCH;
1144 if (is_token(TOKEN_SEMICOLON)) {
1145 accept(TOKEN_SEMICOLON);
1151 st->type = STATEMENT_FIELD;
1152 st->f.t_id = accept_id();
1154 if (is_token_accept(TOKEN_LPAREN)) {
1155 parse_expression_list(&st->f.params);
1156 accept(TOKEN_RPAREN);
1159 st->f.params = NULL;
1161 st->f.id = accept_id();
1162 if (is_token_accept(TOKEN_COLON))
1163 st->f.bits = accept_int();
1165 else if (is_token_accept(TOKEN_LBRACKET)) {
1166 st->f.arr = xparse_expression();
1167 accept(TOKEN_RBRACKET);
1170 if (is_formatting())
1171 st->f.format = xparse_formatting();
1173 if (is_token_accept(TOKEN_LCURLY)) {
1174 st->f.sts = xparse_statements();
1175 accept(TOKEN_RCURLY);
1176 is_token_accept(TOKEN_SEMICOLON);
1180 accept(TOKEN_SEMICOLON);
1183 /* Protocol = "protocol", ID, [Params], [Formatting], "{", Statements, "}", ";" ; */
1185 parse_protocol(npl_protocol_t *p)
1187 accept(TOKEN_PROTOCOL);
1188 p->id = accept_id();
1191 parse_params(&p->params);
1193 if (is_formatting())
1194 p->format = xparse_formatting();
1196 accept(TOKEN_LCURLY);
1197 p->sts = xparse_statements();
1198 accept(TOKEN_RCURLY);
1199 is_token_accept(TOKEN_SEMICOLON);
1203 parse_struct(npl_struct_t *s, int statement)
1205 if (is_token_accept(TOKEN_STRUCT))
1207 else if (is_token_accept(TOKEN_PRIVATE_STRUCT))
1212 if (!statement || is_id())
1213 s->id = accept_id();
1216 parse_params(&s->params);
1219 if (is_token_accept(TOKEN_LBRACKET)) {
1220 s->count_expr = xparse_expression();
1221 accept(TOKEN_RBRACKET);
1225 if (is_formatting())
1226 s->format = xparse_formatting();
1228 accept(TOKEN_LCURLY);
1229 s->sts = xparse_statements();
1230 accept(TOKEN_RCURLY);
1231 is_token_accept(TOKEN_SEMICOLON);
1234 /* Table = "table", ID, [Params], "{", "switch", [ "(", Expr, ")" ], {TableCase}, [DefaultCase], "}", ";" ;
1236 DefaultCase = "default", ":", Expression", ";" ;
1239 parse_table(npl_table_t *t)
1241 accept(TOKEN_TABLE);
1242 t->id = accept_id();
1244 parse_params(&t->params);
1246 accept(TOKEN_LCURLY);
1248 struct npl_table_case **ptr;
1250 accept(TOKEN_SWITCH);
1251 if (is_token_accept(TOKEN_LPAREN)) {
1252 t->switch_expr = xparse_expression();
1253 accept(TOKEN_RPAREN);
1256 accept(TOKEN_LCURLY);
1259 while (is_token_accept(TOKEN_CASE)) {
1260 struct npl_table_case *cur;
1262 cur = *ptr = xnew(struct npl_table_case);
1265 parse_expression(&(cur->e));
1266 accept(TOKEN_COLON);
1268 while (is_token_accept(TOKEN_CASE)) {
1269 cur = *ptr = xnew(struct npl_table_case);
1272 parse_expression(&(cur->e));
1273 accept(TOKEN_COLON);
1275 cur->return_expr = xparse_expression();
1276 accept(TOKEN_SEMICOLON);
1280 if (is_token_accept(TOKEN_DEFAULT)) {
1281 accept(TOKEN_COLON);
1282 t->default_expr = xparse_expression();
1283 accept(TOKEN_SEMICOLON);
1285 accept(TOKEN_RCURLY);
1288 accept(TOKEN_RCURLY);
1289 is_token_accept(TOKEN_SEMICOLON);
1296 is_token(TOKEN_DECIMAL) ||
1297 is_token(TOKEN_NUMBER) ||
1298 is_token(TOKEN_TIME) ||
1299 is_token(TOKEN_UNSIGNED_NUMBER);
1302 /* Type = BasicType, ID, [Params], "{", {TypeAttr}, "}" ;
1304 BasicType = "Decimal" | "Number" | "Time" | "UnsignedNumber" ;
1306 TypeAttr = AttrName, "=", Expression ;
1308 AttrName = "ByteOrder" | "DisplayFormat" | "Size" ;
1311 parse_type(npl_type_t *t)
1313 if (is_token_accept(TOKEN_DECIMAL))
1314 t->type = FIELD_DECIMAL;
1315 else if (is_token_accept(TOKEN_NUMBER))
1316 t->type = FIELD_NUMBER;
1317 else if (is_token_accept(TOKEN_TIME))
1318 t->type = FIELD_TIME;
1319 else if (is_token_accept(TOKEN_UNSIGNED_NUMBER))
1320 t->type = FIELD_UNSIGNED_NUMBER;
1324 t->id = accept_id();
1326 parse_params(&t->params);
1327 accept(TOKEN_LCURLY);
1329 while (!is_token(TOKEN_RCURLY)) {
1330 npl_expression_t **ptr;
1332 if (is_token_accept(TOKEN_BYTE_ORDER))
1333 ptr = &t->byte_order;
1334 else if (is_token_accept(TOKEN_DISPLAY_FORMAT))
1335 ptr = &t->display_format;
1336 else if (is_token_accept(TOKEN_SIZE))
1342 fprintf(stdout, "already got %s attr!\n", str);
1344 accept(TOKEN_ASSIGN);
1345 *ptr = xparse_expression();
1347 if (is_token_accept(TOKEN_COMMA))
1349 else if (is_token_accept(TOKEN_SEMICOLON))
1352 accept(TOKEN_RCURLY);
1355 /* Const = "const", ID, "=", Expression, ";" ; */
1357 parse_const(npl_const_t *c)
1359 accept(TOKEN_CONST);
1360 c->id = accept_id();
1361 accept(TOKEN_ASSIGN);
1362 parse_expression(&c->expr);
1363 accept(TOKEN_SEMICOLON);
1366 /* Declaration = Attributes
1372 | ( "include", STR )
1376 parse_decl(npl_decl_t *d)
1378 parse_all_attributes(&d->attr_list);
1380 if (is_token(TOKEN_STRUCT)) {
1381 d->type = DECL_STRUCT;
1382 parse_struct(&d->s.data, 0);
1384 } else if (is_token(TOKEN_TABLE)) {
1385 d->type = DECL_TABLE;
1386 parse_table(&d->t.data);
1388 } else if (is_token(TOKEN_CONST)) {
1389 d->type = DECL_CONST;
1390 parse_const(&d->c.data);
1392 } else if (is_token(TOKEN_PROTOCOL)) {
1393 d->type = DECL_PROTOCOL;
1394 parse_protocol(&d->p.data);
1396 } else if (is_type()) {
1397 d->type = DECL_TYPE;
1398 parse_type(&d->ty.data);
1400 } else if (is_token_accept(TOKEN_INCLUDE)) {
1401 d->type = DECL_INCLUDE;
1402 d->i.file = accept_str(); /* XXX, it's C-escaped */ /* XXX, unix / vs dos \\ */
1408 /* NPL = { Declaration } ; */
1410 parse_npl(npl_code_t *code)
1412 struct _npl_decl_list **ptr = &(code->decls);
1414 while (!is_token_accept(TOKEN_EOF)) {
1415 struct _npl_decl_list *cur = xnew(struct _npl_decl_list);
1420 parse_decl(&cur->d);
1426 npl_parse_file(npl_code_t *code, FILE *f, const char *filename)
1428 volatile int parse_ok = 0;
1430 yyfilename = filename;
1433 if (!setjmp(parser_exception)) {
1441 return (parse_ok == 1);