[PATCH 035/188] adding parser

From 287588a80cd263eba59e38de6fdafb48511a86e0 Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <skalogryz.lists@gmail.com>
Date: Wed, 20 Nov 2019 00:31:34 -0500

git-svn-id: branches/wasm@46031 -
This commit is contained in:
nickysn 2020-08-03 12:59:20 +00:00
parent f7ae46356b
commit 3a3d299599

View File

@ -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.