Browse Source

[PATCH 035/188] adding parser

From 287588a80cd263eba59e38de6fdafb48511a86e0 Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <[email protected]>
Date: Wed, 20 Nov 2019 00:31:34 -0500

git-svn-id: branches/wasm@46031 -
nickysn 5 years ago
parent
commit
3a3d299599
1 changed files with 192 additions and 1 deletions
  1. 192 1
      utils/wasmbin/watparser.pas

+ 192 - 1
utils/wasmbin/watparser.pas

@@ -5,7 +5,7 @@ unit watparser;
 interface
 
 uses
-  SysUtils, Classes, parseutils, wasmtext;
+  SysUtils, Classes, parseutils, wasmtext, wasmmodule, wasmbin;
 
 type
   TWatToken = (weNone, weError,
@@ -40,6 +40,8 @@ type
     resText   : string;
     procedure SetSource(const abuf: string);
     function Next: Boolean;
+
+    function GetInt32: Integer;
   end;
 
 const
@@ -79,6 +81,18 @@ const
 
 function ScanString(const buf: string; var idx: integer): string;
 
+
+type
+  TParseResult = record
+    error : string;
+  end;
+
+//function ConsumeToken(sc: TWatScanner; tk: TWatToken): Boolean;
+function ParseModule(sc: TWatScanner; dst: TWasmModule; var res: TParseResult): Boolean;
+procedure ErrorUnexpected(var res: TParseResult; const tokenstr: string = '');
+procedure ErrorExpectButFound(var res: TParseResult; const expected: string; const butfound: string = '');
+procedure ErrorUnexpectedEof(var res: TParseResult);
+
 implementation
 
 procedure GetGrammar(const txt: string; out entity: TWatToken; out instByte: byte);
@@ -240,4 +254,181 @@ begin
     resText := Copy(buf, ofs, idx-ofs);
 end;
 
+function TWatScanner.GetInt32: Integer;
+var
+  err: integer;
+begin
+  Val(resText, Result, err);
+  if err<>0 then Result:=0;
+end;
+
+function ConsumeOpenToken(sc: TWatScanner; tk: TWatToken): Boolean;
+begin
+  sc.Next;
+  Result := (sc.token=weOpenBrace) or (sc.Token=tk);
+  if Result and (sc.token=weOpenBrace) then begin
+    sc.Next;
+    Result := (sc.Token=tk);
+  end;
+end;
+
+function ConsumeToken(sc: TWatScanner; tk: TWatToken; var res: TParseResult): Boolean;
+begin
+  Result:=sc.token =tk;
+  if not Result then
+    ErrorExpectButFound(res, 'some token','?')
+  else
+    sc.Next;
+end;
+
+function ParseNumOfId(sc: TWatScanner; out num: integer; out id: string; var res: TParseResult): Boolean;
+begin
+  num:=-1;
+  id:='';
+  Result := sc.Next;
+  if not Result then begin
+    ErrorUnexpectedEof(res);
+    Exit;
+  end;
+
+  case sc.token of
+    weNumber: num:=sc.GetInt32;
+    weIdent: id:=sc.resText;
+  else
+    ErrorExpectButFound(res, 'index');
+    Result := false;
+  end;
+  Result := true;
+  if Result then sc.Next;
+end;
+
+function TokenTypeToValType(t: TWatToken; out tp: byte): Boolean;
+begin
+  Result:=true;
+  case t of
+    wei32: tp:=valtype_i32;
+    wei64: tp:=valtype_i64;
+    wef32: tp:=valtype_f32;
+    wef64: tp:=valtype_f64;
+  else
+    tp:=0;
+    Result:=false;
+  end;
+end;
+
+function ParseParam(sc: TWatScanner; out id: string; out tp: byte; var res: TParseResult): Boolean;
+begin
+  tp:=0;
+  id:='';
+  if sc.token=weParam then sc.Next;
+
+  if sc.token=weIdent then begin
+    id:=sc.resText;
+    sc.Next;
+  end;
+
+  if not TokenTypeToValType(sc.token, tp) then begin
+    ErrorExpectButFound(res, 'type');
+    Result:=false;
+    Exit;
+  end else
+    Result:=true;
+  sc.Next;
+  Result := sc.token=weCloseBrace;
+  if Result then sc.Next
+  else ErrorExpectButFound(res, ')');
+end;
+
+function ParseFunc(sc: TWatScanner; dst: TWasmFunc; var res: TParseResult): Boolean;
+var
+  nm : integer;
+  id : string;
+  p  : TWasmParam;
+begin
+  if sc.token=weFunc then sc.Next;
+  repeat
+    if sc.token=weIdent then begin
+      dst.id:=sc.resText;
+      sc.Next;
+    end;
+
+    Result:=false;
+    if sc.token=weOpenBrace then begin
+      sc.Next;
+      case sc.token of
+        weType: begin
+          if not ParseNumOfId(sc, nm, id, res) then Exit;
+          if nm>=0 then dst.typeIdx:=nm
+          else dst.typeId:=id;
+        end;
+        weParam: begin
+          sc.Next;
+          p:=dst.GetInlineType.AddParam;
+          if not ParseParam(sc, p.id, p.tp, res) then Exit;
+        end;
+        weResult: begin
+          sc.Next;
+          p:=dst.GetInlineType.AddResult;
+          if not ParseParam(sc, p.id, p.tp, res) then Exit;
+        end;
+        weLocal: begin
+          sc.Next;
+          p:=dst.AddLocal;
+          if not ParseParam(sc, p.id, p.tp, res) then Exit;
+        end;
+      else
+        ErrorUnexpected(res, 'booh');
+        Exit;
+      end;
+      if not ConsumeToken(sc, weCloseBrace, res) then Exit;
+    end;
+
+  until sc.token=weCloseBrace;
+  sc.Next;
+end;
+
+function ParseModule(sc: TWatScanner; dst: TWasmModule; var res: TParseResult): Boolean;
+begin
+  if not ConsumeOpenToken(sc, weModule) then begin
+    Result := false;
+    Exit;
+  end;
+
+  repeat
+    sc.Next;
+    if sc.token=weOpenBrace then begin
+      sc.Next;
+
+      if sc.token = weFunc then begin
+        Result := ParseFunc(sc, dst.AddFunc, res);
+        if not Result then Exit;
+      end;
+
+    end else if sc.token<>weCloseBrace then begin
+      ErrorUnexpected(res);
+      Result := false;
+      exit;
+    end;
+
+  until sc.token=weCloseBrace;
+  Result := true;
+end;
+
+procedure ErrorUnexpected(var res: TParseResult; const tokenstr: string);
+begin
+  res.error:='unexpected token '+tokenstr;
+end;
+
+procedure ErrorUnexpectedEof(var res: TParseResult);
+begin
+  res.error:='unexpected end of file';
+end;
+
+procedure ErrorExpectButFound(var res: TParseResult; const expected, butfound: string);
+begin
+  res.error:=expected +' is expected';
+  if butfound<>'' then
+    res.error:=res.error+', but '+butfound+ ' found';
+end;
+
 end.