unit Pas2JavaSc;
{
TAnsiCalculate‚É#Pas2JavaSc‚ð’Ç‰Á‚·‚é
#P2Js ‚ÌsˆÈŒã‚É‘Î‚µ‚Ä ‹@ŠB“I‚È’uŠ·‚ðs‚¤

,begin ,@o
,end   , p

‘Î‰ž‚µ‚Ä‚¢‚È‚¢Ž–
EType JavaScript‚ª‚»‚à‚»‚à•Ï”‚ÉŒ^‚ª–³‚¢‚©‚ç
Eƒ|ƒCƒ“ƒ^‚âŽQÆ‰‰ŽZŽq‚Ì—Þ
EŠÖ”“àŠÖ”  “®ì‚ÌˆÀ’è‚Ìˆ×‚É‚ ‚é’ö“xˆ—‚Í‚µ‚Ä‚é‚ª
Efor•¶‚Ì•Ï”‚É‚Í–ˆ‰ñlet‚ð•t‚¯‚Ä‚µ‚Ü‚¤ “™ let•t‚¯‚Ì‰ö‚µ‚³

‚â‚Á‚Ä‚­‚ê‚éŽ–
Eexit java‚É‚Í‚È‚¢ pascal‚ÍŠÖ”‚ÌI—¹‚È‚Ì‚Å return‚©@return Result‚É’uŠ·
EŠÖ”‚Ìæ“ª‚Å let Result; ÅŒã‚É return Result’Ç‰Á
E'•¶Žš—ñ'#13‚Ì‚æ‚¤‚È•¶Žš—ñ‚ð  "•¶Žš—ñ\r"  ‚Æ’uŠ·
Einc(a)‚ð++a‚É’uŠ· inc(a,3)‚ða+=3‚É’uŠ·
Esetlength(a,3)‚ða.length=3‚É’uŠ· length(a)‚ða.length‚É’uŠ·
Epi‚ðMath.PI ‘¼Math‚É‚ ‚è‚»‚¤‚ÈŠÖ”‚Í Math.‚ð•t‚¯¬•¶Žš‚É‚·‚é
Eln()‚ðMath.log()‚É’uŠ·   (‘¼‚É‚à–¼‘O‚ªˆá‚¤ê‡‚à‚ ‚é‚¾‚ë‚¤‚¯‚Ç’²¸•s‘«)
Esqr(x)‚ð‚Qæsqr(x)‚É’uŠ·‚·‚é‚Ì‚ÅŽ©•ª‚Å‚Qæ‚ÉC³‚·‚é‚±‚Æ—á (x)**2 ‚Ì‚æ‚¤‚É
E•Ï”–¼‚ðÅ‰‚ÉŽg‚Á‚½–¼‘O‚É‘å•¶Žš¬•¶Žš‚ðŒÅ’è‚·‚é
E$abc‚Ì‚æ‚¤‚È”‚ð 0xabc‚Æ’uŠ·
Eif while for •¶‚ð’uŠ·
Eprocedure ‚ðfunction‚É’uŠ·
Evar const ‚ÌŒ^–¼‚ðíœ
EŠÖ”“à‚Ìvar’è‹`‚ðÁ‚µ‚Ä —˜—pŽž‚Élet‚ð•t‚¯‚Ü‚­‚éi–³‘Ê‚È•ª‚ÍŽ©•ª‚ÅC³‚µ‚Ä‰º‚³‚¢)
EAND OR XOR NOT  “™‚Ì  & | ^ ’uŠ·iƒrƒbƒg‰‰ŽZŽq‚Æ‚µ‚Ä‚é‚Ì‚Å˜_—Œ^‚È‚çŽ©•ª‚ÅC³)
E:=‚ð=  =‚ð==  <>‚ð!=
EƒRƒƒ“ƒg"o`p"‚ð/*`*/‚É’uŠ·

}
//,"{.J}hoge{bom}", bom         ,Å‰‚ÉŒ©‚Â‚¯‚½{}ƒRƒƒ“ƒg‚Æ“ü‚ê•Ï‚¦‚é.hoge‚àbom‚à‰½‚à‰ðŽß‚µ‚È‚¢
//,"{.J}hoge{}   ",             ,JavaScript‚É‚Ío—Í‚µ‚È‚¢
//,"{.J{hoge}    ", hoge        ,JavaScript‚É‚¾‚¯o—Í‚·‚é
//,"{.o}foo(hoge,", hoge.foo( ,ƒIƒuƒWƒFƒNƒg—p‚Å ‘æˆêˆø”‚Ìƒƒ\ƒbƒh‚É‚·‚é
//,"{.r}'hoge'   ", hoge        ,³‹K•\Œ»—p‚Åƒuƒ‰ƒPƒbƒg‚ðŠO‚·(''''‚É‚Í‘Î‰ž‚µ‚Ä‚¢‚È‚¢\x27 ‚ðŽg‚¤Ž–	)
//,"{.E}`{.e}   ",             ,o—Í‹ÖŽ~{.e}‚ª–³‚¯‚ê‚ÎI’[‚Ü‚Å#P2Js‚Ì‚T•¶Žš‚à{.e}‚Æ“¯—l‚ÌŒø‰Ê‚ª‚ ‚é
//,"{.a}         ",             ,’¼Œã‚Ì•Ï”  Object.assign({},•Ï”)‚Æ’uŠ·
//,"{.V}         ",             ,ˆÈŒãlet const‚ðvar‚Æ‚µ‚Äo—Í‚·‚é
//,"{.v}         ",             ,’¼Œã‚Ìƒ[ƒJƒ‹•Ï”’è‹`‚ðvar‚Åo—Í‚·‚é
//,"{.L}         ",             ,’¼Œã‚Ì not and or ‚ð ! && ||
//,"{.B}         ",             ,’¼Œã‚Ì not and or ‚ð ^  &  |


/////ƒtƒ@ƒCƒ‹ƒ‚[ƒh
// ƒtƒ@ƒCƒ‹ƒ‚[ƒh‚Å‚Í#P2Js‚Ì5•¶Žš‚ªƒtƒ@ƒCƒ‹’†‚É‚ ‚éê‡‚Éˆ—‚µAŽŸ‚Ìs‚æ‚èˆ—‚ðŽn‚ß‚é
// ƒtƒ@ƒCƒ‹ƒ‚[ƒh‚Å‚Í{#P2Js} ‚â//#P2Js‚Ì‚æ‚¤‚És“ª‚©‚çŽn‚Ü‚ç‚È‚­‚Ä‚à‚æ‚¢‚ª‘å•¶Žš¬•¶Žš‚Í‹æ•Ê‚·‚é
interface
uses Windows, SysUtils
  , CalcAnsiScript
  , uAnsiCharTools
  ;

type
  TLabelD = record s: string; t: Integer end;
  AString = array of TLabelD;
  TOnTextOut = procedure(s: AnsiString) of object;
  TOnCMD = procedure(var p: PChar) of object;

const //labelMd‚Ì“à—e
  lbUse = 1;
  lbConst = 2;
  lbInFunc = 4; //ƒ[ƒJƒ‹•Ï”
  lbBool = 8; //˜_—Œ^
  lbFunc = 16; //ƒƒ\ƒbƒhƒƒ“ƒo
  lbCntM = 128; //‚±‚Ì’l‚ðƒlƒXƒg‚ª[‚­‚È‚é‚Æ‰ÁŽZ‚µAó‚­‚È‚é‚ÆŒ¸‚¶‚é
  lbLet = 1 shl 30; //ƒ[ƒJƒ‹•Ï” ‚ÌéŒ¾–¢‚¾
type
  TPasRec = record
    name: string; //record/class–¼
    labels: AString; //’è‹`‚³‚ê‚éƒ‰ƒxƒ‹
  end;
  TAPasRec = array of TPasRec;
  TpasMode = //ŠÖ”éŒ¾‚ÍŠÖ”“à‚Åˆ—‚·‚é‚Ì‚Å
    (pasExt //‰Šúó‘Ô
    , pasVar //Var éŒ¾’†
    , pasConst //ConstéŒ¾’†
    , pasInFunc //ŠÖ”“àƒuƒƒbƒN
    , pasType //TypeéŒ¾’† //‚»‚Ì‚Ü‚Üo—Í‚·‚é
    );
  TuPas2JavaSc = class(TObject) //ˆê‚Â‚ÌŠÖ”‚É‚µ‚Ä‚à—Ç‚¢‚¯‚Ç
  private
    tagConst: string;
    tagLET: string;
    endp: PChar; //ˆ—‚·‚é•¶Žš—ñ‚ÌI’[‚ÌƒAƒhƒŒƒX
    fDebug: boolean;
    consOutDebug: boolean;
    isProc: boolean; //ŠÖ”“à‚©procedure“à‚©
    isLogic: boolean; // ƒƒWƒbƒNƒ‚[ƒh and or not ‚ð&& || !‚É
    finFunc: Boolean;
    pasMode: TpasMode;
    LabelCnt: Integer;
    ResultCnt: Integer; //ŠÖ”“à‚Å‰½“xResult‚É‘ã“ü‚µ‚½‚©
    ResultValue: string; //‚»‚Ì‚P‰ñ‚¾‚¯‚Ì‹A‚è’l
    RecDatas: TAPasRec;
    RecData: TPasRec; //ƒƒ\ƒbƒh‚Ìƒƒ“ƒo[—Þ‚ª“ü‚Á‚Ä‚¢‚é
    nestc: Integer;

    isVarOut: boolean; //ŠÖ”“à•Ï”‚Ì’¼Œã‚Ìƒ‰ƒxƒ‹‚ð‘‚«‚¾‚·
    LabelName: AString; //‘å•¶Žš¬•¶Žš‚ÌŠÔˆá‚¢‚ðŒ¸‚ç‚·‚½‚ß‚É

    LastSt: string;
    msgBufstr: string;
    inCase: boolean; //case’†
    CaseInBlock: boolean; //case’†‚Ébegin end‚ª‚ ‚Á‚½
    usedBreak: boolean; //case’†‚Åbreak‚ðŽg‚Á‚½
    labelBrake: string; //ƒuƒŒ[ƒNƒ‰ƒxƒ‹
    labelBrakeCnt: Integer; //for while repeat‚Ì”Ô–Ú

    function isMember(var lab: string): boolean;
    procedure copyC(var p: PChar); //‚P•¶Žš‚Ì src->dst copy
    function isLet(var s: string): boolean;
    procedure NestLevel(updn: Integer); //ƒuƒƒbƒN‚Ì[‚³
    function SetLabel(s: string; typ: integer; ref: boolean = false): string;
    procedure msgBuf(s: string); virtual; //dst‚Ö‚Ìo—Í
    procedure msgNorm(s: string); virtual; //dst‚Ö‚Ìo—Í
    procedure SwapMsgBufMd(var MsgFunc: TOnTextOut; var dtMsg: string); //ƒoƒbƒtƒ@ƒ‚[ƒhØ‘Ö—p
    procedure outBreak();
    procedure CallLp(cmd: TOnCMD; var p: PChar); //for repeat while‚ðŒÄ‚Ô
  protected
    msg: TOnTextOut;
    function prjCall(var p: PChar; c: TSysCharSet; call: string): string; //msgBuf‚ÉØ‚è‘Ö‚¦‚ÄŒ‹‰Ê‚ð•Ô‚·
    function prjBool(var p: PChar; c: TSysCharSet; call: string): string; //˜_—’l‚ð•K—v‚Æ‚·‚éê–Ê
    function LabelSet(lab: string; var p: PChar): boolean;
    procedure mVar(var p: PChar);
    procedure mIF(var p: PChar);
    procedure mFor(var p: PChar);
    procedure mWhile(var p: PChar);
    procedure mWith(var p: PChar);
    procedure mRepeat(var p: PChar);
    procedure mType(var p: PChar);
    procedure mFunc(var p: PChar);
    procedure mBlock(var p: PChar; inCase1: boolean); //begin end block
    procedure mTry(var p: PChar);
    procedure mCase(var p: PChar);
    procedure CmtSkip(var p: PChar; swOut: boolean = true);
    procedure mCmt(var p: PChar; swOut: boolean = true); //{}ƒRƒƒ“ƒg‚Æ’uŠ·ƒ^ƒO
    procedure moji(var p: PChar);
    procedure kazu(var p: PChar);
    procedure mOrd(var p: PChar);
    function mathFunc(const lab: string; var p: PChar): boolean;
    function kakko(var p: PChar; tojiru: boolean = true): boolean;
    procedure Hairetu(var p: PChar);
  public
    OnTextOut: TOnTextOut;
    procedure Exec(var p: PChar);
    procedure prj(var p: PChar; c: TSysCharSet; call: string);
  end;

  TPas2JavaScCalc = class(TCalcuAddition)
  private
    OutMsgStr: AnsiString;
    procedure MsgOut(msg: AnsiString);
  public
 //  function CallFunc(const lab: AnsiString; Labels: TAMyCalLabel): boolean ;override;
 // function ExeLabel(const lab: AnsiString; var ret: Extended; cmd: TGetLabelCmd): boolean; override;
    procedure StartEndScript(n: Integer); override; //0:start 1:end;
    function LineCmd(const lab: AnsiString; var p: PChar): boolean; override; //#‚ÅŽn‚Ü‚ésƒRƒ}ƒ“ƒh
    function FileExec(const fname: AnsiString; p: PChar): boolean; override; //ƒtƒ@ƒCƒ‹ƒ‚[ƒh‚Å“Á•Ê‚Èˆ—‚ª‚ ‚éê‡
  end;


implementation



function LabelD(nm: string; typ: Integer): TLabelD;
begin
  Result.s := nm;
  Result.t := typ or lbUse;
end;

procedure AddStrArray(var d: AString; add: TLabelD);
var
  n: Integer;
begin
  n := length(d);
  setlength(d, n + 1);
  d[n] := add;
end;

procedure labelIsBool(var d, se: AString);
var //d‚És‚Ì–¼‘O‚Ìƒ‰ƒxƒ‹‚ð’T‚µ‚ÄlbBool‚ð•t‚¯‚é
  i, j: Integer;
begin
  for j := 0 to High(se) do
    for i := 0 to High(d) do if SameText(d[i].s, se[j].s) then begin
        d[i].t := d[i].t or lbBool;
      end;
end;

procedure AddRecDatas(var d: TAPasRec; add: TPasRec);
var
  n: Integer;
begin
  n := length(d);
  setlength(d, n + 1);
  d[n] := add;
end;

function SwapFlag(var localf, savef: boolean): boolean;
begin
  Result := savef;
  savef := localf;
  localf := Result;
end;

function startsWith(d, s: string): boolean;
begin
  Result := copy(d, 1, length(s)) = s;
end;

function startsSame(d, s: string): boolean;
begin
  d := copy(d, 1, length(s));
  Result := SameText(s, d);
end;



{ TuPas2JavaSc }

procedure TuPas2JavaSc.copyC(var p: PChar);
begin
  if p^ = #0 then begin
    p := p;
    exit;
  end;
  msg(p^); inc(p);
end;


function TuPas2JavaSc.prjBool(var p: PChar; c: TSysCharSet; call: string): string; //˜_—’l‚ð•K—v‚Æ‚·‚éê–Ê
begin
  isLogic := True;
  Result := prjCall(p, c, call);
end;

//c‚Í'C'ˆÈŠO‚ÍI—¹ðŒ

procedure TuPas2JavaSc.prj(var p: PChar; c: TSysCharSet; call: string);
var
  s: string;
begin
  inc(Nestc);
  if consOutDebug then write('/*<' + call + ',' + IntToStr(Nestc) + '>*/');
  if fdebug then msg('/*<' + call + ',' + IntToStr(Nestc) + '>*/');

  try
    while p^ <> #0 do begin
      if not ('p' in c) then if endp <= p then break;
      CmtSkip(p);
      LastSt := p^;
      case p^ of
        #0: exit;
        '<': if p[1] = '>' then begin inc(p, 2); msg('!='); end
          else if p[1] = '=' then begin inc(p, 2); msg('<='); end
          else copyC(p);
        '>': if p[1] = '=' then begin inc(p, 2); msg('>='); end
          else copyC(p);
        ':': if p[1] = '=' then begin inc(p, 2); msg('='); end
          else if ':' in c then exit else copyC(p);
        '=': begin inc(p); msg('=='); end;
        '(': kakko(p);
        ')': if ')' in c then exit else copyC(p);
        '[': Hairetu(p);
        ']': if ']' in c then exit else copyC(p);
        ';': if ';' in c then exit else copyC(p);
        ',': if ',' in c then exit else copyC(p);

        '#', '''': if 'a' in c then exit else begin moji(p); if 'A' in c then exit; end;
        '&', //8i”
          '%', //2i”
          '$', '0'..'9': if '9' in c then exit else begin kazu(p); if '0' in c then exit; end;


        '_', 'A'..'Z', 'a'..'z': begin
            s := CAnsiGetAccordChars(p, LabelCharSet);
            LastSt := lowercase(s); //to ‚Ædownto‚Ì‹æ•Ê‚Ìˆ×‚É
            if SameText(s, 'procedure') or SameText(s, 'function') then
              if 'f' in c then exit else begin mFunc(p); if 'F' in c then exit; end
            else if SameText(s, 'type') then mType(p)
            else if SameText(s, 'var') then mVar(p)
            else if SameText(s, 'const') then pasMode := pasConst
            else if SameText(s, 'begin') then if '{' in c then exit else mBlock(p, 'C' in c)
            else if SameText(s, 'end') then if '}' in c then exit else begin msg('}'); end
            else if SameText(s, 'then') then if #255 in c then exit else begin msg('then'); end
            else if SameText(s, 'else') then if #254 in c then exit else begin msg('else'); end
            else if SameText(s, 'do') then if #253 in c then exit else begin msg('do'); end
            else if SameText(s, 'to') then if #252 in c then exit else begin msg('to'); end
            else if SameText(s, 'downto') then if #252 in c then exit else begin msg('downto'); end
            else if SameText(s, 'try') then mTry(p)
            else if SameText(s, 'except') then if #251 in c then exit else begin msg('except'); end
            else if SameText(s, 'finally') then if #251 in c then exit else begin msg('finally'); end
            else if SameText(s, 'on') then if #250 in c then exit else begin msg('on'); end
            else if SameText(s, 'repeat') then CallLp(mRepeat, p)
            else if SameText(s, 'until') then if #249 in c then exit else begin msg('until'); end
            else if SameText(s, 'case') then mCase(p)
            else if SameText(s, 'of') then if #248 in c then exit else begin msg('of'); end
            else if SameText(s, 'raise') then begin msg('throw'); end


            else if SameText(s, 'if') then mIF(p)
            else if SameText(s, 'for') then CallLp(mFor, p)
            else if SameText(s, 'while') then CallLp(mWhile, p)
            else if SameText(s, 'with') then mWith(p)
            else if SameText(s, 'break') then outBreak()
            else if SameText(s, 'continue') then msg('continue')
            else if SameText(s, 'exit') then if isProc then msg('return') else
              begin msg('return Result'); ResultCnt := -2; end


            else if SameText(s, 'and') then if isLogic then msg('&&') else msg('&')
            else if SameText(s, 'or') then if isLogic then msg('||') else msg('|')
            else if SameText(s, 'XOR') then msg('^')
            else if SameText(s, 'SHL') then msg('<<')
            else if SameText(s, 'NOT') then if isLogic then msg('!') else msg('~')
            else if SameText(s, 'DIV') then msg('/')
            else if SameText(s, 'MOD') then msg('%')
            else if SameText(s, 'self') then msg('this')
            else if SameText(s, 'True') then msg('true')
            else if SameText(s, 'False') then msg('false')
            else if SameText(s, 'ord') then mOrd(p)

            else if mathFunc(s, p) then
            else if LabelSet(s, p) then
            else
              ;
          end;
      else copyC(p);
      end;
    end;
  finally dec(nestc); end;
end;

procedure TuPas2JavaSc.Hairetu(var p: PChar);
begin
  if p[0] = '[' then copyC(p);
  prj(p, [#0, ']'], 'Hairetu');
  if p[0] = ']' then copyC(p);
end;

function TuPas2JavaSc.kakko(var p: PChar; tojiru: boolean): boolean;
begin

  Result := p^ = '(';
  if Result then begin
    if tojiru then msg('(');
    inc(p);
  end;
  prj(p, [#0, ')'], 'Kakko');
  if p^ = ')' then inc(p);
  if tojiru then msg(')');
end;

function TuPas2JavaSc.isMember(var lab: string): boolean;
var
  i: Integer;
begin
  Result := false;
  for i := 0 to High(RecData.labels) do if SameText(RecData.labels[i].s, lab) then begin
      Result := True;
      lab := RecData.labels[i].s;
      isLogic := (RecData.labels[i].t and lbBool) <> 0;
    end;
end;



procedure TuPas2JavaSc.mVar(var p: PChar);
begin
  pasMode := pasVar;
  if finFunc then CAnsiSkipBlank(p, true); //ŠÖ”“à‚Ì•Ï”Ý’è‚Ì‰üs“™‚ðíœ‚·‚é
end;

function TuPas2JavaSc.LabelSet(lab: string; var p: PChar): boolean;
type
  TAChar2 = array[0..1] of AnsiChar; pA2 = ^TAChar2;
var
  sp: PChar;
  s, Member, ext: string;
  buf: AString;
begin
  Result := True;
  s := lab;
  sp := p;
  CAnsiSkipBlank(sp);
  Member := lab;
  ext := '';
  if sp^ = '.' then begin
    ext := CAnsiGetAccordChars(sp, LabelCharSet + ['.']);
    lab := lab + ext;
    p := sp;
    CAnsiSkipBlank(sp);
  end;

  if pasMode = pasConst then begin
    if finFunc then SetLabel(lab, lbInFunc or lbConst) else SetLabel(lab, lbConst);
    msg(tagConst); msg(' '); msg(lab);
    CAnsiGetNextStr(p, [#0, '=']); //Œ^’è‹`•”‚ðŠO‚·
    if p^ = '=' then begin
      msg(p^); inc(p);
    end;
    prj(p, [#0, ';'], 'LabelSet.Const');
    exit;
  end;
  SetLength(buf, 0);
  if pasMode = pasVar then begin
    if finFunc then begin //ƒ[ƒJƒ‹•Ï”---------------------
      CmtSkip(p, false);
      if isVarOut then begin msg('var ' + lab + ';'); SetLabel(s, lbInFunc); end
      else SetLabel(s, lbInFunc or lbLet);
      AddStrArray(buf, LabelD(s, 0));
      isVarOut := false;
      CmtSkip(p, false);
      while p^ = ',' do begin
        inc(p); CmtSkip(p, false);
        s := CAnsiGetAccordChars(p, LabelCharSet);
        if isVarOut then begin msg('var ' + lab + ';'); SetLabel(s, lbInFunc); end
        else SetLabel(s, lbInFunc or lbLet);
        AddStrArray(buf, LabelD(s, 0));
        CmtSkip(p, false);
      end;
      if p^ = ':' then begin
        inc(p); CmtSkip(p); s := CAnsiGetNextStr(p, [#0, ';']); //Œ^’è‹`•”‚ðŠO‚·
        if startsSame(s, 'bool') then labelIsBool(LabelName, buf);
      end;
      isVarOut := false;
      if p^ = ';' then inc(p);
      CAnsiSkipBlank(p, true);
      exit;
    end else begin //ƒOƒ[ƒoƒ‹•Ï”  ---------------------
      SetLabel(lab, 0);
      AddStrArray(buf, LabelD(lab, 0));
      msg('var ' + lab);
      msg(CAnsiGetAccordChars(p, cSpace));
      while p^ = ',' do begin
        inc(p); CmtSkip(p);
        s := CAnsiGetAccordChars(p, LabelCharSet);
        SetLabel(s, 0);
        AddStrArray(buf, LabelD(s, 0));
        msg('; var ' + s);
        CmtSkip(p);
      end;
      if p^ = ':' then begin
        inc(p); CmtSkip(p); s := CAnsiGetNextStr(p, [#0, ';']); //Œ^’è‹`•”‚ðŠO‚·
        if startsSame(s, 'bool') then labelIsBool(LabelName, buf);
      end;
      if p^ = '=' then begin
        copyC(p);
        prj(p, [#0, ';'], 'LabelSet.var');
      end;
      exit;
    end;
  end;
  if (pasMode = pasInFunc) and isMember(Member) then begin
    msg('this.');
    msg(lab);
    msg(ext);
    exit;
  end;

  if pA2(sp)^ <> ':=' then begin
    msg(SetLabel(lab, 0, true));
    exit;
  end;
  p := sp;
  inc(p, 2);
  if (ResultCnt >= 0) and SameText(lab, 'Result') then begin
    inc(ResultCnt); //Result‚Ö‚Ì‘ã“ü‚ª•¡”‚ ‚é‚È‚ç’ú‚ß‚é
    if ResultCnt = 1 then begin
      ResultValue := prjCall(p, [#0, ';'], 'Result');
      if p[0] = ';' then inc(p);
      exit;
    end;
  end;


  if isLet(lab) then s := tagLET + ' ' else s := '';
  s := s + lab + ' =';
  msg(s);
  exit;
end;

function TuPas2JavaSc.isLet(var s: string): boolean;
var
  i: Integer;
begin
  Result := false;
  for i := 0 to LabelCnt - 1 do if SameText(s, LabelName[i].s) then begin
      Result := (LabelName[i].t and lbLet) = lbLet;
      if Result then begin
        LabelName[i].t := LabelName[i].t and (lbCntM - 1); // lbCntM‚æ‚èã‚Ìƒrƒbƒg‚ðƒNƒŠƒA‚·‚é
      end;
      s := LabelName[i].s;
      exit;
    end;
end;

function TuPas2JavaSc.SetLabel(s: string; typ: integer; ref: boolean): string;
var
  i: Integer;
begin
//ToDo:‚±‚ê‚Å‚Íƒ[ƒJƒ‹•Ï”‚ÅƒOƒ[ƒoƒ‹•Ï”‚ªã‘‚«‚³‚ê‚Ä‚µ‚Ü‚¤‚¼
  for i := 0 to LabelCnt - 1 do if SameText(s, LabelName[i].s) then begin
      Result := LabelName[i].s;
      LabelName[i].t := typ or lbUse;
      if ref then isLogic := (LabelName[i].t and lbBool) <> 0;
      exit;
    end;
  LabelName[LabelCnt].s := s;
  LabelName[LabelCnt].t := typ or lbUse;
  inc(LabelCnt);
  if LabelCnt >= length(LabelName) then begin
    SetLength(LabelName, length(LabelName) * 2);
  end;

  Result := s;
end;

procedure TuPas2JavaSc.NestLevel(updn: Integer);
var
  i: Integer;
begin
  for i := 0 to LabelCnt - 1 do begin
    if ((LabelName[i].t and lbInFunc) <> 0)
      and ((LabelName[i].t and lblet) = 0) then begin
      LabelName[i].t := LabelName[i].t + updn * lbCntM;
    end;
  end;
end;

procedure TuPas2JavaSc.mOrd(var p: PChar);
var
  pSave: PChar;
begin
  pSave := p;
  CAnsiSkipBlank(p);
  if p^ = '(' then begin
    inc(p);
    CAnsiSkipBlank(p);
    if (p[0] = '''')
      and (p[0] = p[2]) then begin
      msg(format('/*%s*/0x%2.2x', [p[1], ord(p[1])]));
      if (p[0] = p[1])
        and (p[0] = p[3]) then inc(p, 4)
      else inc(p, 4);
      CAnsiSkipBlank(p);
      if p^ = '(' then
        inc(p);
    end else begin
      kakko(p, false);
      msg('.codePointAt(0)');
    end;
    exit;
  end;
  p := pSave;
end;

//java mathƒNƒ‰ƒX‚Ìˆ—‚ÆŠÔˆá‚¦‚»‚¤‚Èsqr‚Ìˆ—
//inc/dec‚ð++/-- ‚É’uŠ·‚·‚é

function TuPas2JavaSc.mathFunc(const lab: AnsiString; var p: PChar): boolean;
const
  math = 'PI,power,ln,sqr,abs,acos,acosh,asin,atan,atan2,atanh,cbrt,ceil,cos,cosh,exp,floor,hypot,log,log10,log2,max,min,pow,random,round,sign,sin,sinh,sqrt,tan,trunc,';
var
  s, v: string;
  n: Integer;
  sp: PChar;
begin
  sp := p;
  CAnsiSkipBlank(sp);

  s := LowerCase(lab);
  if s = 'pi' then begin
    Result := True;
    msg('Math.PI');
    exit;
  end;
  Result := false;
  if (s = 'char') then begin
    if sp^ <> '(' then exit;
    msg('String.fromCharCode');
    Result := true;
    exit;
  end;

  if (s = 'inc') or (s = 'dec') then begin
    CAnsiSkipBlank(p);
    if sp^ <> '(' then exit;
    p := sp + 1;
    v := CAnsiGetNextStr(p, [#0, ',', ')']);
    Result := True;
    v := SetLabel(v, 0);
    if p^ = ',' then begin
      inc(p);
      if s = 'inc' then msg(v + '+=')
      else msg(v + '-=');
      prj(p, [#0, ')'], 'f.inc');
      if p^ = ')' then inc(p);

    end else begin
      if s = 'inc' then msg('++' + v)
      else msg('--' + v);
    end;
    if p^ = ')' then inc(p);
    exit;
  end;
  if (s = 'length') then begin // length -----------------
    CAnsiSkipBlank(p);
    if p^ <> '(' then exit;
    inc(p);
    v := CAnsiGetNextStr(p, [#0, ')']);
    Result := True;
    v := SetLabel(v, 0);
    msg(v + '.length');
    if p^ = ')' then inc(p);
    exit;
  end;
  if (s = 'setlength') then begin // SetLength -----------------
    CAnsiSkipBlank(p);
    if p^ <> '(' then exit;
    inc(p);
    v := CAnsiGetNextStr(p, [#0, ',']);
    Result := True;
    if isLet(v) then msg(tagLET + ' ' + v + ';');
    msg(v + '.length = ');
    if p^ = ',' then inc(p);
    prj(p, [#0, ')'], 'f.Length');
    if p^ = ')' then inc(p);
    exit;
  end;
  if (s = 'inttostr')
    or (s = 'floattostr') then begin
    if p^ <> '(' then exit;
    msg('String');
    kakko(p);
    Result := True; exit;
  end;


  n := Pos(',' + s + ',', math);
  Result := false;
  if n < 1 then begin
    if sp = '(' then begin
      Result := True;
      p := sp;
      msg(lab);
      kakko(p);
    end;
    exit;
  end;
  CAnsiSkipBlank(p);
  if p^ <> '(' then exit;
  Result := True;
  if s = 'power' then msg('Math.pow')
  else if s = 'ln' then msg('Math.log')
  else if s = 'sqr' then msg('‚Qæsqr')
  else begin
    s := copy(math, n + 1, 10);
    n := Pos(',', s);
    s := copy(s, 1, n - 1);
    msg('Math.' + s);
  end;
  kakko(p);
end;


//•¡”sƒRƒƒ“ƒg‚Ìˆ—

procedure TuPas2JavaSc.CmtSkip(var p: PChar; swOut: boolean);
  procedure m(s: AnsiString);
  begin if swOut then msg(s);
  end;
begin
  repeat
    m(CAnsiGetAccordChars(p, cSpace));
    case p^ of
      '/': if p[1] = '/' then begin m(CAnsiGetNextStr(p, [#0, #13, #10])); continue; end;
      '{': begin mCmt(p); continue; end;
      '(': if p[1] = '*' then begin mCmt(p); continue; end;
    else break;
    end;
    break;
  until false;
end;

procedure TuPas2JavaSc.mCmt(var p: PChar; swOut: boolean);
  procedure m(s: AnsiString);
  begin if swOut then msg(s);
  end;
var
  s: string;
  ps: PChar;
  opsiz: Integer;
begin
  opsiz := 4;
  ps := p;
  if CAnsiCmpStrs(p, ['(*']) then begin inc(p); opsiz := 5; end;

  if (p[1] = '.') then //‚¿‚å‚Á‚ÆŽè”²‚«
    if (((ps[0] = '{') and (p[3] = '}')) or CAnsiCmpStrs(p + 3, ['*)'])) then
      case p[2] of
        'J': begin inc(p, opsiz);
            if ps[0] = '{' then begin
              CAnsiGetSplitStr(p, '{');
              msg(CAnsiGetSplitStr(p, '}'));
            end else begin
              CAnsiGetSplitStr(p, '(*');
              msg(CAnsiGetSplitStr(p, '*)'));
            end;
            exit;
          end;
        'o': begin inc(p, opsiz);
            s := CAnsiGetSplitStr(p, '(');
            msg(prjCall(p, [#0, ','], '{.o}')); if p[0] = ',' then inc(p);
            msg('.'); msg(s); msg('(');
            kakko(p);
            exit;
          end;
        'a': begin inc(p, opsiz);
            s := CAnsiGetAccordChars(p, LabelCharSet);
            msg('Object.assign({},'); msg(s); msg(')');
            exit;
          end;
        'r': begin inc(p, opsiz);
            s := p[0];
            inc(p);
            msg(CAnsiGetSplitStr(p, s));
            exit;
          end;
        'E': begin inc(p, opsiz);
            CAnsiFindStrs(p, ['{.e}', '(*.e*)', '']);
            exit;
          end;
        'V': begin inc(p, opsiz);
            tagConst := 'var';
            tagLET := 'var';
            exit;
          end;
        'v': begin inc(p, opsiz);
            isVarOut := true;
            exit;
          end;
        'L': begin inc(p, opsiz);
            isLogic := true;
            exit;
          end;
        'B': begin inc(p, opsiz);
            isLogic := false;
            exit;
          end;

      end;
  m('/*');

  inc(p);
  if ps[0] = '{' then begin
    m(CAnsiGetNextStr(p, [#0, '}']) + '*/');
    if p^ = '}' then inc(p);
  end else begin
    m(CAnsiGetSplitStr(p, '*)') + '*/');
  end;
end;



// Type‚Ìˆ—•û–@‚ªŽv‚¢‚Â‚©‚È‚¢‚Ì‚Å‚»‚Ì‚Ü‚Üo—Í

procedure TuPas2JavaSc.mType(var p: PChar);
var
  s, lab, typeName: string;
  RecData: TPasRec;
  no: Integer;
  fEnum: boolean;
begin
  pasMode := pasType;
  msg('/*type*/');
  while not (p^ in [#0]) do begin
    CmtSkip(p);
    case p^ of
      '_', 'A'..'Z', 'a'..'z': begin
          s := CAnsiGetAccordChars(p, LabelCharSet);
          if SameText(s, 'procedure') or SameText(s, 'function') then begin
            pasMode := pasExt;
            LastSt := lowercase(s);
            mFunc(p); exit;
          end
          else if SameText(s, 'var') then begin pasMode := pasVar; exit; end
          else if SameText(s, 'type') then msg('type')
          else if SameText(s, 'const') then begin pasMode := pasConst; exit; end
            ;
          msg(CAnsiGetAccordChars(p, cSpace));

          if p[0] = '=' then begin
            typeName := s;
            inc(p);
            msg(CAnsiGetAccordChars(p, cSpace));
            s := CAnsiGetAccordChars(p, LabelCharSet);
            if SameText(s, 'procedure')
              or SameText(s, 'function') then begin
              msg('/*');
              msg(typeName);
              msg('=');
              msg(s);
              msg(CAnsiGetNextStr(p, [#0, #13, #10]));
              msg('*/');
              continue;
            end;


            if SameText(s, 'record')
              or SameText(s, 'class') then
            begin
              CAnsiSkip(p, [' ', #9, #13, #10]);
              if p[0] = '(' then begin inc(p); msg('/*' + CAnsiGetSplitStr(p, ')') + '*/'); end;
              if p[0] = ';' then begin //Ž–‘O’è‹`
                msg('/*'); msg(typeName); msg('='); msg(s); msg('*/');
                inc(p);
                continue;
              end;
              RecData.name := typeName;
              SetLength(RecData.labels, 0);

              msg('function ' + typeName + '(){');
              while not (p^ in [#0]) do begin
                CmtSkip(p);
                case p^ of
                  '_', 'A'..'Z', 'a'..'z': begin
                      s := CAnsiGetAccordChars(p, LabelCharSet);
                      if SameText(s, 'procedure') or SameText(s, 'function') then begin
                        msg(cvU('/*Ÿfunction'));
                        msg(CAnsiGetAccordChars(p, cSpace));
                        s := CAnsiGetAccordChars(p, LabelCharSet);
                        AddStrArray(RecData.labels, LabelD(s, lbFunc));
                        msg(s);

                        msg(CAnsiGetNextStr(p, [#0, #13, #10]));
                        msg(cvU('Ÿ*/'));
                        continue;
                      end
                      else if SameText(s, 'end') then begin msg(' return this;}');
                        AddRecDatas(RecDatas, RecData);
                        break;
                      end
                      else if SameText(s, 'private') then msg('/*private*/')
                      else if SameText(s, 'protected') then msg('/*protected*/')
                      else if SameText(s, 'public') then msg('/*public*/')
                      else begin
                        lab := s;
                        msg('this.' + lab);
                        if p^ = ':' then begin //Œ^–¼‚Í“Ç‚Ý”ò‚Î‚·
                          inc(p); CmtSkip(p); s := CAnsiGetNextStr(p, [#0, ',', ';']); //Œ^’è‹`•”‚ðŠO‚·
                          if startsSame(s, 'bool') then AddStrArray(RecData.labels, LabelD(lab, lbBool))
                          else AddStrArray(RecData.labels, LabelD(lab, 0));


                          if startsSame(s, 'double')
                            or startsSame(s, 'Int') then msg('=0 /*' + s + '*/')
                          else if startsSame(s, 'string') then msg('="" /*' + s + '*/')
                          else if startsSame(s, 'array') then msg('=[] /*' + s + '*/')
                          else msg('/*' + s + '*/')
                        end else
                          if p[0] in [',', ';'] then copyC(p);

                      end;
                    end;
                else copyC(p);
                end;
              end;
            end else begin // class or record  end
              fEnum := true;
              if SameText(s, 'set') then begin //set of ‚ÍƒRƒƒ“ƒgƒAƒEƒg
                msg('/* ');
                msg(s);
                msg(CAnsiGetAccordChars(p, cSpace));
                s := CAnsiGetAccordChars(p, LabelCharSet);
                msg(s); //of
                msg('*/ ');
                fEnum := false;
              end else begin
                msg('/*'); msg(typeName); msg('='); msg(s);
                msg(CAnsiGetNextStr(p, [#0, ';']));
                msg('*/');
                if p[0] = ';' then inc(p);
                continue;
              end;
              msg(CAnsiGetAccordChars(p, cSpace));
              if p[0] = '(' then begin //—ñ‹“Œ^
                msg(tagConst); msg(' ');
                msg(typeName); msg('='); msg('{');
                inc(p);
                no := 0;
                repeat
                  msg(CAnsiGetAccordChars(p, cSpace));
                  CmtSkip(p);
                  case p^ of
                    ',': begin msg(','); inc(p); continue; end;
                    ')': begin msg('}'); inc(p); break; ; end; //—ñ‹“Œ^I‚í‚è

                    '_', 'A'..'Z', 'a'..'z': begin
                        msg(CAnsiGetAccordChars(p, LabelCharSet));
                        if fEnum then begin msg(':'); msg(IntToStr(no)); inc(no);
                        end else msg(':false');
                        msg(CAnsiGetAccordChars(p, cSpace));
                      end;
                  else begin copyC(p); msg(cvU('<Ÿ?')); end;
                  end;
                until p^ = #0;
              end;
            end;
          end;
        end;
    else copyC(p);
    end;
  end;
end;


//ŠÖ”éŒ¾@ˆø”‚ÌŒ^–¼‚ðŠO‚µ‚Ä‚ä‚­

procedure TuPas2JavaSc.mFunc(var p: PChar);
var
  i, j, n, m, resultBool: Integer;
  ps: PChar;
  s, fncName, clsName: string;
  svIsProc, thisInFunc, thisIsProc, thisIsMe: boolean;
  SaveLabelName: AString;

begin
  inCase := false; //case’†
  labelBrakeCnt := 0; //for while repeat‚Ì”Ô–Ú

  svIsProc := isProc;
  ResultCnt := -1;
  thisInFunc := finFunc;
  thisIsProc := LastSt = 'procedure';
  isProc := thisIsProc;


  finFunc := True;
  pasMode := pasInFunc;


  CAnsiSkipBlank(p);
  s := CAnsiGetAccordChars(p, LabelCharSet);
  fncName := s;
  thisIsMe := p^ = '.';
  if thisIsMe then begin //ƒƒ\ƒbƒh‚Ìê‡
    clsName := s;
    inc(p);
    CAnsiSkipBlank(p);
    fncName := CAnsiGetAccordChars(p, LabelCharSet);
    n := -1;
    m := -1;
    for i := 0 to High(RecDatas) do if SameText(RecDatas[i].name, clsName) then begin
        n := i;
        clsName := RecDatas[n].name; //‘å•¶Žš¬•¶Žš‚ä‚ç‚¬‘Îô
        for j := 0 to High(RecDatas[i].labels) do
          if SameText(RecDatas[i].labels[j].s, fncName) then
            m := j;
        if m < 0 then AddStrArray(RecDatas[i].labels, LabelD(fncName, lbFunc))
        else fncName := RecDatas[n].labels[m].s; //‘å•¶Žš¬•¶Žš‚ä‚ç‚¬‘Îô
        resultBool := RecDatas[n].labels[m].t; //‹A‚è’l‚ª˜_—Œ^‚©
        RecData := RecDatas[n];
        break;
      end;
    if n < 0 then begin
      RecData.name := clsName;
      SetLength(RecData.labels, 1);
      RecData.labels[0] := LabelD(fncName, lbFunc);

    end;
    ps := p;
    if p^ = '(' then inc(p);
    msg(clsName); msg('.prototype.'); msg(fncName); msg('=function (');
  end else begin
    CAnsiSkipBlank(p);
    ps := p;
    if p^ = '(' then inc(p);
    msg('function '); msg(s); msg('(');
  end;
  CAnsiSkipBlank(p);
  repeat //ƒ‹[ƒv‚Å‚Í‚È‚­break‚Å”²‚¯‚éˆ×‚É
    if ps^ <> '(' then begin
      msg(')  {'#13#10);
      CAnsiSkipBlank(p);
      if p^ = ':' then begin //Œ^–¼‚Í“Ç‚Ý”ò‚Î‚·
        inc(p); if startsSame(CAnsiGetNextStr(p, [#0, ';']), 'bool') then
        begin resultBool := resultBool or lbBool; RecDatas[n].labels[m].t := resultBool; end;

      end;
      if p^ = ';' then begin // ;‚Í()‚Ì‚È‚¢procedure/function‚ÌI‚í‚è
        inc(p); CAnsiSkipBlank(p, true);
      end;
      break;
    end;
    while true do begin
      CmtSkip(p);
      if p^ = #0 then exit;
      msg(CAnsiGetAccordChars(p, cSpace));
      s := CAnsiGetAccordChars(p, LabelCharSet);
      CmtSkip(p);
      if SameText(s, 'var') //‚±‚ê‚ç‚Í“Ç‚Ý”ò‚Î‚·
        or SameText(s, 'out')
        or SameText(s, 'const') then begin
        msg(CAnsiGetAccordChars(p, cSpace)); CmtSkip(p);
        s := CAnsiGetAccordChars(p, LabelCharSet); CmtSkip(p);
      end;
      msg(s); //ˆø”–¼
      SetLabel(s, lbInFunc);
      if p^ = ':' then begin //Œ^–¼‚Í“Ç‚Ý”ò‚Î‚·
        inc(p); CAnsiGetNextStr(p, [#0, ',', ';', ')']); CmtSkip(p);
      end;
      if p^ in [',', ';'] then begin
        msg(',');
        inc(p);
      end;
      if p^ = ')' then begin
        inc(p);
        msg(')  {'#13#10);
        CAnsiSkipBlank(p, true); CmtSkip(p);
        if p^ = ':' then begin //Œ^–¼‚Í“Ç‚Ý”ò‚Î‚·
          inc(p); CAnsiSkipBlank(p, true);
          s := CAnsiGetNextStr(p, [#0, ' ', #9, ';']);
          CAnsiSkipBlank(p, true);
        end;
        if p^ = ';' then inc(p); //;‚Í“Ç‚Ý”ò‚Î‚·
        CAnsiSkipBlank(p, true);
        break;
      end;
    end;
    break;
  until true;
  repeat
    finFunc := True;
    ps := p;
    s := prjCall(p, [#0, 'f', '{'], 'mFunc.def');
    if (LastSt = 'procedure')
      or (LastSt = 'function') then begin //ŠÖ”“àŠÖ”‚È‚Ì‚Å
      p := ps; //Šª‚«–ß‚µ‚Ä
      finFunc := false; //•Ï”éŒ¾‚ÉVARéŒ¾‚ð‚³‚¹‚é
      prj(p, [#0, '}', 'F'], 'mFunc.In.' + fncName);
      CAnsiSkipBlank(p, true);
      if p[0] = ';' then copyC(p);
    end else begin
      msg(s);
      break;
    end;
  until false;
  if (LastSt = 'begin') then begin
    NestLevel(+1);
    isProc := thisIsProc;
    if not thisIsProc then begin
      ResultCnt := 0;
      finFunc := false; pasMode := pasInFunc;
      ps := p;
      SaveLabelName := LabelName;
      SetLength(SaveLabelName, length(LabelName));
      s := prjCall(p, [#0, '}'], 'function.Code.' + fncName);
      if ResultCnt = 1 then begin
        msg(s); msg('return '); msg(ResultValue); msg(';'#13#10'}');
        if fDebug then msg(format('/*end %s #(%d)*/', [fncName, nestc]));
        NestLevel(-1);
        if thisIsMe then SetLength(RecData.labels, 0);
        pasMode := pasExt; //ŠÖ”“àƒuƒƒbƒN‚ÌI—¹
        isProc := svIsProc;
        exit;
      end;
      LabelName := SaveLabelName;
      p := ps;
    end;
    ResultCnt := -1;
    if not thisIsProc then msg(tagLET + ' Result;'#13#10); //Result‚ðƒ[ƒJƒ‹•Ï”‚Æ‚µ‚Ä“o˜^‚·‚é
    CAnsiSkipBlank(p, true);
    if not thisIsProc then SetLabel('Result', lbInFunc or resultBool);
    finFunc := false;
    pasMode := pasInFunc;
    prj(p, [#0, '}'], 'mFunc.Code.' + fncName);
    if not thisIsProc then msg('return Result;//'#13#10); //Result‚ð•Ô‚·‚Ì‚ð’Ç‰Á
    msg('}');
    if fDebug then msg(format('/*end %s #(%d)*/', [fncName, nestc]));
    NestLevel(-1);
    if thisIsMe then SetLength(RecData.labels, 0);
    isProc := svIsProc;
    pasMode := pasExt; //ŠÖ”“àƒuƒƒbƒN‚ÌI—¹
    exit;
  end;
  isProc := svIsProc;
end;


procedure TuPas2JavaSc.mBlock(var p: PChar; inCase1: boolean);
begin
  if not inCase1 then begin msg('{'); NestLevel(+1); end;

  CmtSkip(p); //case‚Ì’†‚ÌƒuƒƒbƒN‚¾‚¯ŠO‚·
  prj(p, [#0, '}'], 'mBlock');
  if not inCase1 then begin msg('}'); NestLevel(-1); end else begin
    CmtSkip(p); //case ’†‚ÌƒuƒƒbƒN‚ÍŠO‚¹‚é‚Ì‚ÅŠO‚·@‚»‚Ìê‡;‚ªd‚È‚é‚Ì‚Å
    CaseInBlock := True;
  end;
end;

procedure TuPas2JavaSc.SwapMsgBufMd(var MsgFunc: TOnTextOut; var dtMsg: string);
var
  buf: string;
  svMsgFunc: TOnTextOut;
begin
  buf := dtMsg;
  SetLength(buf, length(buf));
  dtMsg := MsgBufstr;
  SetLength(dtMsg, length(dtMsg));
  MsgBufstr := buf;

  svMsgFunc := msg;
  msg := MsgFunc;
  MsgFunc := svMsgFunc;

end;

function TuPas2JavaSc.prjCall(var p: PChar; c: TSysCharSet; call: string): string;
var
  MsgFunc: TOnTextOut;
  saves: string;
  savedbg: boolean;
begin
  savedbg := fDebug; fDebug := false;

  MsgFunc := msgBuf;
  saves := '';
  SwapMsgBufMd(MsgFunc, saves);
  prj(p, c, call);
  SwapMsgBufMd(MsgFunc, saves);
  Result := saves;
  fDebug := savedbg;
end;

procedure TuPas2JavaSc.CallLp(cmd: TOnCMD; var p: PChar); //for repeat while‚ðŒÄ‚Ô
var
  MsgFunc: TOnTextOut;
  saves: string;
  usedBreakSv: boolean;
  labelBrakeSv: string;
begin
  usedBreakSv := usedBreak;
  labelBrakeSv := labelBrake;
  usedBreak := false; //case’†‚Åbreak‚ðŽg‚Á‚½
  inc(labelBrakeCnt);
  labelBrake := 'L' + IntToStr(labelBrakeCnt);

  MsgFunc := msgBuf;
  saves := '';
  SwapMsgBufMd(MsgFunc, saves);
  cmd(p);
  SwapMsgBufMd(MsgFunc, saves);

  if usedBreak then begin
    msg(labelBrake); msg(':');
  end;
  msg(saves);
  usedBreak := usedBreakSv;
  labelBrake := labelBrakeSv;
end;

procedure TuPas2JavaSc.outBreak();
begin
  msg('break');
  if inCase then begin //case’†‚É‚ ‚ébreak‚Íbreak label‚É•ÏŠ·
    msg(' ');
    msg(labelBrake);
    usedBreak := true;
  end;
end;

procedure TuPas2JavaSc.mCase(var p: PChar);
var
  s: string;
  q: PChar;
  inCaseSv: boolean;
  CaseInBlockSv: boolean;
begin
  inCaseSv := inCase;
  CaseInBlockSv := CaseInBlock;

  msg('switch(');
  CmtSkip(p);
  prj(p, [#248, '}', #0], 'mCase.of'); //  of=#248
  msg('){/* case */');
  CmtSkip(p); //ƒRƒƒ“ƒg+‹ó”’Œn‚Ì•¶Žš‚ð‚»‚Ì‚Ü‚Ü“n‚·
  repeat
    inCase := false;
    if p^ = #0 then exit;
    repeat
      CmtSkip(p); //ƒRƒƒ“ƒg+‹ó”’Œn‚Ì•¶Žš‚ð‚»‚Ì‚Ü‚Ü“n‚·
      s := prjCall(p, [':', ',', #254, '}', #0], 'mCase.tag'); // else=#254 end=}
      if LastSt = 'end' then begin
        msg('}/*switch(case) end*/ ');
        inCase := inCaseSv;
        CaseInBlock := CaseInBlockSv;
        exit;
      end else
        if LastSt = 'else' then begin
          msg('default:');
          break;
        end else begin
          msg('case ');
          msg(s);
          msg(':');
        end;
      q := p;
      if p^ in [',', ':'] then
        inc(p);
    until not (q[0] = ',');
    inCase := True;
    CaseInBlock := false;
    prj(p, [#0, ';', 'b', 'C'], 'mCase.code'); //'b'break 'C'begin`end‚ÌƒuƒƒbƒN‰ðœ
    inCase := false;
    if CaseInBlock then if p[0] = ';' then inc(p);

    if p^ in [';'] then copyC(p);

    msg('break; ');
  until p[0] = #0;

end;

procedure TuPas2JavaSc.mTry(var p: PChar);
var
  m, s: string;
begin
  NestLevel(+1);
  msg('try {/* */');
  prj(p, [#251, #0], 'mTry.In'); //finally ‚© except
  m := LastSt;
  if LastSt = 'except' then begin
    msg('} catch(e){'); //
    s := prjCall(p, [#0, #254, #250, '}'], 'mTry.catch'); //Else=#54 ON=#250 end=}
    if (LastSt = 'end') or (p^ = #0) then begin //ON‚ª‚È‚¢
      msg(s);
      msg('}'); //end ‚Ü‚Å
      NestLevel(-1);
      exit;
    end;
    msg(cvU('/* on ‚ÍŽ©‘O‚ÅC³‚µ‚Ä‚Ë@*/)'));
    msg(s);
    repeat
      if (LastSt = 'on') then begin
        msg(' if (e instanceof /*');
        prj(p, [#0, ':'], 'mTry.on');
        msg(cvU(' :š—vC³*/)'));
        prj(p, [#0, #253, ';'], 'mTry.do'); //Do=#253
        msg(') {');
        prj(p, [#0, ';'], 'mTry.doCode'); //
      end else break;
      prj(p, [#0, #254, #250, '}'], 'mTry.else'); //Else=#54 ON=#250 end=}
      if (LastSt = 'on') then begin
        msg('} else '); //
      end else
        if (LastSt = 'else') then begin
          msg('} else { '); //
          prj(p, [#0, #254, #250, ';'], 'mTry.elseCode'); //Else=#54 ON=#250 end=}
          msg('} ; '); //
          break;
        end else
          if (LastSt = 'end') then begin
            msg('} ; '); //
            msg('/* ******' + m + ' End********* */}'); //end ‚Ü‚Å
            NestLevel(-1);
            exit;
          end;
    until LastSt <> 'on';
  end else begin
    msg('} finally {');
  end;
  prj(p, [#0, '}'], 'mTry.finally');

  msg('/*' + m + ' End */}'); //end ‚Ü‚Å
  NestLevel(-1);
end;




procedure TuPas2JavaSc.mIF(var p: PChar);
begin
  msg('if(');
  msg(prjBool(p, [#0, #255], 'mIF')); //then‚Ü‚Å‚ð•Ô‚·
  msg(')');
  prj(p, [#0, #254, ';'], 'mIF.then'); //;‚© #254=else end’¼‘O‚Ü‚Å
  if (LastSt = 'else') then begin
    msg('else');
    prj(p, [';', #0], 'mIF.else');
  end;
end;



procedure TuPas2JavaSc.mRepeat(var p: PChar);
var
  ps: PChar;
  s: string;
begin
  msg('do{ /*repeat*/ ');
  msg(CAnsiGetAccordChars(p, cSpace)); //‹ó”’Œn‚Ì•¶Žš‚ð‚»‚Ì‚Ü‚Ü“n‚·
  NestLevel(+1);
  prj(p, [#0, #249], 'repeat'); //until‚Ü‚Å
  NestLevel(-1);

  CAnsiSkipBlank(p, true);
  s := prjBool(p, [#0, ';'], 'until'); //;‚Ü‚Å‚ð•Ô‚·
  ps := PChar(s);
  CmtSkipC(ps, cSpace);
  s := ps;
  s := trim(s);
  if SameText(s, 'true') then s := '!false';
  if SameText(s, 'false') then s := '!true';
  ps := PChar(s);
  if ps[0] = '!' then begin
    inc(ps);
    msg('}while ('); msg(ps); msg(')');
  end else begin
    msg('}while (!('); //˜_—‚ª‹t‚È‚Ì‚Å
    msg(s);
    msg(cvU('))/*until‚Ítrue‚ÅI—¹*/'));
  end;
end;

procedure TuPas2JavaSc.mWith(var p: PChar);
begin
  msg('with(');
  prj(p, [#0, #253], 'with'); //do‚Ü‚Å‚ð•Ô‚·
  msg(')');
  prj(p, [#0, ';'], 'with.code'); //end’¼‘O‚Ü‚Å
end;

procedure TuPas2JavaSc.mWhile(var p: PChar);
//var  sp: PChar;
begin
  msg('while(');
  msg(prjBool(p, [#0, #253], 'while')); //do‚Ü‚Å‚ð•Ô‚·
  msg(')');
  prj(p, [#0, ';'], 'while.code'); //end’¼‘O‚Ü‚Å

  //  sp := p;
//  msg(CAnsiGetAccordChars(p, cSpace)); //‹ó”’Œn‚Ì•¶Žš‚ð‚»‚Ì‚Ü‚Ü“n‚·
//  if sameText(CAnsiGetAccordChars(sp, LabelCharSet), 'begin') then begin
//    msg('{');
//    p := sp;
//    NestLevel(+1);
//    prj(p, [#0, '}'], 'while.code'); //end’¼‘O‚Ü‚Å
//    msg('}');
//    NestLevel(-1);
//  end;
end;

 {pascal  for i=0 to n do        for i=n downto m do
  javaSC  for(let i=0;i<=n;i++)  for(let i=n;i>=n;i--)
 }

procedure TuPas2JavaSc.mFor(var p: PChar);
var
  isInc: boolean;
  lab: string;
begin
  msg('for(');
  CAnsiSkipBlank(p);

  if p^ in ['_', 'A'..'Z', 'a'..'z'] then begin
    lab := CAnsiGetAccordChars(p, LabelCharSet);
    lab := setLabel(lab, lbInFunc);
    if isLet(lab) then msg(tagLET + ' ');
    msg(lab);
  end;
  prj(p, [#0, #252], 'for.to'); //to/downto‚Ü‚Å‚ð•Ô‚·
  isInc := LastSt = 'to';
  if isInc then msg(';' + lab + '<=')
  else msg(';' + lab + '>=');
  prj(p, [#0, #253], 'for.do'); //do‚Ü‚Å‚ð•Ô‚·
  if isInc then msg(';' + lab + '++ )')
  else msg(';' + lab + '-- )');
  NestLevel(+1);
  prj(p, [#0, ';'], 'for.code'); //;‚Ü‚Å‚ð•Ô‚·
  NestLevel(-1);
end;
{ ”’l•\Œ»‚Ìˆá‚¢
,      ,Pascal,javaSc
, 2i”,%0101 ,0b0101
, 8i”,&0123 ,0o0123
,16i”,$01aB ,0x01aB
‘¼‚Í‚Ù‚Ú“¯‚¶‚È‚Ì‚Å‚»‚Ì‚Ü‚Ü“n‚¹‚Î‚æ‚¢
+-•„†‚à‚»‚Ì‚Ü‚Ü“n‚¹‚Î‚æ‚¢‚Ì‚Å–³Ž‹
‚½‚¾”’l—ñ‚Ì”ÍˆÍ‚ðŠm”F‚·‚é•K—v‚ª‚ ‚é
@”.”E}”
}

procedure TuPas2JavaSc.kazu(var p: PChar);
var
  s: string;
  sp: PChar;
begin
  sp := p; inc(p);
  case sp^ of
    '&': s := '0o' + CAnsiGetAccordChars(p, ['0'..'7']); //8i”
    '%': s := '0b' + CAnsiGetAccordChars(p, ['0', '1']); //2i”
    '$': s := '0X' + CAnsiGetAccordChars(p, ['0'..'9', 'a'..'z', 'A'..'Z']); //16i”
    '0'..'9': begin
        s := sp^ + CAnsiGetAccordChars(p, ['0'..'9']);
        if p^ = '.' then begin //¬”“_‚ÌŒã‚É”Žš
          inc(p);
          s := s + '.' + CAnsiGetAccordChars(p, ['0'..'9']);
        end;
        if p^ in ['e', 'E'] then begin //E‚ÌŒã‚É•„†
          s := s + p^; inc(p);
          if p^ in ['+', '-'] then begin //E‚ÌŒã‚É•„†
            s := s + p^; inc(p);
          end;
          s := s + CAnsiGetAccordChars(p, ['0'..'9']);
        end;
      end;
  end;
  msg(s);
end;
{ •¶Žš•\Œ»‚Ìˆá‚¢
 Pascal '•¶Žš'‚Æ(#‚ÌŒã‚É”Žš)‚Ì˜A‘±  ''''‚Å'‚P•¶Žš

 javaSc '•¶Žš'‚©"•¶Žš"‚Å\\‚Í‚P•¶Žš\
,    ,Pascal,javaSc
, CR ,#13   ,\r \x0d
, LF ,#10   ,\n \x0a
,TAB ,#9    ,\t \x09
,FEED,#12   ,\f \x0c
,    ,''    ,\'
,    ,"     ,\"
,    ,\     ,\\
  }

procedure TuPas2JavaSc.moji(var p: PChar);
var
  s, n: string;
  c: Integer;
begin
  s := '';
  while true do begin
    if p^ = '#' then begin
      inc(p);
      n := CAnsiGetAccordChars(p, ['0'..'9']);
      if n <> '' then c := StrToInt(n) else c := 0;
      case c of
        9: s := s + '\t';
        10: s := s + '\n';
        13: s := s + '\r';
        12: s := s + '\f';
      else s := s + format('\x%2.2x', [c]);
      end;

    end else
      if p^ = '''' then begin
        inc(p);
        while not (p^ in [#0, #10..#13]) do
          if (p[0] = '''') then begin
            if (p[1] = p[0]) then begin
              inc(p, 2);
              s := s + '\''';
            end else begin
              inc(p);
              break;
            end;
          end else
            if (p[0] = '"') then begin
              inc(p);
              s := s + '\"';
            end else begin
              s := s + p[0];
              inc(p);
            end;

      end else break;
  end;
  msg('"'); msg(s); msg('"');
end;

procedure TuPas2JavaSc.msgNorm(s: string);
begin
  if Assigned(OnTextOut) then OnTextOut(s);
  if consOutDebug then write(s);
end;

procedure TuPas2JavaSc.msgBuf(s: string);
begin
  msgBufStr := addS([msgBufStr, s]);
  if consOutDebug then write(s);
end;

procedure TuPas2JavaSc.Exec(var p: PChar);
begin
  if consOutDebug then allocConsole;
  tagConst := 'const';
  tagLET := 'let';

  msg := msgNorm;
  finFunc := False;
  pasMode := pasExt;
  LabelCnt := 0;
  nestc := 0;
  ResultCnt := -1;
  SetLength(LabelName, 4096);
  prj(p, [#0], 'Exec');
end;

procedure writeFileStr(fname, s: ansistring);
var
  hin: THandle;
  rsize: DWORD;
begin
  rsize := 0;
  hin := CreateFile(pansichar(fname), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL, 0);
  if hin <> INVALID_HANDLE_VALUE then try
    windows.Writefile(hin, pansichar(s)^, Length(s), rsize, nil);
  finally CloseHandle(hin);
  end;
end;

procedure TPas2JavaScCalc.MsgOut(msg: AnsiString);
var
  w, sz: integer;
begin
  w := length(OutMsgStr);
  sz := length(msg);
  SetLength(OutMsgStr, w + sz);
  move(msg[1], OutMsgStr[w + 1], sz);
end;

function TPas2JavaScCalc.FileExec(const fname: AnsiString; p: PChar): boolean;
var
  s, fil: string;
begin
  Result := CAnsiFindStrs(p, ['#P2Js']);
  if Result then begin
    CAnsiSkipBlank(p);
    fil := '';
    if p[0] = '''' then begin
      inc(p);
      fil := CAnsiGetSplitStr(p, '''');
      CAnsiSkipBlank(p);
    end;
    s := CAnsiGetAccordChars(p, LabelCharSet);

    CAnsiGetNextStr(p, [#0, #13, #10]); // •¶ŽšƒZƒbƒg‚Ì‚Ç‚ê‚©–˜‚Ì•¶Žš—ñ
    CAnsiSkip(p, [#13, #10]);
    with TuPas2JavaSc.Create do try
      fDebug := SameText(s, 'debug');
      consOutDebug := s = 'Debug';
      endp := PChar(owner.MyCmd) + length(owner.MyCmd);
      OnTextOut := MsgOut;
      Exec(p);
    finally free end;
    if fil <> '' then begin writeFileStr(fil, OutMsgStr); end else
    begin owner.MsgOut(OutMsgStr); end;
  end;
end;

function TPas2JavaScCalc.LineCmd(const lab: AnsiString; var p: PChar): boolean;
var
  s: string;
begin
  Result := False;
  if SameText(lab, 'h') or (lab = '') then //help‚ÌŽž‚Íˆ—‚µ‚Ä‚àfalse‚ð•Ô‚·
  begin
    owner.MsgOutLn(cvU(
      '#P2Js ‚ÌsˆÈŒã‚É‘Î‚µ‚Ä ‹@ŠB“I‚È’uŠ·‚ðs‚¤'#13#10 +
      '# ƒRƒ“ƒ\[ƒ‹ƒ‚[ƒh‚Å‚Í1s’PˆÊ‚É‰ðŽß‚³‚ê‚é‚Ì‚Å“®ì‚µ‚È‚¢'#13#10 +
      ''));
  end;
  if not SameText(lab, 'P2Js') then exit;
  CAnsiSkipBlank(p);
  s := CAnsiGetAccordChars(p, LabelCharSet);
  CAnsiGetNextStr(p, [#0, #13, #10]); // •¶ŽšƒZƒbƒg‚Ì‚Ç‚ê‚©–˜‚Ì•¶Žš—ñ
  CAnsiSkip(p, [#13, #10]);
  with TuPas2JavaSc.Create do try
    fDebug := SameText(s, 'debug');
    endp := PChar(owner.MyCmd) + length(owner.MyCmd);
    OnTextOut := owner.MsgOut;
    Exec(p);
  finally free end;

end;


procedure TPas2JavaScCalc.StartEndScript(n: Integer);
begin
  case n of //0:start 1:end;
    0: begin
      end;
    1: begin
      end;
  end;
end;




initialization
  CalcAddTCalcuAddition(TPas2JavaScCalc);
end.

