view tests/agcl/parsifal/ss-kb.syn @ 21:1c9dac05d040

Add lint-style FALLTHROUGH annotations to fallthrough cases. (in the parse engine and thus the output code) Document this, because the old output causes warnings with gcc10.
author David A. Holland
date Mon, 13 Jun 2022 00:04:38 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
Copyright 1992, Jerome T. Holland
See the file COPYING for license and usage terms.
*/

/* Keyboard syntax for Sample Spreadsheet */

backspace          = '\b'
delete             = 339
letter             = 'a-z' + 'A-Z'
digit              = '0-9'
eof                = 0
any key            =~eof
yes                ='y' + 'Y'
no                 =~yes

text character     = 32..127

up                 = 328
page up            = 329
left               = 331
right              = 333
down               = 336
page down          = 337
control page up    = 388
control page down  = 374
control left       = 371
control right      = 372
home               = 327
control home       = 375
end                = 335
control end        = 373
escape             = 27
return             = '\r'

alt x              = 301

F1                 = 315
F2                 = 316

file error message   = !display_message(&file_error_msg);
goto query           = !accept_text(&goto_msg,"");
load name query      = !accept_text(&load_from_msg, file_name);
no such file message = !accept_text(&nonexistent_msg, file_name);
overwrite query      = !display_message(&file_exists_msg);
save changes query   = !display_message(&changes_msg);
save name query      = !accept_text(&save_to_msg, file_name);
print file query     = !accept_text(&print_to_msg, file_name);
block query          = !accept_text(&block_msg,"");
decimals query       = !accept_text(&decimals_msg, "");
bad decimals message = !accept_text(&bad_decimals_msg,NULL);

[
//  sticky edit text
 ~allow macros
  default token type = void
 ~lines and columns
 ~diagnose errors
  reduction choices
  parser file name = "#.cpp"
]


grammar
 -> {top level command =update_status();}..., eof

top level command
 -> recalc request                    =recalc();
 -> utility menu, 'f' + 'F'           =toggle_formula_display();
 -> main menu, 'a'+'A'                =autocalc_flag = !autocalc_flag;
// -> edit request, edit text, return?  =set_cell_text();
 -> edit request, edit text, return   =set_cell_text();
 -> edit request, edit text, escape
 -> delete request                    =delete_cell();
 -> page up                           =page_up();
 -> page down                         =page_down();
 -> control left                      =scroll_left();
 -> control right                     =scroll_right();
 -> home                              =home();
 -> end                               =end();
 -> up                                =cursor_up();
 -> down                              =cursor_down();
 -> left                              =cursor_left();
 -> right                             =cursor_right();
 -> load file
 -> save file
 -> clear spreadsheet
 -> format
 -> exit                              =quit();
 -> error
 -> goto
 -> column menu, 'i' + 'I'            =insert_column();
 -> column menu, 'd' + 'D'            =delete_column();
 -> column width
 -> row menu, 'i' + 'I'               =insert_row();
 -> row menu, 'd' + 'D'               =delete_row();
 -> any menu, escape
 -> print menu, 'o' + 'O', print file name    =print();

any menu
 -> main menu
 -> spreadsheet menu
 -> utility menu
 -> column menu
 -> row menu

format
 -> format menu, 'c' + 'C', block                 =set_conversion(currency);
 -> format menu, 'g' + 'G', block                 =set_conversion(general);
 -> format menu, 'f' + 'F', digits spec:n, block  =set_decimals(n);
 -> label menu, how:h, block                      =set_alignment(h);

(int) how
 -> 'l' + 'L'  =LEFT;
 -> 'c' + 'C'  =CENTER;
 -> 'r' + 'R'  =RIGHT;

(int) digits spec, bad digits spec
 -> decimals query, edit number, return               =check_digits();
 -> bad digits spec, bad decimals message, edit number, return =check_digits();

recalc request
 -> F1
 -> utility menu, 'r' + 'R'

delete request
 -> delete
 -> main menu, 'd' + 'D'

goto
 -> main menu, 'g' + 'G', goto query, cell name      =go();

column width request
 -> column menu, 'w' + 'W'          =accept_text(&col_width_msg,"");

column width, column width request
 -> column width request, edit number, return    =set_column_width();

column width
 -> column width request, edit number, escape

cell name, bad cell name
 -> edit text, return                  =parse_cell_name();
 -> edit text, escape
 -> bad cell name, edit text, return   =parse_cell_name();
 -> bad cell name, edit text, escape

block, bad block
 -> block query, edit text, return     =parse_block();
 -> block query, edit text, escape
 -> bad block, edit text, return       =parse_block();
 -> bad block, edit text, escape

exit
 -> exit request, save changes

exit request
 -> main menu, 'q' + 'Q'
 -> alt x

load file
 -> spreadsheet menu, 'l' + 'L', save changes, load spreadsheet

save file
 -> spreadsheet menu, 's' + 'S', save spreadsheet

save changes
 -> not changed
 -> changed, save changes query, no
 -> changed, save changes query, yes, save spreadsheet

changed, not changed
 -> !STATUS(n_changes, changed);

save spreadsheet
 -> save name query, write file
 -> save name query, old file, overwrite query, no, save spreadsheet

load spreadsheet
 -> load name query, old file      =load_file();
 -> load name query, new file, no such file message, load spreadsheet

print file name
 -> print file query, new file
 -> print file query, old file, overwrite query, yes
 -> print file query, old file, overwrite query, no, print file name

new file, old file
 -> edit text, return                     =check_file_name();

write file, file error
 -> new file                       =write_file();
 -> old file, overwrite query, yes =write_file();

write file
 -> file error, file error message, any key

clear spreadsheet
 -> clear spreadsheet request, yes      =clear();
 -> clear spreadsheet request, no

clear spreadsheet request
 -> spreadsheet menu, 'c' + 'C'    =display_message(&clear_spreadsheet);

main menu
 -> '/'                            =display_menu(&main_menu);

spreadsheet menu
 -> main menu, 's' + 'S'           =display_menu(&spreadsheet_menu);

column menu
 -> main menu, 'c' + 'C'           =display_menu(&column_menu);

row menu
 -> main menu, 'r' + 'R'           =display_menu(&row_menu);

utility menu
 -> main menu, 'u' + 'U'           =display_menu(&utility_menu);

format menu
 -> main menu, 'f' + 'F'           =display_menu(&format_menu);

label menu
 -> format menu, 'l' + 'L'         =display_menu(&label_menu);

print menu
 -> spreadsheet menu, 'p' + 'P'    =pm_msg();
 -> print menu, 'w' + 'W' + 'n' + 'N'  =print_wide = !print_wide, pm_msg();
 -> print menu, 'l' + 'L'          =(print_border = !print_border),pm_msg();
 -> print menu, 'b' + 'B',
    block =print_block=TRUE,print_from=first_cell,print_to=last_cell,pm_msg();

edit request
 -> F2                             =init_cell_edit();
 -> main menu, 'e' + 'E'           =init_cell_edit();
 -> text character - '/':c         =init_text_input(c);
 -> ^S                             =init_text_input('ä');    //228
 -> ^P                             =init_text_input('ã');    //227

(void) edit text
 ->
 -> edit text, text character:c =insert_char(c);
 -> edit text, ^S       =insert_char(228);
 -> edit text, ^P       =insert_char(227);
 -> edit text, edit key

(void) edit number
 ->
 -> edit number, digit:d =insert_char(d);
 -> edit number, edit key

(void) edit key
 -> backspace           =backspace_char();
 -> delete              =delete_char();
 -> left                =text_cursor_left();
 -> right               =text_cursor_right();
 -> home                =text_cursor_home();
 -> end                 =text_cursor_end();
 -> error               =beep();

{
#include "ssd.h"

char text_buffer[100];
int text_index;
pair<int> text_cursor = {INPUT_LINE, 1};

#define GET_INPUT {int c;\
  PCB.input_code = ((c=getch()) != 0 ? c : getch()+256);}

#define SYNTAX_ERROR

#define STATUS(x,y) PCB.reduction_token = (x)?kb_##y##_token:kb_not_##y##_token

void beep(void) {
  sound(440);
  delay(75);
  nosound();
}

void accept_text(message *m, char *t) {
  display_message(m);
  init_text_edit(t);
}

void backspace_char(void) {
  if (text_cursor.col == 1) return;
  text_cursor_left();
  delete_char();
}

int check_digits(void){
  char *tb = text_buffer + 1;
  int n;
  for (n = 0; *tb;) n = 10*n + *tb++ - '0';
  if (n > 7) CHANGE_REDUCTION(bad_digits_spec);
  return n;
}

void delete_cell(void) {
  cell_pointer cp = ss[ac.ssc.row][ac.ssc.col];
  if (cp) free(cp);
  ss[ac.ssc.row][ac.ssc.col] = NULL;
  update_cell(ac.scc, ac.ssc);
  set_active_cell();
}

void delete_char(void) {
  strcpy(&text_buffer[text_cursor.col], &text_buffer[text_cursor.col+1]);
  display_field(
    text_cursor,
    SCREEN_WIDTH - text_cursor.col,
    LEFT,
    TEXT_COLOR,
    "%s",
    &text_buffer[text_cursor.col]
  );
  set_cursor(text_cursor);
}

void delete_column(void) {
  int i,j;
  new_column = ac.ssc.col;
  for (i = 0; i < MAXROWS; i++) if (ss[i][new_column]) free(ss[i][new_column]);
  for (i = new_column; i < max_col; i++)
    for (j = 0; j <= max_row; j++)
      ss[j][i] = ss[j][i+1];
  for (j = 0; j <= max_row; j++) ss[j][max_col] = NULL;
  max_col--;
  inserted_columns = -1;
  relabel(0,new_column);
  new_column = inserted_columns = 0;
}

void delete_row(void) {
  int i,j;
  new_row = ac.ssc.row;
  for (i = 0; i < MAXCOLS; i++) if (ss[new_row][i]) free(ss[new_row][i]);
  for (i = new_row; i < max_row; i++)
    for (j = 0; j <= max_col; j++)
      ss[i][j] = ss[i+1][j];
  for (j = 0; j <= max_col; j++) ss[max_row][j] = NULL;
  max_row--;
  inserted_rows = -1;
  relabel(new_row,0);
  new_row = inserted_rows = 0;
}

void init_cell_edit(void) {
  cell_pointer cp = ss[ac.ssc.row][ac.ssc.col];
  if (cp) strcpy(text_buffer+1, cp->text);
  else text_buffer[1] = 0;
  text_cursor.col = strlen(text_buffer+1) + 1;
  textattr(TEXT_COLOR);
  _setcursortype(_NORMALCURSOR);
  input_msg.msg = text_buffer+1;
  display_message(&input_msg);
  set_cursor(text_cursor);
}

void init_text_edit(char *c) {
  if (c) strcpy(text_buffer+1, c);
  text_cursor.col = strlen(text_buffer+1) + 1;
  textattr(TEXT_COLOR);
  _setcursortype(_NORMALCURSOR);
  input_msg.msg = text_buffer+1;
  display_message(&input_msg);
  set_cursor(text_cursor);
}

void init_text_input(int c) {
  textattr(TEXT_COLOR);
  _setcursortype(_NORMALCURSOR);
  text_buffer[text_cursor.col = 1] = c;
  set_cursor(text_cursor);
  putch(c);
  text_buffer[++text_cursor.col] = 0;
}

void insert_char(int c){
  int n = strlen(&text_buffer[text_cursor.col]);
  memmove(&text_buffer[text_cursor.col+1], &text_buffer[text_cursor.col], n+1);
  text_buffer[81] = 0;
  text_buffer[text_cursor.col++] = c;
  putch(c);
  display_field(text_cursor, n, LEFT, TEXT_COLOR, &text_buffer[text_cursor.col]);
  set_cursor(text_cursor);
}

void insert_column(void) {
  int i,j;
  if (max_col + 1 >= MAXCOLS) {
    for (i = 0; i < MAXROWS; i++) if (ss[i][max_col]) free(ss[i][max_col]);
  }
  max_col++;
  new_column = ac.ssc.col;
  for (i = max_col; i > new_column; i--)
    for (j = 0; j <= max_row; j++)
      ss[j][i] = ss[j][i-1];
  for (j = 0; j < MAXROWS; j++) ss[j][new_column] = NULL;
  inserted_columns = 1;
  relabel(0,new_column);
  new_column = inserted_columns = 0;
}

void insert_row(void) {
  int i,j;
  if (max_row + 1 >= MAXROWS) {
    for (i = 0; i < MAXCOLS; i++) if (ss[max_row][i]) free(ss[max_row][i]);
  }
  max_row++;
  new_row = ac.ssc.row;
  for (i = max_row; i > new_row; i--)
    for (j = 0; j <= max_col; j++)
      ss[i][j] = ss[i-1][j];
  for (j = 0; j < MAXCOLS; j++) ss[new_row][j] = NULL;
  inserted_rows = 1;
  relabel(new_row,0);
  new_row = inserted_rows = 0;
}

void recalc(void) {
  int i,j;
  recalc_flag = 1;
  circular_flag = 0;
  for (i = 0; i <= max_row; i++) for (j = 0; j <= max_col; j++) {
    cell_pointer cp = ss[i][j];

    if (cp == NULL || cp->type != formula) continue;
    if (cp->recalc == recalc_count) eval(cp);
  }
  recalc_count += 2;
  recalc_flag = 0;
  update_screen();
  set_active_cell();
}

void relabel(int row, int col) {
  int i,j;

  n_changes++;
  for (i = row; i <= max_row; i++) for (j = col; j <= max_col; j++) {
    cell_pointer cp = ss[i][j];

    if (cp == NULL || cp->type != formula) continue;
    relabel_formula(cp);
  }
  update_screen();
  set_active_cell();
}

void set_cell_text(void) {
  char *tb = text_buffer + 1;
  cell_pointer cp = realloc(
    ss[ac.ssc.row][ac.ssc.col],
    sizeof(cell_descriptor) + strlen(tb)
  );
  n_changes++;
  assert(cp);
  if (ac.ssc.row > max_row) max_row = ac.ssc.row;
  if (ac.ssc.col > max_col) max_col = ac.ssc.col;
  strcpy(cp->text, tb);
  cp->error = 0;
  ss[ac.ssc.row][ac.ssc.col] = cp;
  cp->recalc = recalc_count;
  _setcursortype(_NOCURSOR);
  eval(cp);
  if (cp->type != text && autocalc_flag) recalc();
  else {
    update_cell(ac.scc, ac.ssc);
    set_active_cell();
  }
}

void text_cursor_end(void) {
  while (text_buffer[text_cursor.col]) {
    text_cursor.col++;
  }
  set_cursor(text_cursor);
}

void text_cursor_home(void) {
  if (text_cursor.col == 1) return;
  text_cursor.col = 1;
  set_cursor(text_cursor);
}

void text_cursor_left(void) {
  if (text_cursor.col == 1) return;
  text_cursor.col--;
  set_cursor(text_cursor);
}

void text_cursor_right(void) {
  if (text_buffer[text_cursor.col] == 0) return;
  if (text_cursor.col >= SCREEN_WIDTH) return;
  text_cursor.col++;
  set_cursor(text_cursor);
}

void toggle_formula_display(void) {
  formula_flag = !formula_flag;
  display_message(&form_msg);
  update_screen();
  set_active_cell();
}

}