数値式文字列式評価

 投稿者:荒田浩二  投稿日:2009年 2月14日(土)00時14分36秒
 
十進BASICに添付されたサンプルプログラム"\BASICw32\SAMPLE\INTERPRE.bas"は数値式の評価を行います。
数値式を入力すると、その式の値を出力します。
それを次のように拡張しました。

(1) 数値定数
   小数点で始まる小数や、指数部のある数値も扱える。

(2) 組込み関数
   十進BASICの組込み関数は、配列や特殊な例を除きほとんど利用できる。

(3) 変数
   数値式に変数を使える。
   数値式内に変数を認識すると,変数名を表示し入力を求めてくる(中止は[中止]ボタンで)。
   変数への入力は数値式も可。ただし,この数値式に変数を含むことは不可。
    例) a^2+1 の変数a に[4],[-3/2],[8-3*5],[sqr(5)-1],[SIN(pi/6)]など入力可。[4*n+9]は不可。
   変数名の命名規則は十進BASICに準ずる(漢字可、PI,RND,MAXNUM,DATE,TIME,DATE$,TIME$以外の機能語も可)。
   配列には対応していない。

(4) 文字列式
   文字列式の評価も行える。その場合は入力する文字列式の先頭に「$=」を付ける。
    例) $=REPEAT$("aBc D",3) ; $="alphabet "&CHR$(64+Number) ; $="2*3+7="&STR$(2*3+7)
   文字列では大文字と小文字を区別する。空白も認識する。漢字も可。

(5) 文字列変数
   数値式や文字列式に、文字列変数を使用できる。
   文字列変数への入力は、文字列定数(前後の(")は不要)または文字列式が可。
   文字列変数に文字列式を入力する場合は先頭に「$=」を付ける。この文字列式に変数を含むことは不可。
    例) $=USING$(a$,800.52) のa$に[###],[$=REPEAT$("#",3)]など入力可。
    例) LEN(mj$&"yz") のmj$に[ab漢],[$=LTRIM$("  ab")&UCASE$"cd"]など入力可。[$="mn"&A$]は不可。
    例) VAL(c$)+7 のc$に[-2.5],[$=str$(1/2-3)]など入力可(-2.5は"-2.5"という文字列定数)。

(6) 部分文字列指定
   文字列変数に部分文字列指定ができる。
   ただし部分文字列指定より前に,同名の文字列変数が書かれている必要がある。
    例) $=a$&","&a$(3:5) ; $=UCASE$(cap$&"aBc")&cap$(2:2-1+m) ; POS(r$,r$(k:k))
    誤入力例) $=box$(2:4)&","&box$
    修正例) $=REPEAT$(box$,0)&box$(2:4)&","&box$ ; $=SUBSTR$(box$,2,4)&","&box$

(7) ユーザー定義関数
   数値式に独自に定義した関数を使えるようにした。
   関数名は F1(a)、F2(a,b)、F3(a,b,c)、FS$(a$,b,c)。
   変数への入力にも使える。 例) SQR(r-4)+1 のrに[2*F2(3,7-5)]など入力可。
   この関数の定義部は1260行の後ろにあるので必要に応じて変更して下さい。再帰呼び出しも可能です。

入力例(関数名,変数名は大文字と小文字の区別はしない)
  2*.43+7E2  ;  MOD(10^2,int(MAX(7.4,sqr(10)+3)))-1  ;  sin(a)^2+cos(b)^2
  2*x^2-7*x+6  ;  1+INT(RND*n)  ;  INT(借入金*(1+年利/100)^年数)  ;  LEN("ab""cd ef gh")
  $=mj$&"xYz"&STR$(n)  ;  $=UCASE$(p$)&","&LCASE$(p$)  ;  $="0x"&BSTR$(Decimal,16)
  $=STR$(1/(2*a)*(-b+sqr(b^2-4*a*c)))&","&STR$((-b-sqr(b^2-4*a*c))/(2*a)) !2次方程式の2根
  $="a="&STR$(abs(m^2-n^2))&",b="&STR$(2*m*n)&",c="&STR$(m^2+n^2) !ピタゴラス数
  $=enter$&TIME$&USING$(".#",FP(TIME))  ;  m*f3(N-5,4,sqr(M))  ;  $=FS$("abc",x,6)&"."

目標としたのは「PRINT *******」で出力できる数値式、文字列式を網羅することでした。
配列以外は達成できたと思うのですがどうでしょう。
すべてをチェックしているわけでなく間違った数値式を入力してもエラー表示されないかもしれません。
不具合があれば報告お願いします。
REM 十進BASIC添付"\BASICw32\SAMPLE\INTERPRE.bas"に加筆
REM 行番号のない行が加筆部分。行番号は削除可。
1000 REM Full BASICのモジュールの使い方を示すサンプル
1010 REM
1020 REM 数値式の評価を行う
1030 REM 組込み関数は,SIN,COS,TAN, LOG, EXP, SQR, INT,ABSとPIのみ
1040 REM 大文字と小文字の区別はしない
1050 REM 数値式の文法はほぼFull BASICに準ずるが,関数名に続く括弧は空白を入れずに書く。
1060 REM 数値は,数字で始まり,コンマを1個以下含む数字の列としてのみ書ける。
1070 REM 零除算エラーなどは考慮していない。
1080 DECLARE EXTERNAL FUNCTION interpreter.expression  ! 数値式を評価する関数
1090 DECLARE EXTERNAL STRING interpreter.s$            ! 入力行
1100 DECLARE EXTERNAL NUMERIC interpreter.i            ! 入力行の文字位置
1110 DECLARE EXTERNAL SUB interpreter.skip             ! 空白文字を読み飛ばす副プログラム
     DECLARE EXTERNAL FUNCTION interpreter.str_expression$  !文字列式を評価する関数
     DECLARE EXTERNAL NUMERIC interpreter.vc,interpreter.sc !変数の個数(vc=数値,sc=文字列)
     DECLARE EXTERNAL SUB interpreter.error                 !エラーメッセージ
1120 LINE INPUT s$
1130 ! LET s$=UCASE$(s$) !文字列の小文字保持のため無効にした
     DO
        LET vc,sc=0
1140    LET i=1
1150    CALL skip
        IF s$(i:i)="$" THEN
           LET i=i+1
           CALL skip
           IF s$(i:i)="=" THEN
              LET i=i+1
              CALL skip
              PRINT str_expression$   ! 文字列式評価
           ELSE
              CALL error("$=")
           END IF
        ELSE
1160       PRINT expression   ! 数値式評価
        END IF
1170    IF i<>LEN(s$)+1 THEN PRINT "Syntax error" ! 比較式をi<LEN(s$)から変更
     LOOP UNTIL vc+sc=0 OR i<>LEN(s$)+1 ! 中止は[中止]ボタンで
1180 END
1190 !
1200 MODULE interpreter
  ! MODULE OPTION ARITHMETIC NATIVE ! DECIMAL_HIGH,COMPLEX,RATIONAL 数値オプション
1210 PUBLIC STRING s$
1220 PUBLIC NUMERIC i
1230 PUBLIC FUNCTION expression
1240 PUBLIC SUB skip
1250 SHARE FUNCTION term,factor,primary,numeric
     PUBLIC FUNCTION str_expression$
     PUBLIC NUMERIC vc,sc
     PUBLIC SUB error
     SHARE FUNCTION check,argument,rounding,position,bitval,v_chr,variable
     SHARE FUNCTION str_primary$,str_constant$,str_naming$,sub_string$,str_input$,bitstr$
     SHARE NUMERIC vari_val(20),inputv   ! 20=変数の個数
     SHARE STRING sn$,vari_name$(20),string$(20),str_name$(20)
     SHARE FUNCTION F1,F2,F3,FS$  !!! ユーザー定義関数
     ! MODULE OPTION ANGLE DEGREES  ! 角の大きさの単位
     ! MODULE OPTION CHARACTER BYTE ! 文字列処理の単位
     LET inputv=0
1260 !
     EXTERNAL FUNCTION F1(a)      !!! ユーザー定義関数
        let F1=a
     END FUNCTION
     EXTERNAL FUNCTION F2(a,b)    !!! ユーザー定義関数
        let F2=a+b
     END FUNCTION
     EXTERNAL FUNCTION F3(a,b,c)  !!! ユーザー定義関数
        let F3=a+b+c
     END FUNCTION
     EXTERNAL FUNCTION FS$(a$,b,c)  !!! ユーザー定義関数
        let FS$=a$&str$(b)&str$(c)
     END FUNCTION
     !
1270 EXTERNAL SUB skip
1280    DO WHILE s$(i:i)=" "
1290       LET i=i+1
1300    LOOP
1310 END SUB
1320 !
1330 EXTERNAL FUNCTION expression
1340    DECLARE NUMERIC n
1350    DECLARE STRING op$
1360    SELECT CASE s$(i:i)
1370    CASE "-"
1380       LET i=i+1
1390       CALL skip
1400       LET n=-term
1410    CASE "+"
1420       LET i=i+1
1430       CALL skip
1440       LET n=term
1450    CASE ELSE
1460       LET n=term
1470    END SELECT
1480    DO WHILE s$(i:i)="+" OR s$(i:i)="-"
1490       LET op$=s$(i:i)
1500       LET i=i+1
1510       CALL skip
1520       IF op$="+" THEN LET n=n+term ELSE LET n=n-term
1530    LOOP
1540    LET expression =n
1550    CALL skip
1560 END FUNCTION
1570 !
1580 EXTERNAL FUNCTION term
1590    DECLARE NUMERIC n
1600    DECLARE STRING op$
1610    LET n=factor
1620    DO WHILE s$(i:i)="*" OR s$(i:i)="/"
1630       LET op$=s$(i:i)
1640       LET i=i+1
1650       CALL skip
1660       IF op$="*" THEN LET n=n*factor ELSE LET n=n/factor
1670    LOOP
1680    LET term=n
1690 END FUNCTION
1700 !
1710 EXTERNAL FUNCTION factor
1720    DECLARE NUMERIC n
1730    LET n=primary
1740    DO WHILE s$(i:i)="^"
1750       LET i=i+1
1760       CALL skip
1770       LET n=n^primary
1780    LOOP
1790    LET factor=n
1800 END FUNCTION
1810 !
1820 EXTERNAL FUNCTION primary
1830    IF s$(i:i)>="0" AND s$(i:i)<="9" THEN
1840       LET  primary=numeric
        ELSEIF s$(i:i)="." THEN
           LET  primary=numeric
1850    ELSEIF UCASE$(s$(i:i+1))="PI" AND check(s$(i+2:i+2))=1 THEN ! 関数check加筆
1860       LET i=i+2
1870       CALL skip
1880       LET primary=PI  ! 有理数モード注意
        ELSEIF UCASE$(s$(i:i+2))="RND" AND check(s$(i+3:i+3))=1 THEN
           LET i=i+3
           CALL skip
           LET primary=RND ! 変数入力がある数値式では都度更新
        ELSEIF UCASE$(s$(i:i+3))="TIME" AND check(s$(i+4:i+4))=1 THEN
           LET i=i+4
           CALL skip
           LET primary=TIME ! 変数入力がある数値式では都度更新
        ELSEIF UCASE$(s$(i:i+3))="DATE" AND check(s$(i+4:i+4))=1 THEN
           LET i=i+4
           CALL skip
           LET primary=DATE ! 変数入力がある数値式では都度更新
           !ELSEIF UCASE$(s$(i:i+5))="MAXNUM" AND check(s$(i+6:i+6))=1 THEN
           !   LET i=i+6
           !   CALL skip
           !   LET primary=MAXNUM  ! 有理数モード不可
1890    ELSE
1900       IF s$(i:i)="(" THEN
1910          LET i=i+1
1920          CALL skip
1930          LET  primary=expression
           ELSEIF UCASE$(s$(i:i+2))="F1(" THEN   !!! ユーザー定義関数
              LET i=i+3
              CALL skip
              LET Primary=F1(expression)
           ELSEIF UCASE$(s$(i:i+2))="F2(" THEN   !!! ユーザー定義関数
              LET i=i+3
              CALL skip
              LET primary=F2(expression,argument)
           ELSEIF UCASE$(s$(i:i+2))="F3(" THEN   !!! ユーザー定義関数
              LET i=i+3
              CALL skip
              LET primary=F3(expression,argument,argument)
1940       ELSEIF UCASE$(s$(i:i+3))="SIN(" THEN ! 超越関数
1950          LET i=i+4
1960          CALL skip
1970          LET Primary=SIN(expression)
1980       ELSEIF UCASE$(s$(i:i+3))="COS(" THEN ! 超越関数
1990          LET i=i+4
2000          CALL skip
2010          LET Primary=COS(expression)
2020       ELSEIF UCASE$(s$(i:i+3))="TAN(" THEN ! 超越関数
2030          LET i=i+4
2040          CALL skip
2050          LET Primary=TAN(expression)
2060       ELSEIF UCASE$(s$(i:i+3))="LOG(" THEN ! 超越関数
2070          LET i=i+4
2080          CALL skip
2090          LET Primary=LOG(expression)
2100       ELSEIF UCASE$(s$(i:i+3))="EXP(" THEN ! 超越関数
2110          LET i=i+4
2120          CALL skip
2130          LET Primary=EXP(expression)
2140       ELSEIF UCASE$(s$(i:i+3))="SQR(" THEN ! 有理数モード注意
2150          LET i=i+4
2160          CALL skip
2170          LET Primary=SQR(expression)
2180       ELSEIF UCASE$(s$(i:i+3))="INT(" THEN
2190          LET i=i+4
2200          CALL skip
2210          LET Primary=INT(expression)
2220       ELSEIF UCASE$(s$(i:i+3))="ABS(" THEN
2230          LET i=i+4
2240          CALL skip
2250          LET Primary=ABS(expression)
           ELSEIF UCASE$(s$(i:i+3))="MOD(" THEN
              LET i=i+4
              CALL skip
              LET primary=MOD(expression,argument)
           ELSEIF UCASE$(s$(i:i+5))="ROUND(" THEN
              LET i=i+6
              CALL skip
              LET primary=rounding
           ELSEIF UCASE$(s$(i:i+4))="CEIL(" THEN
              LET i=i+5
              CALL skip
              LET Primary=CEIL(expression)
           ELSEIF UCASE$(s$(i:i+3))="SGN(" THEN
              LET i=i+4
              CALL skip
              LET Primary=SGN(expression)
           ELSEIF UCASE$(s$(i:i+2))="IP(" THEN
              LET i=i+3
              CALL skip
              LET Primary=IP(expression)
           ELSEIF UCASE$(s$(i:i+2))="FP(" THEN
              LET i=i+3
              CALL skip
              LET Primary=FP(expression)
           ELSEIF UCASE$(s$(i:i+9))="REMAINDER(" THEN
              LET i=i+10
              CALL skip
              LET primary=REMAINDER(expression,argument)
           ELSEIF UCASE$(s$(i:i+8))="TRUNCATE(" THEN
              LET i=i+9
              CALL skip
              LET primary=TRUNCATE(expression,argument)
           ELSEIF UCASE$(s$(i:i+4))="LOG2(" THEN ! 超越関数
              LET i=i+5
              CALL skip
              LET Primary=LOG2(expression)
           ELSEIF UCASE$(s$(i:i+5))="LOG10(" THEN ! 超越関数
              LET i=i+6
              CALL skip
              LET Primary=LOG10(expression)
           ELSEIF UCASE$(s$(i:i+3))="CSC(" THEN ! 超越関数
              LET i=i+4
              CALL skip
              LET Primary=CSC(expression)
           ELSEIF UCASE$(s$(i:i+3))="SEC(" THEN ! 超越関数
              LET i=i+4
              CALL skip
              LET Primary=SEC(expression)
           ELSEIF UCASE$(s$(i:i+3))="COT(" THEN ! 超越関数
              LET i=i+4
              CALL skip
              LET Primary=COT(expression)
           ELSEIF UCASE$(s$(i:i+4))="ASIN(" THEN ! 超越関数
              LET i=i+5
              CALL skip
              LET Primary=ASIN(expression)
           ELSEIF UCASE$(s$(i:i+4))="ACOS(" THEN ! 超越関数
              LET i=i+5
              CALL skip
              LET Primary=ACOS(expression)
           ELSEIF UCASE$(s$(i:i+3))="ATN(" THEN ! 超越関数
              LET i=i+4
              CALL skip
              LET Primary=ATN(expression)
           ELSEIF UCASE$(s$(i:i+5))="ANGLE(" THEN ! 超越関数
              LET i=i+6
              CALL skip
              LET primary=ANGLE(expression,argument)
           ELSEIF UCASE$(s$(i:i+4))="SINH(" THEN ! 超越関数
              LET i=i+5
              CALL skip
              LET Primary=SINH(expression)
           ELSEIF UCASE$(s$(i:i+4))="COSH(" THEN ! 超越関数
              LET i=i+5
              CALL skip
              LET Primary=COSH(expression)
           ELSEIF UCASE$(s$(i:i+4))="TANH(" THEN ! 超越関数
              LET i=i+5
              CALL skip
              LET Primary=TANH(expression)
              !ELSEIF UCASE$(s$(i:i+3))="EPS(" THEN ! 有理数モード不可
              !   LET i=i+4
              !   CALL skip
              !   LET Primary=EPS(expression)
           ELSEIF UCASE$(s$(i:i+3))="DEG(" THEN
              LET i=i+4
              CALL skip
              LET Primary=DEG(expression)
           ELSEIF UCASE$(s$(i:i+3))="RAD(" THEN
              LET i=i+4
              CALL skip
              LET Primary=RAD(expression)
           ELSEIF UCASE$(s$(i:i+3))="MAX(" THEN
              LET i=i+4
              CALL skip
              LET primary=MAX(expression,argument)
           ELSEIF UCASE$(s$(i:i+3))="MIN(" THEN
              LET i=i+4
              CALL skip
              LET primary=MIN(expression,argument)
           ELSEIF UCASE$(s$(i:i+4))="FACT(" THEN !十進BASIC独自拡張
              LET i=i+5
              CALL skip
              LET Primary=FACT(expression)
           ELSEIF UCASE$(s$(i:i+4))="PERM(" THEN !十進BASIC独自拡張
              LET i=i+5
              CALL skip
              LET primary=PERM(expression,argument)
           ELSEIF UCASE$(s$(i:i+4))="COMB(" THEN !十進BASIC独自拡張
              LET i=i+5
              CALL skip
              LET primary=COMB(expression,argument)
           ELSEIF UCASE$(s$(i:i+10))="COLORINDEX(" THEN !十進BASIC独自拡張
              LET i=i+11
              CALL skip
              LET primary=COLORINDEX(expression,argument,argument)
              !ELSEIF UCASE$(s$(i:i+7))="COMPLEX(" THEN !複素関数
              !   LET i=i+8
              !   CALL skip
              !   LET primary=COMPLEX(expression,argument)
              !ELSEIF UCASE$(s$(i:i+2))="RE(" THEN      !複素関数
              !   LET i=i+3
              !   CALL skip
              !   LET Primary=RE(expression)
              !ELSEIF UCASE$(s$(i:i+2))="IM(" THEN      !複素関数
              !   LET i=i+3
              !   CALL skip
              !   LET Primary=IM(expression)
              !ELSEIF UCASE$(s$(i:i+4))="CONJ(" THEN    !複素関数
              !   LET i=i+5
              !   CALL skip
              !   LET Primary=CONJ(expression)
              !ELSEIF UCASE$(s$(i:i+3))="ARG(" THEN     !複素関数
              !   LET i=i+4
              !   CALL skip
              !   LET Primary=ARG(expression)
              !ELSEIF UCASE$(s$(i:i+5))="NUMER(" THEN   !有理数モード専用
              !   LET i=i+6
              !   CALL skip
              !   LET Primary=NUMER(expression)
              !ELSEIF UCASE$(s$(i:i+5))="DENOM(" THEN   !有理数モード専用
              !   LET i=i+6
              !   CALL skip
              !   LET Primary=DENOM(expression)
              !ELSEIF UCASE$(s$(i:i+3))="GCD(" THEN     !有理数モード専用
              !   LET i=i+4
              !   CALL skip
              !   LET primary=GCD(expression,argument)
              !ELSEIF UCASE$(s$(i:i+6))="INTSQR(" THEN  !有理数モード専用
              !   LET i=i+7
              !   CALL skip
              !   LET Primary=INTSQR(expression)
              !ELSEIF UCASE$(s$(i:i+7))="INTLOG2(" THEN !有理数モード専用
              !   LET i=i+8
              !   CALL skip
              !   LET Primary=INTLOG2(expression)
           ELSEIF UCASE$(s$(i:i+3))="LEN(" THEN
              LET i=i+4
              CALL skip
              LET primary=LEN(str_expression$)
           ELSEIF UCASE$(s$(i:i+3))="POS(" THEN
              LET i=i+4
              CALL skip
              LET primary=position
           ELSEIF UCASE$(s$(i:i+3))="VAL(" THEN
              LET i=i+4
              CALL skip
              LET primary=VAL(str_expression$)
           ELSEIF UCASE$(s$(i:i+3))="ORD(" THEN
              LET i=i+4
              CALL skip
              LET primary=ORD(str_expression$)
           ELSEIF UCASE$(s$(i:i+4))="BVAL(" THEN
              LET i=i+5
              CALL skip
              LET primary=bitval
           ELSEIF UCASE$(s$(i:i+4))="BLEN(" THEN !十進BASIC独自拡張
              LET i=i+5
              CALL skip
              LET primary=BLEN(str_expression$)
           ELSEIF v_chr(s$(i:i))=1 THEN
              LET primary=variable    !  変数
              CALL skip
              EXIT FUNCTION
2260       ELSE
              CALL error("FUNCTION primary")
2270          PRINT "Syntax error"
2280          STOP
2290       END IF
2300       IF s$(i:i)=")" THEN
2310          LET i=i+1
2320          CALL skip
2330       ELSE
              CALL error("FUNCTION primary")
2340          PRINT "Syntax error"
2350          STOP
2360       END IF
2370    END IF
2380 END FUNCTION
2390 !
2400 EXTERNAL FUNCTION numeric
2410    DECLARE NUMERIC i0
2420    CALL skip
2430    LET i0=i
        IF s$(i:i)="." THEN ! 小数点で始まる
           LET i=i+1
        ELSE
2440       DO WHILE s$(i:i)>="0" AND s$(i:i)<="9"
2450          LET i=i+1
2460       LOOP
2470       IF s$(i:i)="." THEN LET i=i+1
        END IF
2480    DO WHILE s$(i:i)>="0" AND s$(i:i)<="9"
2490       LET i=i+1
2500    LOOP
        IF LEN(s$)>=i AND UCASE$(s$(i:i))="E" THEN ! 指数部
           LET i=i+1
           IF s$(i:i)="+" OR s$(i:i)="-" THEN LET i=i+1
           DO WHILE s$(i:i)>="0" AND s$(i:i)<="9"
              LET i=i+1
           LOOP
        END IF
2510    LET numeric=VAL(s$(i0:i-1))
2520    CALL skip
2530 END FUNCTION
2540 !
![その2]へ続く
 

Re: 数値式文字列式評価[その2]

 投稿者:荒田浩二  投稿日:2009年 2月14日(土)00時18分47秒
  > No.276[元記事へ]

! [その2]
  !  *以下すべて加筆部分*
     EXTERNAL FUNCTION check(c$) !! 予約語の後続字
        DECLARE STRING p$
        LET check=-1
        DO
           READ IF MISSING THEN EXIT DO : p$
           IF c$=p$ THEN LET check=1
        LOOP
        DATA " " , "+" , "-" , "*" , "/" , "^" , "," , ")" , ""
     END FUNCTION
     !
     EXTERNAL FUNCTION argument !! 引数
        CALL skip
        IF s$(i:i)="," THEN
           LET i=i+1
           CALL skip
        ELSE
           CALL error("FUNCTION argument,引数")
        END IF
        LET argument=expression
     END FUNCTION
     !
     EXTERNAL FUNCTION rounding  !! 関数ROUNDの識別
        DECLARE NUMERIC a
        LET a=expression
        IF s$(i:i)="," THEN
           LET i=i+1
           CALL skip
           LET rounding=ROUND(a,expression)
        ELSEIF s$(i:i)=")" THEN
           LET rounding=ROUND(a) ! 十進BASIC独自拡張
        ELSE
           CALL error("FUNCTION rounding,関数ROUND")
        END IF
     END FUNCTION
     !
     EXTERNAL FUNCTION position  !! 関数POSの識別
        DECLARE STRING aa$,bb$
        LET aa$=str_expression$
        IF s$(i:i)="," THEN
           LET i=i+1
           CALL skip
           LET bb$=str_expression$
           IF s$(i:i)=")" THEN
              LET position=POS(aa$,bb$)
           ELSEIF s$(i:i)="," THEN
              LET i=i+1
              CALL skip
              LET position=POS(aa$,bb$,expression)
           ELSE
              CALL error("FUNCTION position,関数POS")
           END IF
        ELSE
           CALL error("FUNCTION position,関数POS")
        END IF
     END FUNCTION
     !
     EXTERNAL FUNCTION bitval   !! 関数BVALの識別
        DECLARE STRING aa$
        LET aa$=str_primary$
        IF s$(i:i)="," THEN
           LET i=i+1
           CALL skip
           IF s$(i:i)="2" THEN
              LET i=i+1
              CALL skip
              LET bitval=BVAL(aa$,2)
           ELSEIF s$(i:i+1)="16" THEN
              LET i=i+2
              CALL skip
              LET bitval=BVAL(aa$,16)
           ELSE
              CALL error("FUNCTION bitval,関数BVAL")
           END IF
        ELSE
           CALL error("FUNCTION bitval,関数BVAL")
        END IF
     END FUNCTION
     !
     EXTERNAL FUNCTION v_chr(c$)   !! 変数名文字
        IF c$>="A" AND c$<="Z" OR c$>="a" AND c$<="z" OR c$>="ぁ" THEN !先頭文字及びそれ以降
           LET v_chr=1
        ELSEIF c$>="0" AND c$<="9" OR c$="_" OR c$>="0" THEN ! 2文字目以降
           LET v_chr=2
        ELSE
           LET v_chr=-1
        END IF
     END FUNCTION
     !
     EXTERNAL FUNCTION variable   !! 変数
        DECLARE NUMERIC j,vi
        DECLARE STRING vn$,aa$,vs$
        LET vn$=""
        DO WHILE v_chr(s$(i:i))>=1
           LET vn$=vn$&s$(i:i)
           LET i=i+1
        LOOP
        FOR j=1 TO vc
           IF UCASE$(vn$)=UCASE$(vari_name$(j)) THEN
              LET variable=vari_val(j)  ! 既出の変数
              EXIT FUNCTION
           END IF
        NEXT j
        LET vc=vc+1
        LET vari_name$(vc)=vn$
        IF inputv=0 THEN
           DO
              LINE INPUT PROMPT vn$&"=" : aa$ ! 変数への入力
           LOOP UNTIL aa$<>""
        ELSE
           CALL error("FUNCTION variable,変数入力")
        END IF
        LET vs$=s$
        LET vi=i
        LET s$=LTRIM$(aa$)
        LET i=1
        LET inputv=1
        LET vari_val(vc)=expression ! 変数に入力した数値式の処理
        LET inputv=0
        LET s$=vs$
        LET i=vi
        LET variable=vari_val(vc)
     END FUNCTION
     !
     !
     EXTERNAL FUNCTION str_expression$ !! 文字列式
        DECLARE STRING str_n$
        LET str_n$=str_primary$
        DO WHILE s$(i:i)="&"
           LET i=i+1
           CALL skip
           LET str_n$=str_n$&str_primary$
        LOOP
        LET str_expression$ =str_n$
        CALL skip
     END FUNCTION
     !
     EXTERNAL FUNCTION str_primary$ !! 文字列一次子
        DECLARE NUMERIC j
        IF s$(i:i)="""" THEN
           LET i=i+1
           LET str_primary$=str_constant$
        ELSEIF UCASE$(s$(i:i+4))="DATE$" THEN
           LET i=i+5
           CALL skip
           LET str_primary$=DATE$  !変数入力がある数値式では都度更新
        ELSEIF UCASE$(s$(i:i+4))="TIME$" THEN
           LET i=i+5
           CALL skip
           LET str_primary$=TIME$  !変数入力がある数値式では都度更新
        ELSE
           IF v_chr(s$(i:i))=1 THEN
              LET sn$=str_naming$ ! 文字列関数/変数名
              FOR j=1 TO sc
                 IF UCASE$(sn$)=UCASE$(str_name$(j)) THEN
                    CALL skip
                    IF s$(i:i)="(" THEN
                       LET i=i+1
                       CALL skip
                       LET str_primary$=sub_string$(string$(j)) !部分文字列
                    ELSE
                       LET str_primary$=string$(j)  ! 既出の文字列変数
                    END IF
                    EXIT FUNCTION
                 END IF
              NEXT j
           ELSE
              CALL error("FUNCTION str_primary$,文字列一次子")
           END IF
           SELECT CASE UCASE$(sn$)&s$(i:i)
           CASE "FS$("    !!! ユーザー定義関数
              LET i=i+1
              CALL skip
              LET str_primary$=FS$(str_expression$,argument,argument)
           CASE "REPEAT$("
              LET i=i+1
              CALL skip
              LET str_primary$=REPEAT$(str_expression$,argument)
           CASE "STR$("
              LET i=i+1
              CALL skip
              LET str_primary$=STR$(expression)
           CASE "USING$("
              LET i=i+1
              CALL skip
              LET str_primary$=USING$(str_expression$,argument)
           CASE "CHR$("
              LET i=i+1
              CALL skip
              LET str_primary$=CHR$(expression)
           CASE "LCASE$("
              LET i=i+1
              CALL skip
              LET str_primary$=LCASE$(str_expression$)
           CASE "UCASE$("
              LET i=i+1
              CALL skip
              LET str_primary$=UCASE$(str_expression$)
           CASE "LTRIM$("
              LET i=i+1
              CALL skip
              LET str_primary$=LTRIM$(str_expression$)
           CASE "RTRIM$("
              LET i=i+1
              CALL skip
              LET str_primary$=RTRIM$(str_expression$)
           CASE "BSTR$("
              LET i=i+1
              CALL skip
              LET str_primary$=bitstr$
           CASE "SUBSTR$(" ! 十進BASIC独自拡張
              LET i=i+1
              CALL skip
              LET str_primary$=SUBSTR$(str_expression$,argument,argument)
           CASE "MID$("    ! 十進BASIC独自拡張
              LET i=i+1
              CALL skip
              LET str_primary$=MID$(str_expression$,argument,argument)
           CASE "LEFT$("   ! 十進BASIC独自拡張
              LET i=i+1
              CALL skip
              LET str_primary$=LEFT$(str_expression$,argument)
           CASE "RIGHT$("  ! 十進BASIC独自拡張
              LET i=i+1
              CALL skip
              LET str_primary$=RIGHT$(str_expression$,argument)
           CASE ELSE
              LET str_primary$=str_input$ ! 文字列入力
              CALL skip
              EXIT FUNCTION
           END SELECT
           IF s$(i:i)=")" THEN
              LET i=i+1
              CALL skip
           ELSE
              CALL error("FUNCTION str_primary$")
           END IF
        END IF
     END FUNCTION
     !
     EXTERNAL FUNCTION str_constant$  !! 文字列定数
        DECLARE STRING cc$
        LET cc$=""
        DO
           IF s$(i:i)="""" THEN
              IF s$(i+1:i+1)="""" THEN ! [""]の識別
                 LET cc$=cc$&s$(i:i)
                 LET i=i+2
              ELSE
                 LET i=i+1
                 EXIT DO
              END IF
           ELSE
              LET cc$=cc$&s$(i:i)
              LET i=i+1
              IF i>LEN(s$)+1 THEN
                 CALL error("FUNCTION str_constant$,文字列定数")
                 EXIT DO
              END IF
           END IF
        LOOP
        CALL skip
        LET str_constant$=cc$
     END FUNCTION
     !
     EXTERNAL FUNCTION str_naming$ !! 文字列関数/変数名
        LET sn$=""
        DO WHILE v_chr(s$(i:i))>=1
           LET sn$=sn$&s$(i:i)
           LET i=i+1
        LOOP
        IF s$(i:i)="$" THEN
           LET str_naming$=sn$&s$(i:i)
           LET i=i+1
        ELSE
           CALL error("FUNCTION str_naming$,文字列関数/変数名")
        END IF
     END FUNCTION
     !
     EXTERNAL FUNCTION sub_string$(ss$)  !! 部分文字列
        DECLARE NUMERIC a
        LET a=expression
        IF s$(i:i)=":" THEN
           LET i=i+1
           CALL skip
           LET sub_string$=ss$(a:expression)
           IF s$(i:i)=")" THEN
              LET i=i+1
              CALL skip
           ELSE
              CALL error("FUNCTION sub_string$,部分文字列")
           END IF
        ELSE
           CALL error("FUNCTION sub_string$,部分文字列")
        END IF
     END FUNCTION
     !
     EXTERNAL FUNCTION str_input$  !! 文字列入力
        DECLARE NUMERIC j,vi
        DECLARE STRING vs$
        LET sc=sc+1
        LET str_name$(sc)=sn$
        IF inputv=0 THEN
           LINE INPUT PROMPT sn$&"=" : string$(sc)
        ELSE
           CALL error("FUNCTION str_input$,文字列入力")
        END IF
        LET j=1
        DO WHILE string$(sc)(j:j)=" "
           LET j=j+1
        LOOP
        IF string$(sc)(j:j)="$" THEN
           LET j=j+1
           DO WHILE string$(sc)(j:j)=" "
              LET j=j+1
           LOOP
           IF string$(sc)(j:j)="=" THEN
              LET vs$=s$
              LET vi=i
              LET s$=string$(sc)(j+1:LEN(string$(sc)))
              LET s$=LTRIM$(s$)
              LET i=1
              LET inputv=1
              LET string$(sc)=str_expression$ ! 文字列変数に入力した文字列式の処理
              LET inputv=0
              LET s$=vs$
              LET i=vi
           END IF
        END IF
        LET str_input$=string$(sc)
     END FUNCTION
     !
     EXTERNAL FUNCTION bitstr$   !! 関数BSTR$の識別
        DECLARE NUMERIC a
        LET a=expression
        IF s$(i:i)="," THEN
           LET i=i+1
           CALL skip
           IF s$(i:i)="2" THEN
              LET i=i+1
              CALL skip
              LET bitstr$=BSTR$(a,2)
           ELSEIF s$(i:i+1)="16" THEN
              LET i=i+2
              CALL skip
              LET bitstr$=BSTR$(a,16)
           ELSE
              CALL error("FUNCTION bitstr$,関数BSTR$")
           END IF
        ELSE
           CALL error("FUNCTION bitstr$,関数BSTR$")
        END IF
     END FUNCTION
     !
     EXTERNAL SUB error(e$)  !! エラー表示
        PRINT "Error (";e$;")"
        !STOP
     END SUB
     !
2550 END MODULE
 
 

戻る