| /**************************************************************************** |
| * apps/interpreters/bas/bas_token.l |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /* Tokens and token sequence arrays. */ |
| %{ |
| #include <nuttx/config.h> |
| |
| #include <assert.h> |
| #include <ctype.h> |
| #include <float.h> |
| #include <limits.h> |
| #include <math.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <termios.h> |
| |
| #include "bas_auto.h" |
| #include "bas_token.h" |
| #include "bas_statement.h" |
| |
| static int g_matchdata; |
| static int g_backslash_colon; |
| static int g_uppercase; |
| int yylex(void); |
| static struct Token *g_cur; |
| |
| static void string(const char *text) |
| { |
| if (g_cur) |
| { |
| const char *t; |
| char *q; |
| size_t l; |
| |
| for (t=text+1,l=0; *(t+1); ++t,++l) |
| { |
| if (*t=='"') ++t; |
| } |
| g_cur->u.string=malloc(sizeof(struct String)); |
| String_size(String_new(g_cur->u.string),l); |
| for (t=text+1,q=g_cur->u.string->character; *(t+1); ++t,++q) |
| { |
| *q=*t; |
| if (*t=='"') ++t; |
| } |
| } |
| } |
| |
| static void string2(void) |
| { |
| if (g_cur) |
| { |
| char *t,*q; |
| size_t l; |
| |
| for (t=yytext+1,l=0; *t; ++t,++l) |
| { |
| if (*t=='"') ++t; |
| } |
| g_cur->u.string=malloc(sizeof(struct String)); |
| String_size(String_new(g_cur->u.string),l); |
| for (t=yytext+1,q=g_cur->u.string->character; *t; ++t,++q) |
| { |
| *q=*t; |
| if (*t=='"') ++t; |
| } |
| } |
| } |
| |
| %} |
| /* flex options and definitions */ |
| %option noyywrap |
| %option nounput |
| %x DATAINPUT ELSEIF IMAGEFMT |
| REAL ([0-9]+("!"|"#"))|([0-9]+\.[0-9]*(e("+"|"-")?[0-9]+)?("!"|"#")?)|([0-9]*\.[0-9]+(e("+"|"-")?[0-9]+)?("!"|"#")?|([0-9]+e("+"|"-")?[0-9]+("!"|"#")?)) |
| INTEGER [0-9]+%? |
| HEXINTEGER &H[0-9A-F]+ |
| OCTINTEGER &O[0-7]+ |
| IDENTIFIER ("fn"[ \t]+)?[A-Z][A-Z_0-9\.]*("$"|"%"|"#")? |
| STRING \"([^"]|\"\")*\" |
| STRING2 \"([^"]|\"\")*$ |
| REM rem([^0-9A-Z_\.\n][^\n]*)? |
| QUOTE ("'"|"!")[^\n]* |
| ENDIF end[ \t]*if |
| ENDPROC end[ \t]*proc |
| ENDSELECT end[ \t]*select |
| DOUNTIL do[ \t]+until |
| DOWHILE do[ \t]+while |
| EXITDO exit[ \t]+do |
| EXITFOR exit[ \t]+for |
| LINEINPUT (line[ \t]+input)|linput |
| LOOPUNTIL loop[ \t]+until |
| DATAITEM [^ \t\n,:][^,:\n]* |
| ONERROR on[ \t]+error |
| ONERROROFF on[ \t]+error[ \t]+off |
| ONERRORGOTO0 on[ \t]+error[ \t]+goto[ \t]+0 |
| SELECTCASE select[ \t]+case |
| |
| %% |
| /* flex rules */ |
| if (g_matchdata) BEGIN(DATAINPUT); |
| |
| "#" return T_CHANNEL; |
| {REAL} { |
| int overflow; |
| double d; |
| |
| d=Value_vald(yytext,(char**)0,&overflow); |
| if (overflow) |
| { |
| if (g_cur) g_cur->u.junk=yytext[0]; |
| yyless(1); |
| return T_JUNK; |
| } |
| if (g_cur) g_cur->u.real=d; |
| return T_REAL; |
| } |
| {INTEGER} { |
| int overflow; |
| long int n; |
| |
| n=Value_vali(yytext,(char**)0,&overflow); |
| if (overflow) |
| { |
| double d; |
| |
| d=Value_vald(yytext,(char**)0,&overflow); |
| if (overflow) |
| { |
| if (g_cur) g_cur->u.junk=yytext[0]; |
| yyless(1); |
| return T_JUNK; |
| } |
| if (g_cur) g_cur->u.real=d; |
| return T_REAL; |
| } |
| if (g_cur) g_cur->u.integer=n; |
| return T_INTEGER; |
| } |
| {HEXINTEGER} { |
| int overflow; |
| long int n; |
| |
| n=Value_vali(yytext,(char**)0,&overflow); |
| if (overflow) |
| { |
| if (g_cur) g_cur->u.junk=yytext[0]; |
| yyless(1); |
| return T_JUNK; |
| } |
| if (g_cur) g_cur->u.hexinteger=n; |
| return T_HEXINTEGER; |
| } |
| {OCTINTEGER} { |
| int overflow; |
| long int n; |
| |
| n=Value_vali(yytext,(char**)0,&overflow); |
| if (overflow) |
| { |
| if (g_cur) g_cur->u.junk=yytext[0]; |
| yyless(1); |
| return T_JUNK; |
| } |
| if (g_cur) g_cur->u.octinteger=n; |
| return T_OCTINTEGER; |
| } |
| {STRING} string(yytext); return T_STRING; |
| {STRING2} string2(); return T_STRING; |
| "("|"[" return T_OP; |
| ")"|"]" return T_CP; |
| "*" return T_MULT; |
| "+" return T_PLUS; |
| "-" return T_MINUS; |
| "," return T_COMMA; |
| "/" return T_DIV; |
| "\\" { |
| if (g_backslash_colon) |
| { |
| if (g_cur) g_cur->statement=stmt_COLON_EOL; |
| return T_COLON; |
| } |
| return T_IDIV; |
| } |
| ":" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_COLON_EOL; |
| } |
| return T_COLON; |
| } |
| ";" return T_SEMICOLON; |
| "<" return T_LT; |
| "<=" return T_LE; |
| "=<" return T_LE; |
| "<>"|"><" return T_NE; |
| "=" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_EQ_FNRETURN_FNEND; |
| } |
| return T_EQ; |
| } |
| ">" return T_GT; |
| ">=" return T_GE; |
| "=>" return T_GE; |
| "^" return T_POW; |
| "access"[ \t]+"read" return T_ACCESS_READ; |
| "access"[ \t]+"read"[ \t]+"write" return T_ACCESS_READ_WRITE; |
| "access"[ \t]+"write" return T_ACCESS_WRITE; |
| "and" return T_AND; |
| "as" return T_AS; |
| "call" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CALL; |
| } |
| return T_CALL; |
| } |
| "case"[ \t]+"else" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CASE; |
| g_cur->u.casevalue=malloc(sizeof(struct Casevalue)); |
| } |
| return T_CASEELSE; |
| } |
| "case" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CASE; |
| g_cur->u.casevalue=malloc(sizeof(struct Casevalue)); |
| } |
| return T_CASEVALUE; |
| } |
| "chdir" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CHDIR_MKDIR; |
| } |
| return T_CHDIR; |
| } |
| "clear" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CLEAR; |
| } |
| return T_CLEAR; |
| } |
| "close" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CLOSE; |
| } |
| return T_CLOSE; |
| } |
| "close"/"#" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CLOSE; |
| } |
| return T_CLOSE; |
| } |
| "cls"|"home" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CLS; |
| } |
| return T_CLS; |
| } |
| "color" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_COLOR; |
| } |
| return T_COLOR; |
| } |
| "con" return T_CON; |
| "copy" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_COPY_RENAME; |
| } |
| return T_COPY; |
| } |
| "data"|"d." { |
| BEGIN(DATAINPUT); |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DATA; |
| } |
| return T_DATA; |
| } |
| <DATAINPUT>{STRING} string(yytext); return T_STRING; |
| <DATAINPUT>{STRING2} string2(); return T_STRING; |
| <DATAINPUT>"," return T_COMMA; |
| <DATAINPUT>{DATAITEM} { |
| if (g_cur) g_cur->u.datainput=strcpy(malloc(strlen(yytext)+1),yytext); |
| return T_DATAINPUT; |
| } |
| <DATAINPUT>[ \t]+ |
| <DATAINPUT>\n BEGIN(INITIAL); |
| <DATAINPUT>: BEGIN(INITIAL); return T_COLON; |
| "dec" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEC_INC; |
| } |
| return T_DEC; |
| } |
| "defdbl" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEFINT_DEFDBL_DEFSTR; |
| } |
| return T_DEFDBL; |
| } |
| "defint" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEFINT_DEFDBL_DEFSTR; |
| } |
| return T_DEFINT; |
| } |
| "defstr" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEFINT_DEFDBL_DEFSTR; |
| } |
| return T_DEFSTR; |
| } |
| "def"/[ \t]+fn[ \t]*[A-Z_0-9\.] { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEFFN_DEFPROC_FUNCTION_SUB; |
| g_cur->u.localSyms=(struct Symbol*)0; |
| } |
| return T_DEFFN; |
| } |
| "def"/[ \t]+proc[A-Z_0-9\.] { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEFFN_DEFPROC_FUNCTION_SUB; |
| g_cur->u.localSyms=(struct Symbol*)0; |
| } |
| return T_DEFPROC; |
| } |
| "delete" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DELETE; |
| } |
| return T_DELETE; |
| } |
| "dim" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DIM; |
| } |
| return T_DIM; |
| } |
| "display" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DISPLAY; |
| } |
| return T_DISPLAY; |
| } |
| "do" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DO; |
| } |
| return T_DO; |
| } |
| {DOUNTIL} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DOcondition; |
| } |
| return T_DOUNTIL; |
| } |
| {DOWHILE} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DOcondition; |
| } |
| return T_DOWHILE; |
| } |
| "edit" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_EDIT; |
| } |
| return T_EDIT; |
| } |
| "else"|"el." { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ELSE_ELSEIFELSE; |
| } |
| return T_ELSE; |
| } |
| "else"/"if" { |
| BEGIN(ELSEIF); |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ELSE_ELSEIFELSE; |
| } |
| return T_ELSEIFELSE; |
| } |
| <ELSEIF>"if" { |
| BEGIN(INITIAL); |
| if (g_cur) |
| { |
| g_cur->statement=stmt_IF_ELSEIFIF; |
| } |
| return T_ELSEIFIF; |
| } |
| end[ \t]+function { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ENDFN; |
| } |
| return T_ENDFN; |
| } |
| {ENDIF} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ENDIF; |
| } |
| return T_ENDIF; |
| } |
| {ENDPROC} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ENDPROC_SUBEND; |
| } |
| return T_ENDPROC; |
| } |
| {ENDSELECT} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ENDSELECT; |
| } |
| return T_ENDSELECT; |
| } |
| "end"[ \t]*"sub" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ENDPROC_SUBEND; |
| } |
| return T_SUBEND; |
| } |
| "end" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_END; |
| } |
| return T_END; |
| } |
| "environ" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ENVIRON; |
| } |
| return T_ENVIRON; |
| } |
| "erase" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ERASE; |
| } |
| return T_ERASE; |
| } |
| "eqv" return T_EQV; |
| {EXITDO} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_EXITDO; |
| } |
| return T_EXITDO; |
| } |
| {EXITFOR} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_EXITFOR; |
| } |
| return T_EXITFOR; |
| } |
| "exit"[ \t]+"function" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_FNEXIT; |
| } |
| return T_FNEXIT; |
| } |
| "exit"[ \t]+"sub" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_SUBEXIT; |
| } |
| return T_SUBEXIT; |
| } |
| "field" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_FIELD; |
| } |
| return T_FIELD; |
| } |
| "field"/"#" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_FIELD; |
| } |
| return T_FIELD; |
| } |
| "fnend" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_EQ_FNRETURN_FNEND; |
| } |
| return T_FNEND; |
| } |
| "fnreturn" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_EQ_FNRETURN_FNEND; |
| } |
| return T_FNRETURN; |
| } |
| "for" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_FOR; |
| } |
| return T_FOR; |
| } |
| "for"[ \t]+"input" return T_FOR_INPUT; |
| "for"[ \t]+"output" return T_FOR_OUTPUT; |
| "for"[ \t]+"append" return T_FOR_APPEND; |
| "for"[ \t]+"random" return T_FOR_RANDOM; |
| "for"[ \t]+"binary" return T_FOR_BINARY; |
| "function" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEFFN_DEFPROC_FUNCTION_SUB; |
| g_cur->u.localSyms=(struct Symbol*)0; |
| } |
| return T_FUNCTION; |
| } |
| "get" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_GET_PUT; |
| } |
| return T_GET; |
| } |
| "get"/"#" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_GET_PUT; |
| } |
| return T_GET; |
| } |
| "go"[ \t]*"sub" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_GOSUB; |
| } |
| return T_GOSUB; |
| } |
| "go"[ \t]*"to" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_RESUME_GOTO; |
| } |
| return T_GOTO; |
| } |
| "idn" return T_IDN; |
| "if" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_IF_ELSEIFIF; |
| } |
| return T_IF; |
| } |
| "image"[ \t]*/[^"\n \t] { |
| BEGIN(IMAGEFMT); |
| if (g_cur) |
| { |
| g_cur->statement=stmt_IMAGE; |
| } |
| return T_IMAGE; |
| } |
| <IMAGEFMT>.*$ { |
| BEGIN(INITIAL); |
| if (g_cur) |
| { |
| size_t l; |
| |
| l=strlen(yytext); |
| g_cur->u.string=malloc(sizeof(struct String)); |
| String_size(String_new(g_cur->u.string),l); |
| memcpy(g_cur->u.string->character,yytext,l); |
| } |
| return T_STRING; |
| } |
| "image" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_IMAGE; |
| } |
| return T_IMAGE; |
| } |
| "imp" return T_IMP; |
| "inc" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEC_INC; |
| } |
| return T_INC; |
| } |
| "input" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_INPUT; |
| } |
| return T_INPUT; |
| } |
| "input"/"#" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_INPUT; |
| } |
| return T_INPUT; |
| } |
| "inv" return T_INV; |
| "is" return T_IS; |
| "kill" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_KILL; |
| } |
| return T_KILL; |
| } |
| "let" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LET; |
| } |
| return T_LET; |
| } |
| "list" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LIST_LLIST; |
| } |
| return T_LIST; |
| } |
| "llist" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LIST_LLIST; |
| } |
| return T_LLIST; |
| } |
| "load" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LOAD; |
| } |
| return T_LOAD; |
| } |
| "local" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LOCAL; |
| } |
| return T_LOCAL; |
| } |
| "locate" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LOCATE; |
| } |
| return T_LOCATE; |
| } |
| "lock" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LOCK_UNLOCK; |
| } |
| return T_LOCK; |
| } |
| "lock"[ \t]+"read" return T_LOCK_READ; |
| "lock"[ \t]+"write" return T_LOCK_WRITE; |
| "loop" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LOOP; |
| } |
| return T_LOOP; |
| } |
| {LOOPUNTIL} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LOOPUNTIL; |
| } |
| return T_LOOPUNTIL; |
| } |
| "lprint" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_PRINT_LPRINT; |
| } |
| return T_LPRINT; |
| } |
| "lset" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LSET_RSET; |
| } |
| return T_LSET; |
| } |
| "mat"[ \t]+"input" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_MATINPUT; |
| } |
| return T_MATINPUT; |
| } |
| "mat"[ \t]+"print" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_MATPRINT; |
| } |
| return T_MATPRINT; |
| } |
| "mat"[ \t]+"read" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_MATREAD; |
| } |
| return T_MATREAD; |
| } |
| "mat"[ \t]+"redim" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_MATREDIM; |
| } |
| return T_MATREDIM; |
| } |
| "mat"[ \t]+"write" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_MATWRITE; |
| } |
| return T_MATWRITE; |
| } |
| "mat" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_MAT; |
| } |
| return T_MAT; |
| } |
| "mkdir" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_CHDIR_MKDIR; |
| } |
| return T_MKDIR; |
| } |
| "mod" return T_MOD; |
| "new" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_NEW; |
| } |
| return T_NEW; |
| } |
| "name" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_NAME; |
| } |
| return T_NAME; |
| } |
| "next" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_NEXT; |
| g_cur->u.next=malloc(sizeof(struct Next)); |
| } |
| return T_NEXT; |
| } |
| "not" return T_NOT; |
| {ONERROROFF} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ONERROROFF; |
| } |
| return T_ONERROROFF; |
| } |
| {ONERRORGOTO0} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ONERRORGOTO0; |
| } |
| return T_ONERRORGOTO0; |
| } |
| {ONERROR} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ONERROR; |
| } |
| return T_ONERROR; |
| } |
| "on" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ON; |
| g_cur->u.on.pcLength=1; |
| g_cur->u.on.pc=(struct Pc*)0; |
| } |
| return T_ON; |
| } |
| "open" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_OPEN; |
| } |
| return T_OPEN; |
| } |
| "option"[ \t]+"base" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_OPTIONBASE; |
| } |
| return T_OPTIONBASE; |
| } |
| "option"[ \t]+"run" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_OPTIONRUN; |
| } |
| return T_OPTIONRUN; |
| } |
| "option"[ \t]+"stop" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_OPTIONSTOP; |
| } |
| return T_OPTIONSTOP; |
| } |
| "or" return T_OR; |
| "out" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_OUT_POKE; |
| } |
| return T_OUT; |
| } |
| "print"|"p."|"?" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_PRINT_LPRINT; |
| } |
| return T_PRINT; |
| } |
| ("print"|"p."|"?")/"#" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_PRINT_LPRINT; |
| } |
| return T_PRINT; |
| } |
| "poke" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_OUT_POKE; |
| } |
| return T_POKE; |
| } |
| "put" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_GET_PUT; |
| } |
| return T_PUT; |
| } |
| "put"/"#" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_GET_PUT; |
| } |
| return T_PUT; |
| } |
| "randomize" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_RANDOMIZE; |
| } |
| return T_RANDOMIZE; |
| } |
| "read" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_READ; |
| } |
| return T_READ; |
| } |
| "renum"|"ren." { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_RENUM; |
| } |
| return T_RENUM; |
| } |
| "repeat"|"rep." { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_REPEAT; |
| } |
| return T_REPEAT; |
| } |
| "restore"|"res." { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_RESTORE; |
| } |
| return T_RESTORE; |
| } |
| "resume" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_RESUME_GOTO; |
| } |
| return T_RESUME; |
| } |
| "return"|"r." { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_RETURN; |
| } |
| return T_RETURN; |
| } |
| "rset" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LSET_RSET; |
| } |
| return T_RSET; |
| } |
| "run" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_RUN; |
| } |
| return T_RUN; |
| } |
| "save" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_SAVE; |
| } |
| return T_SAVE; |
| } |
| {SELECTCASE} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_SELECTCASE; |
| g_cur->u.selectcase=malloc(sizeof(struct Selectcase)); |
| } |
| return T_SELECTCASE; |
| } |
| "shared" return T_SHARED; |
| "shell" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_SHELL; |
| } |
| return T_SHELL; |
| } |
| "sleep" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_SLEEP; |
| } |
| return T_SLEEP; |
| } |
| "spc" return T_SPC; |
| "step" return T_STEP; |
| "stop" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_STOP; |
| } |
| return T_STOP; |
| } |
| "sub"[ \t]*"end" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ENDPROC_SUBEND; |
| } |
| return T_SUBEND; |
| } |
| "sub"[ \t]*"exit" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_SUBEXIT; |
| } |
| return T_SUBEXIT; |
| } |
| "sub" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_DEFFN_DEFPROC_FUNCTION_SUB; |
| g_cur->u.localSyms=(struct Symbol*)0; |
| } |
| return T_SUB; |
| } |
| "swap" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_SWAP; |
| } |
| return T_SWAP; |
| } |
| "system"|"bye" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_SYSTEM; |
| } |
| return T_SYSTEM; |
| } |
| "then"|"th." return T_THEN; |
| "tab" return T_TAB; |
| "to" return T_TO; |
| "trn" return T_TRN; |
| "troff" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_TROFF; |
| } |
| return T_TROFF; |
| } |
| "tron" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_TRON; |
| } |
| return T_TRON; |
| } |
| "truncate" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_TRUNCATE; |
| } |
| return T_TRUNCATE; |
| } |
| "unlock" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LOCK_UNLOCK; |
| } |
| return T_UNLOCK; |
| } |
| "unnum" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_UNNUM; |
| } |
| return T_UNNUM; |
| } |
| "until" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_UNTIL; |
| } |
| return T_UNTIL; |
| } |
| "using" return T_USING; |
| "wait" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_WAIT; |
| } |
| return T_WAIT; |
| } |
| "wend" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_WEND; |
| g_cur->u.whilepc=malloc(sizeof(struct Pc)); |
| } |
| return T_WEND; |
| } |
| "while" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_WHILE; |
| g_cur->u.afterwend=malloc(sizeof(struct Pc)); |
| } |
| return T_WHILE; |
| } |
| "width" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_WIDTH; |
| } |
| return T_WIDTH; |
| } |
| "width"/"#" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_WIDTH; |
| } |
| return T_WIDTH; |
| } |
| "write" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_WRITE; |
| } |
| return T_WRITE; |
| } |
| "write"/"#" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_WRITE; |
| } |
| return T_WRITE; |
| } |
| "xor" return T_XOR; |
| "xref" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_XREF; |
| } |
| return T_XREF; |
| } |
| "zer" return T_ZER; |
| "zone" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_ZONE; |
| } |
| return T_ZONE; |
| } |
| {REM} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_QUOTE_REM; |
| g_cur->u.rem=strcpy(malloc(strlen(yytext+3)+1),yytext+3); |
| } |
| return T_REM; |
| } |
| "rename" { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_COPY_RENAME; |
| } |
| return T_RENAME; |
| } |
| {QUOTE} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_QUOTE_REM; |
| strcpy(g_cur->u.rem=malloc(strlen(yytext+1)+1),yytext+1); |
| } |
| return T_QUOTE; |
| } |
| {LINEINPUT} { |
| if (g_cur) |
| { |
| g_cur->statement=stmt_LINEINPUT; |
| } |
| return T_LINEINPUT; |
| } |
| {IDENTIFIER} { |
| if (g_cur) |
| { |
| size_t len; |
| char *s; |
| int fn; |
| |
| g_cur->statement=stmt_IDENTIFIER; |
| if (tolower(yytext[0])=='f' && tolower(yytext[1])=='n') |
| { |
| for (len=2,s=&yytext[2]; *s==' ' || *s=='\t'; ++s); |
| fn=1; |
| } |
| else |
| { |
| len=0; |
| s=yytext; |
| fn=0; |
| } |
| len+=strlen(s); |
| g_cur->u.identifier=malloc(offsetof(struct Identifier,name)+len+1); |
| if (fn) |
| { |
| memcpy(g_cur->u.identifier->name,yytext,2); |
| strcpy(g_cur->u.identifier->name+2,s); |
| } |
| else |
| { |
| strcpy(g_cur->u.identifier->name,s); |
| } |
| switch (yytext[yyleng-1]) |
| { |
| case '$': g_cur->u.identifier->defaultType=V_STRING; break; |
| case '%': g_cur->u.identifier->defaultType=V_INTEGER; break; |
| default: g_cur->u.identifier->defaultType=V_REAL; break; |
| } |
| } |
| return T_IDENTIFIER; |
| } |
| [ \t\n]+ |
| . { |
| if (g_cur) g_cur->u.junk=yytext[0]; |
| return T_JUNK; |
| } |
| |
| %% |
| |
| int g_token_property[T_LASTTOKEN]; |
| |
| struct Token *Token_newCode(const char *ln) |
| { |
| int l,lasttok,thistok,addNumber=0,sawif; |
| struct Token *result; |
| YY_BUFFER_STATE buf; |
| |
| g_cur=(struct Token*)0; |
| buf=yy_scan_string(ln); |
| /* determine number of tokens */ |
| g_matchdata=sawif=0; |
| for (lasttok=T_EOL,l=1; (thistok=yylex()); ++l) |
| { |
| if (l==1 && thistok!=T_INTEGER) { addNumber=1; ++l; } |
| if ((lasttok==T_THEN || lasttok==T_ELSE) && thistok==T_INTEGER) ++l; |
| if (thistok==T_IF) sawif=1; |
| if (thistok==T_THEN) sawif=0; |
| if (thistok==T_GOTO && sawif) ++l; |
| lasttok=thistok; |
| } |
| if (l==1) { addNumber=1; ++l; } |
| |
| yy_delete_buffer(buf); |
| g_cur=result=malloc(sizeof(struct Token)*l); |
| if (addNumber) |
| { |
| g_cur->type=T_UNNUMBERED; |
| ++g_cur; |
| } |
| buf=yy_scan_string(ln); |
| lasttok=T_EOL; |
| g_matchdata=sawif=0; |
| while (g_cur->statement=NULL,(g_cur->type=yylex())) |
| { |
| if (g_cur->type==T_IF) sawif=1; |
| if (g_cur->type==T_THEN) sawif=0; |
| if (g_cur->type==T_GOTO && sawif) |
| { |
| sawif=0; |
| *(g_cur+1)=*g_cur; |
| g_cur->type=T_THEN; |
| lasttok=T_GOTO; |
| g_cur+=2; |
| } |
| else if ((lasttok==T_THEN || lasttok==T_ELSE) && g_cur->type==T_INTEGER) |
| { |
| *(g_cur+1)=*g_cur; |
| g_cur->type=T_GOTO; |
| g_cur->statement=stmt_RESUME_GOTO; |
| lasttok=T_INTEGER; |
| g_cur+=2; |
| } |
| else |
| { |
| lasttok=g_cur->type; |
| ++g_cur; |
| } |
| } |
| g_cur->type=T_EOL; |
| g_cur->statement=stmt_COLON_EOL; |
| yy_delete_buffer(buf); |
| return result; |
| } |
| |
| struct Token *Token_newData(const char *ln) |
| { |
| int l; |
| struct Token *result; |
| YY_BUFFER_STATE buf; |
| |
| g_cur=(struct Token*)0; |
| buf=yy_scan_string(ln); |
| g_matchdata=1; |
| for (l=1; yylex(); ++l); |
| yy_delete_buffer(buf); |
| g_cur=result=malloc(sizeof(struct Token)*l); |
| buf=yy_scan_string(ln); |
| g_matchdata=1; |
| while (g_cur->statement=NULL,(g_cur->type=yylex())) ++g_cur; |
| g_cur->type=T_EOL; |
| g_cur->statement=stmt_COLON_EOL; |
| yy_delete_buffer(buf); |
| return result; |
| } |
| |
| void Token_destroy(struct Token *token) |
| { |
| struct Token *r=token; |
| |
| do |
| { |
| switch (r->type) |
| { |
| case T_ACCESS_READ: break; |
| case T_ACCESS_WRITE: break; |
| case T_AND: break; |
| case T_AS: break; |
| case T_CALL: break; |
| case T_CASEELSE: |
| case T_CASEVALUE: free(r->u.casevalue); break; |
| case T_CHANNEL: break; |
| case T_CHDIR: break; |
| case T_CLEAR: break; |
| case T_CLOSE: break; |
| case T_CLS: break; |
| case T_COLON: break; |
| case T_COLOR: break; |
| case T_COMMA: break; |
| case T_CON: break; |
| case T_COPY: break; |
| case T_CP: break; |
| case T_DATA: break; |
| case T_DATAINPUT: free(r->u.datainput); break; |
| case T_DEC: break; |
| case T_DEFFN: break; |
| case T_DEFDBL: break; |
| case T_DEFINT: break; |
| case T_DEFPROC: break; |
| case T_DEFSTR: break; |
| case T_DELETE: break; |
| case T_DIM: break; |
| case T_DISPLAY: break; |
| case T_DIV: break; |
| case T_DO: break; |
| case T_DOUNTIL: break; |
| case T_DOWHILE: break; |
| case T_EDIT: break; |
| case T_ELSE: break; |
| case T_ELSEIFELSE: break; |
| case T_ELSEIFIF: break; |
| case T_END: break; |
| case T_ENDFN: break; |
| case T_ENDIF: break; |
| case T_ENDPROC: break; |
| case T_ENDSELECT: break; |
| case T_ENVIRON: break; |
| case T_EOL: break; |
| case T_EQ: break; |
| case T_EQV: break; |
| case T_ERASE: break; |
| case T_EXITDO: break; |
| case T_EXITFOR: break; |
| case T_FIELD: break; |
| case T_FNEND: break; |
| case T_FNEXIT: break; |
| case T_FNRETURN: break; |
| case T_FOR: break; |
| case T_FOR_INPUT: break; |
| case T_FOR_OUTPUT: break; |
| case T_FOR_APPEND: break; |
| case T_FOR_RANDOM: break; |
| case T_FOR_BINARY: break; |
| case T_FUNCTION: break; |
| case T_GE: break; |
| case T_GET: break; |
| case T_GOSUB: break; |
| case T_GOTO: break; |
| case T_GT: break; |
| case T_HEXINTEGER: break; |
| case T_OCTINTEGER: break; |
| case T_IDENTIFIER: free(r->u.identifier); break; |
| case T_IDIV: break; |
| case T_IDN: break; |
| case T_IF: break; |
| case T_IMAGE: break; |
| case T_IMP: break; |
| case T_INC: break; |
| case T_INPUT: break; |
| case T_INTEGER: break; |
| case T_INV: break; |
| case T_IS: break; |
| case T_JUNK: break; |
| case T_KILL: break; |
| case T_LE: break; |
| case T_LET: break; |
| case T_LINEINPUT: break; |
| case T_LIST: break; |
| case T_LLIST: break; |
| case T_LOAD: break; |
| case T_LOCAL: break; |
| case T_LOCATE: break; |
| case T_LOCK: break; |
| case T_LOCK_READ: break; |
| case T_LOCK_WRITE: break; |
| case T_LOOP: break; |
| case T_LOOPUNTIL: break; |
| case T_LPRINT: break; |
| case T_LSET: break; |
| case T_LT: break; |
| case T_MAT: break; |
| case T_MATINPUT: break; |
| case T_MATPRINT: break; |
| case T_MATREAD: break; |
| case T_MATREDIM: break; |
| case T_MATWRITE: break; |
| case T_MINUS: break; |
| case T_MKDIR: break; |
| case T_MOD: break; |
| case T_MULT: break; |
| case T_NAME: break; |
| case T_NE: break; |
| case T_NEW: break; |
| case T_NEXT: free(r->u.next); break; |
| case T_NOT: break; |
| case T_ON: if (r->u.on.pc) free(r->u.on.pc); break; |
| case T_ONERROR: break; |
| case T_ONERRORGOTO0: break; |
| case T_ONERROROFF: break; |
| case T_OP: break; |
| case T_OPEN: break; |
| case T_OPTIONBASE: break; |
| case T_OPTIONRUN: break; |
| case T_OPTIONSTOP: break; |
| case T_OR: break; |
| case T_OUT: break; |
| case T_PLUS: break; |
| case T_POKE: break; |
| case T_POW: break; |
| case T_PRINT: break; |
| case T_PUT: break; |
| case T_QUOTE: free(r->u.rem); break; |
| case T_RANDOMIZE: break; |
| case T_READ: break; |
| case T_REAL: break; |
| case T_REM: free(r->u.rem); break; |
| case T_RENAME: break; |
| case T_RENUM: break; |
| case T_REPEAT: break; |
| case T_RESTORE: break; |
| case T_RESUME: break; |
| case T_RETURN: break; |
| case T_RSET: break; |
| case T_RUN: break; |
| case T_SAVE: break; |
| case T_SELECTCASE: free(r->u.selectcase); break; |
| case T_SEMICOLON: break; |
| case T_SHARED: break; |
| case T_SHELL: break; |
| case T_SLEEP: break; |
| case T_SPC: break; |
| case T_STEP: break; |
| case T_STOP: break; |
| case T_STRING: String_destroy(r->u.string); free(r->u.string); break; |
| case T_SUB: break; |
| case T_SUBEND: break; |
| case T_SUBEXIT: break; |
| case T_SWAP: break; |
| case T_SYSTEM: break; |
| case T_TAB: break; |
| case T_THEN: break; |
| case T_TO: break; |
| case T_TRN: break; |
| case T_TROFF: break; |
| case T_TRON: break; |
| case T_TRUNCATE: break; |
| case T_UNLOCK: break; |
| case T_UNNUM: break; |
| case T_UNNUMBERED: break; |
| case T_UNTIL: break; |
| case T_USING: break; |
| case T_WAIT: break; |
| case T_WEND: free(r->u.whilepc); break; |
| case T_WHILE: free(r->u.afterwend); break; |
| case T_WIDTH: break; |
| case T_WRITE: break; |
| case T_XOR: break; |
| case T_XREF: break; |
| case T_ZER: break; |
| case T_ZONE: break; |
| default: assert(0); |
| } |
| } while ((r++)->type!=T_EOL); |
| free(token); |
| } |
| |
| struct String *Token_toString(struct Token *token, struct Token *spaceto, struct String *s, int *indent, int width) |
| { |
| int ns=0,infn=0; |
| int thisindent=0,thisnotindent=0,nextindent=0; |
| size_t oldlength=s->length; |
| struct Token *t; |
| static struct |
| { |
| const char *text; |
| char space; |
| } table[]= |
| { |
| /* 0 */ {(const char*)0,-1}, |
| /* T_ACCESS_READ */ {"access read",1}, |
| /* T_ACCESS_READ_WRITE */ {"access read write",1}, |
| /* T_ACCESS_WRITE */ {"access write",1}, |
| /* T_AND */ {"and",1}, |
| /* T_AS */ {"as",1}, |
| /* T_CALL */ {"call",1}, |
| /* T_CASEELSE */ {"case else",1}, |
| /* T_CASEVALUE */ {"case",1}, |
| /* T_CHANNEL */ {"#",0}, |
| /* T_CHDIR */ {"chdir",1}, |
| /* T_CLEAR */ {"clear",1}, |
| /* T_CLOSE */ {"close",1}, |
| /* T_CLS */ {"cls",1}, |
| /* T_COLON */ {":",1}, |
| /* T_COLOR */ {"color",1}, |
| /* T_COMMA */ {",",0}, |
| /* T_CON */ {"con",0}, |
| /* T_COPY */ {"copy",1}, |
| /* T_CP */ {")",0}, |
| /* T_DATA */ {"data",1}, |
| /* T_DATAINPUT */ {(const char*)0,0}, |
| /* T_DEC */ {"dec",1}, |
| /* T_DEFDBL */ {"defdbl",1}, |
| /* T_DEFFN */ {"def",1}, |
| /* T_DEFINT */ {"defint",1}, |
| /* T_DEFPROC */ {"def",1}, |
| /* T_DEFSTR */ {"defstr",1}, |
| /* T_DELETE */ {"delete",1}, |
| /* T_DIM */ {"dim",1}, |
| /* T_DISPLAY */ {"display",1}, |
| /* T_DIV */ {"/",0}, |
| /* T_DO */ {"do",1}, |
| /* T_DOUNTIL */ {"do until",1}, |
| /* T_DOWHILE */ {"do while",1}, |
| /* T_EDIT */ {"edit",1}, |
| /* T_ELSE */ {"else",1}, |
| /* T_ELSEIFELSE */ {"elseif",1}, |
| /* T_ELSEIFIF */ {(const char*)0,0}, |
| /* T_END */ {"end",1}, |
| /* T_ENDFN */ {"end function",1}, |
| /* T_ENDIF */ {"end if",1}, |
| /* T_ENDPROC */ {"end proc",1}, |
| /* T_ENDSELECT */ {"end select",1}, |
| /* T_ENVIRON */ {"environ",1}, |
| /* T_EOL */ {"\n",0}, |
| /* T_EQ */ {"=",0}, |
| /* T_EQV */ {"eqv",0}, |
| /* T_ERASE */ {"erase",1}, |
| /* T_EXITDO */ {"exit do",1}, |
| /* T_EXITFOR */ {"exit for",1}, |
| /* T_FIELD */ {"field",1}, |
| /* T_FNEND */ {"fnend",1}, |
| /* T_FNEXIT */ {"exit function",1}, |
| /* T_FNRETURN */ {"fnreturn",1}, |
| /* T_FOR */ {"for",1}, |
| /* T_FOR_INPUT */ {"for input",1}, |
| /* T_FOR_OUTPUT */ {"for output",1}, |
| /* T_FOR_APPEND */ {"for append",1}, |
| /* T_FOR_RANDOM */ {"for random",1}, |
| /* T_FOR_BINARY */ {"for binary",1}, |
| /* T_FUNCTION */ {"function",1}, |
| /* T_GE */ {">=",0}, |
| /* T_GET */ {"get",1}, |
| /* T_GOSUB */ {"gosub",1}, |
| /* T_GOTO */ {"goto",1}, |
| /* T_GT */ {">",0}, |
| /* T_HEXINTEGER */ {(const char*)0,0}, |
| /* T_OCTINTEGER */ {(const char*)0,0}, |
| /* T_IDENTIFIER */ {(const char*)0,0}, |
| /* T_IDIV */ {"\\",0}, |
| /* T_IDN */ {"idn",0}, |
| /* T_IF */ {"if",1}, |
| /* T_IMAGE */ {"image",1}, |
| /* T_IMP */ {"imp",0}, |
| /* T_INC */ {"inc",1}, |
| /* T_INPUT */ {"input",1}, |
| /* T_INTEGER */ {(const char*)0,0}, |
| /* T_INV */ {"inv",0}, |
| /* T_IS */ {"is",1}, |
| /* T_JUNK */ {(const char*)0,0}, |
| /* T_KILL */ {"kill",1}, |
| /* T_LE */ {"<=",0}, |
| /* T_LET */ {"let",1}, |
| /* T_LINEINPUT */ {"line input",1}, |
| /* T_LIST */ {"list",1}, |
| /* T_LLIST */ {"llist",1}, |
| /* T_LOAD */ {"load",1}, |
| /* T_LOCAL */ {"local",1}, |
| /* T_LOCATE */ {"locate",1}, |
| /* T_LOCK */ {"lock",1}, |
| /* T_LOCK_READ */ {"lock read",1}, |
| /* T_LOCK_WRITE */ {"lock write",1}, |
| /* T_LOOP */ {"loop",1}, |
| /* T_LOOPUNTIL */ {"loop until",1}, |
| /* T_LPRINT */ {"lprint",1}, |
| /* T_LSET */ {"lset",1}, |
| /* T_LT */ {"<",0}, |
| /* T_MAT */ {"mat",1}, |
| /* T_MATINPUT */ {"mat input",1}, |
| /* T_MATPRINT */ {"mat print",1}, |
| /* T_MATREAD */ {"mat read",1}, |
| /* T_MATREDIM */ {"mat redim",1}, |
| /* T_MATWRITE */ {"mat write",1}, |
| /* T_MINUS */ {"-",0}, |
| /* T_MKDIR */ {"mkdir",1}, |
| /* T_MOD */ {"mod",0}, |
| /* T_MULT */ {"*",0}, |
| /* T_NAME */ {"name",1}, |
| /* T_NE */ {"<>",0}, |
| /* T_NEW */ {"new",1}, |
| /* T_NEXT */ {"next",1}, |
| /* T_NOT */ {"not",0}, |
| /* T_ON */ {"on",1}, |
| /* T_ONERROR */ {"on error",1}, |
| /* T_ONERRORGOTO0 */ {"on error goto 0",1}, |
| /* T_ONERROROFF */ {"on error off",1}, |
| /* T_OP */ {"(",0}, |
| /* T_OPEN */ {"open",1}, |
| /* T_OPTIONBASE */ {"option base",1}, |
| /* T_OPTIONRUN */ {"option run",1}, |
| /* T_OPTIONSTOP */ {"option stop",1}, |
| /* T_OR */ {"or",1}, |
| /* T_OUT */ {"out",1}, |
| /* T_PLUS */ {"+",0}, |
| /* T_POKE */ {"poke",1}, |
| /* T_POW */ {"^",0}, |
| /* T_PRINT */ {"print",1}, |
| /* T_PUT */ {"put",1}, |
| /* T_QUOTE */ {(const char*)0,1}, |
| /* T_RANDOMIZE */ {"randomize",1}, |
| /* T_READ */ {"read",1}, |
| /* T_REAL */ {(const char*)0,0}, |
| /* T_REM */ {(const char*)0,1}, |
| /* T_RENAME */ {"rename",1}, |
| /* T_RENUM */ {"renum",1}, |
| /* T_REPEAT */ {"repeat",1}, |
| /* T_RESTORE */ {"restore",1}, |
| /* T_RESUME */ {"resume",1}, |
| /* T_RETURN */ {"return",1}, |
| /* T_RSET */ {"rset",1}, |
| /* T_RUN */ {"run",1}, |
| /* T_SAVE */ {"save",1}, |
| /* T_SELECTCASE */ {"select case",1}, |
| /* T_SEMICOLON */ {";",0}, |
| /* T_SHARED */ {"shared",1}, |
| /* T_SHELL */ {"shell",1}, |
| /* T_SLEEP */ {"sleep",1}, |
| /* T_SPC */ {"spc",0}, |
| /* T_STEP */ {"step",1}, |
| /* T_STOP */ {"stop",1}, |
| /* T_STRING */ {(const char*)0,0}, |
| /* T_SUB */ {"sub",1}, |
| /* T_SUBEND */ {"subend",1}, |
| /* T_SUBEXIT */ {"subexit",1}, |
| /* T_SWAP */ {"swap",1}, |
| /* T_SYSTEM */ {"system",1}, |
| /* T_TAB */ {"tab",0}, |
| /* T_THEN */ {"then",1}, |
| /* T_TO */ {"to",1}, |
| /* T_TRN */ {"trn",0}, |
| /* T_TROFF */ {"troff",1}, |
| /* T_TRON */ {"tron",1}, |
| /* T_TRUNCATE */ {"truncate",1}, |
| /* T_UNLOCK */ {"unlock",1}, |
| /* T_UNNUM */ {"unnum",1}, |
| /* T_UNNUMBERED */ {"",0}, |
| /* T_UNTIL */ {"until",1}, |
| /* T_USING */ {"using",0}, |
| /* T_WAIT */ {"wait",1}, |
| /* T_WEND */ {"wend",1}, |
| /* T_WHILE */ {"while",1}, |
| /* T_WIDTH */ {"width",1}, |
| /* T_WRITE */ {"write",1}, |
| /* T_XOR */ {"xor",0}, |
| /* T_XREF */ {"xref",0}, |
| /* T_ZER */ {"zer",0}, |
| /* T_ZONE */ {"zone",1}, |
| }; |
| |
| /* precompute indentation */ |
| if (indent) thisindent=nextindent=*indent; |
| t=token; |
| do |
| { |
| switch (t->type) |
| { |
| case T_CASEELSE: |
| case T_CASEVALUE: |
| { |
| if (thisnotindent) --thisnotindent; else if (thisindent) --thisindent; |
| break; |
| } |
| case T_DEFFN: |
| case T_FUNCTION: |
| { |
| struct Token *cp; |
| |
| for (cp=t; cp->type!=T_EOL && cp->type!=T_CP; ++cp); |
| if ((cp+1)->type!=T_EQ) |
| { |
| ++thisnotindent; |
| ++nextindent; |
| } |
| infn=1; |
| break; |
| } |
| case T_COLON: infn=0; break; |
| case T_DEFPROC: |
| case T_DO: |
| case T_DOUNTIL: |
| case T_DOWHILE: |
| case T_REPEAT: |
| case T_SUB: |
| case T_WHILE: ++thisnotindent; ++nextindent; break; |
| case T_FOR: |
| { |
| if ((t>token && ((t-1)->type==T_COLON || (t-1)->type==T_INTEGER || (t-1)->type==T_UNNUMBERED))) |
| { |
| ++thisnotindent; ++nextindent; |
| } |
| break; |
| } |
| case T_SELECTCASE: thisnotindent+=2; nextindent+=2; break; |
| case T_EQ: |
| { |
| if (infn || (t>token && ((t-1)->type==T_COLON || (t-1)->type==T_INTEGER || (t-1)->type==T_UNNUMBERED))) |
| { |
| if (thisnotindent) --thisnotindent; else if (thisindent) --thisindent; |
| if (nextindent) --nextindent; |
| } |
| infn=0; |
| break; |
| } |
| case T_ENDFN: |
| case T_FNEND: |
| case T_ENDIF: |
| case T_ENDPROC: |
| case T_SUBEND: |
| case T_LOOP: |
| case T_LOOPUNTIL: |
| case T_UNTIL: |
| case T_WEND: |
| { |
| if (thisnotindent) --thisnotindent; else if (thisindent) --thisindent; |
| if (nextindent) --nextindent; |
| break; |
| } |
| case T_ENDSELECT: |
| { |
| if (thisnotindent) --thisnotindent; else if (thisindent) --thisindent; |
| if (thisnotindent) --thisnotindent; else if (thisindent) --thisindent; |
| if (nextindent) --nextindent; |
| if (nextindent) --nextindent; |
| break; |
| } |
| case T_NEXT: |
| { |
| ++t; |
| while (1) |
| { |
| if (thisnotindent) --thisnotindent; else if (thisindent) --thisindent; |
| if (nextindent) --nextindent; |
| if (t->type==T_IDENTIFIER) |
| { |
| ++t; |
| if (t->type==T_OP) |
| { |
| int par=0; |
| |
| do |
| { |
| if (t->type==T_OP) ++par; |
| else if (t->type==T_CP) --par; |
| if (t->type!=T_EOL) ++t; |
| else break; |
| } while (par); |
| } |
| if (t->type==T_COMMA) ++t; |
| else break; |
| } |
| else break; |
| } |
| break; |
| } |
| case T_THEN: if ((t+1)->type==T_EOL) { ++thisnotindent; ++nextindent; } break; |
| case T_ELSE: |
| { |
| if (t==token+1) |
| { |
| if (thisnotindent) --thisnotindent; else if (thisindent) --thisindent; |
| } |
| break; |
| } |
| case T_ELSEIFELSE: |
| { |
| if (t==token+1) |
| { |
| if (thisnotindent) --thisnotindent; else if (thisindent) --thisindent; |
| } |
| if (nextindent) --nextindent; |
| break; |
| } |
| default: break; |
| } |
| } while (t++->type!=T_EOL); |
| |
| if (width>=0) /* whole line */ |
| { |
| if (width) /* nicely formatted listing */ |
| { |
| assert (token->type==T_UNNUMBERED || token->type==T_INTEGER); |
| if (token->type==T_INTEGER) String_appendPrintf(s,"%*ld ",width,token->u.integer); |
| else String_appendPrintf(s,"%*s ",width,""); |
| } |
| else assert (token->type==T_UNNUMBERED); |
| ++token; |
| } |
| while (thisindent--) String_appendPrintf(s," "); |
| do |
| { |
| if (s->length>oldlength && token->type!=T_EOL) |
| { |
| const char *keyword; |
| |
| if ((keyword=table[token->type].text)==(const char*)0) keyword="X"; |
| if (ns && s->character[s->length-1]!=' ') |
| { |
| String_appendPrintf(s," "); |
| } |
| else if (isalnum((int)(s->character[s->length-1])) && isalnum((int)*keyword)) |
| { |
| String_appendPrintf(s," "); |
| } |
| else if (s->character[s->length-1]!=' ' && table[token->type].space) |
| { |
| String_appendChar(s,' '); |
| } |
| } |
| if (spaceto && token==spaceto) break; |
| switch (token->type) |
| { |
| case T_DATAINPUT: String_appendChars(s,token->u.datainput); break; |
| case T_ELSEIFIF: break; |
| case T_IDENTIFIER: String_appendChars(s,token->u.identifier->name); break; |
| case T_INTEGER: String_appendPrintf(s,"%ld",token->u.integer); break; |
| case T_HEXINTEGER: String_appendPrintf(s,"&h%lx",token->u.hexinteger); break; |
| case T_OCTINTEGER: String_appendPrintf(s,"&o%lo",token->u.octinteger); break; |
| case T_JUNK: String_appendChar(s,token->u.junk); break; |
| case T_REAL: |
| { |
| String_appendPrintf(s,"%.*g",DBL_DIG,token->u.real); |
| if ((token->u.real<((double)LONG_MIN)) || (token->u.real>((double)LONG_MAX))) String_appendChar(s,'!'); |
| break; |
| } |
| case T_REM: String_appendPrintf(s,"%s%s",g_uppercase?"REM":"rem",token->u.rem); break; |
| case T_QUOTE: String_appendPrintf(s,"'%s",token->u.rem); break; |
| case T_STRING: |
| { |
| size_t l=token->u.string->length; |
| char *data=token->u.string->character; |
| |
| String_appendPrintf(s,"\""); |
| while (l--) |
| { |
| if (*data=='"') String_appendPrintf(s,"\""); |
| String_appendPrintf(s,"%c",*data); |
| ++data; |
| } |
| String_appendPrintf(s,"\""); |
| break; |
| } |
| |
| default: |
| { |
| if (g_uppercase) |
| { |
| struct String u; |
| |
| String_new(&u); |
| String_appendChars(&u,table[token->type].text); |
| String_ucase(&u); |
| String_appendString(s,&u); |
| String_destroy(&u); |
| } |
| else String_appendChars(s,table[token->type].text); |
| } |
| } |
| ns=table[token->type].space; |
| } while (token++->type!=T_EOL); |
| if (indent) *indent=nextindent; |
| if (spaceto && s->length>oldlength) memset(s->character+oldlength,' ',s->length-oldlength); |
| return s; |
| } |
| |
| void Token_init(int b_c, int uc) |
| { |
| #define PROPERTY(t,assoc,unary_priority,binary_priority,is_unary,is_binary) \ |
| g_token_property[t]=(assoc<<8)|(unary_priority<<5)|(binary_priority<<2)|(is_unary<<1)|is_binary |
| |
| g_backslash_colon=b_c; |
| g_uppercase=uc; |
| PROPERTY(T_POW, 1,0,7,0,1); |
| PROPERTY(T_MULT, 0,0,5,0,1); |
| PROPERTY(T_DIV, 0,0,5,0,1); |
| PROPERTY(T_IDIV, 0,0,5,0,1); |
| PROPERTY(T_MOD, 0,0,5,0,1); |
| PROPERTY(T_PLUS, 0,6,4,1,1); |
| PROPERTY(T_MINUS,0,6,4,1,1); |
| PROPERTY(T_LT, 0,0,3,0,1); |
| PROPERTY(T_LE, 0,0,3,0,1); |
| PROPERTY(T_EQ, 0,0,3,0,1); |
| PROPERTY(T_GE, 0,0,3,0,1); |
| PROPERTY(T_GT, 0,0,3,0,1); |
| PROPERTY(T_NE, 0,0,3,0,1); |
| PROPERTY(T_NOT, 0,2,0,1,0); |
| PROPERTY(T_AND, 0,0,1,0,1); |
| PROPERTY(T_OR, 0,0,0,0,1); |
| PROPERTY(T_XOR, 0,0,0,0,1); |
| PROPERTY(T_EQV, 0,0,0,0,1); |
| PROPERTY(T_IMP, 0,0,0,0,1); |
| } |