構文解析とは
構文解析とは、ソースコードの構造を解析し、コンピュータが扱える形式へ変換する処理です。構文解析によって、プログラムを文法上の構造として扱えるようになります。
一般的な構文解析は、字句解析(Lexer/レキサー)、構文解析(Parser/パーサー)、抽象構文木(AST)の生成の3つの工程で行われます。まず字句解析器によってソースコードをトークンと呼ばれる単位に分割し、次に構文解析器によって文法規則に従った構造を組み立てます。最後に、その解析結果を抽象構文木(AST)として表現することで、プログラムの構造を階層的に扱えるようになります。
UWSC構文解析ツールでは、UWSCのソースコードに対してこれらの処理を実行し、トークン列や抽象構文木、構文エラー情報を確認できます。
字句解析(Lexer)
字句解析とは、プログラミング言語などのソースコードを意味を持つ最小単位であるトークン(Token)の列に分解する処理のことです。
例えば、上記のプログラムの字句解析を行うと以下のような結果となります。以下のようにトークンを順番に並べたものをトークン列と言います。
typeは以下のような種類があります。
| type | 意味 | valueの内容 |
|---|---|---|
| NEWLINE | 改行 (\r\n/\r/\n いずれも統一) | 常に\n |
| WHITESPACE | 半角スペース・タブの連続 | 実際の空白文字列(例:" ","\t") |
| COMMENT | //から行末までのコメント | //を含むコメント全文 |
| NUMBER | 数値リテラル(整数・小数・指数表記) | 数字部分の文字列 (例:"123","1.5","1e10") |
| LINE_CONTINUE | 行結合の_ | "_" |
| SYNTAX | 予約語(DIM, IF, FOR, PROCEDURE等、lexer-config.jsonのsyntaxesに登録) | 元の表記そのまま(大文字小文字は保持、判定はstrtoupperで行う) |
| FUNCTION | 組み込み関数名(GETID, MSGBOX 等、functionsに登録) | 元の表記 |
| SPECIAL | 特殊変数(PARAM_STR, G_MOUSE_X等、specialsに登録) | 元の表記 |
| CONSTANT | 定数(TRUE, VK_A 等、constants.allに登録) | 元の表記 |
| IDENTIFIER | 上記いずれにも該当しない識別子(変数名・ 関数名・プロパティ名等) | 元の表記 |
| GLOBAL | GLOBALキーワード(識別子より優先判定) | "GLOBAL"(表記そのまま) |
| THIS | THIS キーワード | "THIS" |
| HEX | 16進数リテラル $FF 形式 | $を含む文字列 (例:"$FF") |
| STRING | 引用符(")で囲まれた文字列 | 引用符を除いた中身 |
| TEXTBLOCK_BODY | TEXTBLOCK~ENDTEXTBLOCK間の本文(1行分) | その行の生テキスト |
| SYMBOL | 演算子・区切り記号(=().+-*/<>:{}[]!;や2文字演算子<><=>=) | 該当する記号(1〜2文字) |
| COMMA | カンマ | ","(他の記号と分離して独立type) |
| ERROR | 字句解析エラー(不正な16進数・未列・不明文字) | エラーの原因となった文字列。meta.errorTypeに種別(INVALID_HEX/UNTERMINATED_STRING/UNKNOWN_CHAR) |
字句解析では、キーワード、変数名、数値、文字列、演算子などを識別します。
構文解析(Parser)
構文解析とは、文法規則に従って文字列や文の構造を分析し、構成要素同士の関係を明らかにすることです。
以下のトークン列を例に手順を説明します。
- IF文の開始
-
まず最初のトークンを確認します。
IFB(SYNTAX)なのでIF文の解析を開始します。
IF文の定義は以下のとおりです。
- 条件式を解析
-
2つ目以降のトークンを見て条件式を読み取ります。
A = 1の識別子 演算子 値という形式は文法として問題ないため、条件式として正常と判断します。
WHITESPACEは文法に無関係のため解析時には無視されます。
- THENを確認
-
条件式の後にTHENがあることを確認します。
- IF文の本体を解析
-
IF文の本体を解析します。
PRINT文の文法として問題ないため、正常と判断します。
- ENDIFを確認
-
IFB文の終了位置ではENDIFが必要です。
期待したトークンが存在するため、IFB文全体が正しい文法であると判断されます。
構文解析では、文の構造やキーワードの対応関係を確認し、プログラム全体の意味を組み立てます。
抽象構文木(AST)
字句解析で生成されたトークン列をもとに、構文解析ではプログラムの文法構造を表す抽象構文木(AST: Abstract Syntax Tree)を生成します。抽象構文木は、ソースコードを木構造で表現したもので、IF文やFOR文、関数呼び出し、演算式などの構造を階層的に保持します。構文解析では文法規則に従ってトークンを読み進め、対応するノードを作成しながら木構造を構築します。これによりプログラムの構造を機械的に扱えるようになり、構文チェックやコード補完、静的解析などの処理に利用できます。
この抽象構文木(AST)の最上位ノードはIfStatementです。IfStatementはIF文全体を表すノードで、条件式を表すcondition、条件が真の場合に実行する処理を表すthen、ELSEIFの処理を格納するelseif、ELSEの処理を格納するelseを持ちます。この例ではconditionとthenが設定されており、elseifは空の配列、elseはnullになっています。
conditionには、条件式を表すBinaryExpressionが格納されています。これは、ソースコードのA = 1に対応します。BinaryExpressionのoperatorには演算子=、leftには左辺のidentifier、rightには右辺のnumberが格納されています。
leftのidentifierはソースコードのAに対応し、nameには識別子名であるAが格納されています。一方、rightのnumberはソースコードの1に対応し、valueには数値を表す1が格納されています。
thenには、条件が真の場合に実行する処理を表すBlockStatementが格納されています。このBlockStatementは、ソースコードのIF文の本体に対応します。そのbodyには実行する文が配列として格納され、この例ではPRINT Aに対応するPrintStatementが一つ含まれています。
PrintStatementのargumentsには、PRINT文で出力する値が格納されています。この例では、ソースコードのPRINT Aに含まれるAに対応するidentifierが格納され、そのnameにAが設定されています。
このようにASTでは、ソースコードの各構文が対応するノードに変換され、ノードのプロパティによってさらに詳細な構造が表現されます。対応関係を整理すると、IF A = 1 THENはIfStatement、A = 1はBinaryExpression、左辺のAはidentifier、右辺の1はnumber、IF文の本体はBlockStatement、PRINT AはPrintStatementに対応します。
つまり、ASTはソースコードを単純に文字列として保持するのではなく、「どの構文が、どの構文の中に含まれているか」という対応関係を階層構造として表現しています。これにより、構文解析後のプログラムについて、文や式の種類だけでなく、それぞれの構成要素を個別に取り出して処理できるようになります。
UWSC構文解析ツール
UWSC構文解析ツールは、UWSCのソースコードをこれまでに解説した字句解析(Lexer)と構文解析(Parser)によって解析し、プログラムの構造を視覚的に確認できるエディタです。
入力したソースコードは字句解析器によってトークンへ分解され、構文解析器がUWSCの文法に従って解析します。その結果は抽象構文木(AST)として構築され、構文エラーや警告、ソースコード上の位置情報とともに確認できます。
エディタでは、AST・Raw AST・Tokenの表示やXPathによるAST検索に加え、自動補完、関数のシグネチャヘルプ、COM・OLEオブジェクトのメンバー補完など、UWSCのコードを調査・編集するための機能を利用できます。
このツールは単なるシンタックスハイライトではなく、字句解析、構文解析、AST、静的解析、自動補完を組み合わせて、UWSCのソースコードを構造的に扱うことができます。
エディタの解析機能
UWSC構文解析ツールの役割について解説します。
AST
ASTタブでは、Parserが生成した抽象構文木(AST)を階層構造として確認できます。
例えばIF文であれば、条件式やIF文の本体がそれぞれ対応するASTノードとして構成されます。このため、ソースコードを単なる文字列としてではなく、文法上の構造として確認できます。
Raw AST
Raw ASTとは生の抽象構文木でソースコードの構造をそのまま表現したデータ構造です。
Raw ASTタブでは、Parserが生成したASTの内部データ構造を確認できます。
ASTツリーとして表示した場合には分かりにくいプロパティや位置情報なども確認できるため、構文解析の結果を詳しく調べたり、Parserの動作を確認したりするときに利用できます。
トークン
トークンタブでは、字句解析器(Lexer)がソースコードから生成したトークンを確認できます。
トークンには、種類(type)、値(value)、行番号(row)、列番号(col)の情報が含まれています。ソースコードがどのように字句へ分解されているかを確認できるため、構文解析の最初の段階を調べる際に利用できます。
XPath検索
XPath検索では、生成されたASTから条件に一致するノードを検索できます。
特定の種類のASTノードを探したり、ASTの構造を調査したりするときに利用できます。ASTが大きくなった場合でも、目的の構文要素を効率よく確認できます。
自動補完
自動補完では、UWSCで使用する関数、構文、定数、COMオブジェクト(メソッド、プロパティ)、DOM、DLLなどを候補として表示します。
補完候補となる名前情報はデータベースまたはキャッシュから取得され、候補の重複排除やソートも行われます。
補完候補として表示されるのは、当サイトがデータベースに定義しているもののみとなります。特にCOMオブジェクト、DOM、DLLに関してはまだ登録が少ないため、実際には存在するメソッドやプロパティが候補として表示されないことがあります。
シグネチャヘルプ
シグネチャヘルプとは、エディタで(を入力したときに関数やメソッドの引数をヒントとして表示する機能のことです。
例えば、FOPEN(と入力したときは、次のような形式で引数情報を表示できます。
現在入力している引数の箇所はハイライトされ、省略可能な引数は[ ]で囲まれます。
COM・OLEオブジェクト補完
COM・OLEオブジェクトについても、ドット以降のメソッドやプロパティを補完候補として表示できます。
このようなコードでは、Workbooksが表すオブジェクトのメソッドやプロパティを候補として表示できます。
以下のASのように大文字で入力するとWorkbook オブジェクトのActiveSheet、ActiveSlicer、AutoSaveOnといった頭文字が一致するメソッドやプロパティが補完候補の上位に表示されます。
また、戻り値の型を一意に決定できない場合は、複数の型を保持したまま補完できます。
例えば、以下のようにSheets.Item(0)がWorksheet オブジェクトまたはChart オブジェクトのいずれかを返す可能性がある場合は、obj.ではそれぞれの型に対応するメンバーを補完候補として扱います。
複数の型候補があるobjを定義したときはすべての型をヒントとして表示しますが、Worksheet.AutoFilter プロパティ (Excel)のようにどちらの型か特定できるメソッドやプロパティを使用した場合、objはWorksheet オブジェクトとしてヒントに表示します。
Sheets.Item(0)の時点ではobjはWorksheet オブジェクト、Chart オブジェクトのどちらか特定できないが、Worksheet.AutoFilter プロパティ (Excel)はChart オブジェクトにはないメソッドのためobjはWorksheet オブジェクトと確定できます。
静的解析
Parserでは、構文の形だけを確認するのではなく、ASTを利用した静的解析も行います。
例えば、コンパイル時に値を確定できる式の評価、配列の次元やサイズの検証、変数への代入状態の追跡などを行います。
また、FOR、WHILE、REPEATなどのループについても、静的に判断できる範囲でシミュレーションを行い、変数の推定値などを解析します。
これにより、単純な文法エラーだけでは判断できない配列サイズや変数の状態についても、ソースコードの解析時に確認できます。
例えば以下のような配列宣言をした場合、二次元目が3というのは解析する時点でわかります。
しかし、次のように変数を使って宣言した場合、プログラムを実行してみないとDIM array[][i] のiに何の数字が代入されているのかわかりませんが変数の代入を追跡することで配列のサイズを特定します。
MODULEと省略メンバー
UWSCでは、MODULE内のメンバーについてTHISを省略した記述ができます。
例えば、MODULE内にsqrt関数が定義されている場合、
を次のように省略して記述できます。
Parserでは、このような省略メンバーをMODULE内の定義と照合して解析します。対象となるメンバーが同じMODULE内に定義されている場合は省略メンバーとして認識し、THISが省略されていますという警告を表示します。
一方、MODULE外の通常の場所で.sqrt(i)のような記述をした場合は、MODULE内の省略メンバーとは異なるため、エラーとして扱います。
WITH構文
WITH文では、対象となるオブジェクトを省略してメンバーへアクセスできます。
この場合、ドットから始まる.WorkbooksはWITHの対象であるExcelのメンバーとして解析されます。
ネストしたWITHでは、現在のスコープに近い対象からメンバーを解決します。なお、WITHによる省略メンバーとMODULE内のTHIS省略は、それぞれ異なる規則として扱われます。
アーカイブ
| バージョン | 日付 | ||
|---|---|---|---|
| 1 | 2026/10/06 | parser_20261006_1157.zip | ![]() |
UWSC構文への対応
ここからは、このツールの解析プログラム(PHPで実装したLexerとParser)が、UWSCの各構文をどのように処理しているかを説明します。
解析プログラムは、LexerがソースコードをTokenに分割し、Parserが構文ごとの解析メソッド(parseIf、parseForなど)でTokenを読み進めてASTを組み立てる、という分担で動いています。構文を認識するだけでなく、RESULTの使用状況、予約語の識別子利用、MODULEやWITHの省略メンバーといったUWSC特有の規則も、この解析の中で検証します。
以下では、Lexerが担当する内容(TEXTBLOCK、Unicode識別子、数値リテラル)と、Parserが担当する内容(制御構文、宣言構文、UWSC固有構文、識別子、RESULTの判定)に分けて説明します。
TEXTBLOCK
TEXTBLOCKは、通常のUWSCコードや文字列とは異なる特殊な構文としてLexerで処理します。
readTextBlockによってTEXTBLOCKからENDTEXTBLOCKまでの内容をまとめて読み取ることで、ブロック内部のテキストが通常のUWSCコードとして解析されることを防ぎます。
Unicode識別子
LexerではUnicode文字を含む識別子を扱えるように、識別子の開始文字と構成文字を判定する処理を備えています。これにより、日本語などのUnicode文字を含む識別子を解析できます。
また、ソースコード中に含まれる不可視Unicode文字を検出する処理も用意されています。
数値リテラル
数値リテラルは、次の形式を解析できます。
- 整数
- 小数
- 指数表記
- $FF形式などの16進数
Lexerが数値をTokenとして認識し、Parserでは式の一部として扱います。
制御構文
UWSCの条件分岐、ループ、SELECT文などの制御構文は、それぞれ専用の解析処理で扱います。
- parseIf
- IF / IFB文を解析します。1行IF、ブロックIF、ELSEIF、ELSEに対応します。
- parseFor
- FOR...TO...NEXTおよびFOR...IN...NEXTを解析します。
- parseWhile
- WHILE...WENDを解析します。
- parseRepeat
- REPEAT...UNTILを解析します。
- parseSelect
- SELECT...CASE...DEFAULT...SELENDを解析します。
- parseCase
- SELECT文のCASE節を解析します。
- parseDefault
- SELECT文のDEFAULT節を解析します。
- parseStatementsUntil
- 指定された終了キーワードのいずれかが現れるまで、文を順番に解析します。
これらの処理によって、IF / ELSEIF / ELSE、FOR、WHILE、REPEAT、SELECT / CASE / DEFAULTなどの制御構文を解析します。
宣言構文
変数、定数、スレッド、OPTIONなどの宣言に関する構文も、それぞれ専用の解析処理で扱います。
- parseDim
- DIM文を解析し、変数宣言、配列宣言、初期値などを処理します。
- parsePublic
- PUBLIC文によるグローバル変数の宣言を解析します。
- parseConst
- CONST文による定数宣言を解析します。
- parseThread
- THREAD文による別スレッドでの関数呼び出しを解析します。
- parseOption
- OPTION文を解析します。
UWSC固有構文
UWSC特有の構文についても、それぞれ専用の解析処理を用意しています。
- parseClass
- CLASS...ENDCLASS構文を解析します。
- parseModule
- MODULE...ENDMODULE構文を解析します。
- parseDll
- DEF_DLLによるDLL宣言を解析します。
- parseProcedure
- PROCEDURE...FEND構文を解析します。
- parseFunction
- FUNCTION...FEND構文を解析し、RESULT代入の有無も確認します。
- parseWith
- WITH...ENDWITH構文を解析します。
- parseTextblock
- TEXTBLOCK...ENDTEXTBLOCK構文を解析します。
- parseHashTbl
- HASHTBL宣言を解析します。
- parseTry
- TRY...EXCEPT/FINALLY...ENDTRY構文を解析します。
- parseComErr
- COM_ERR_IGN...COM_ERR_RET構文を解析します。
- parsePrint
- PRINT文を解析します。
このように、CLASS、MODULE、DLL、PROCEDURE、FUNCTION、WITH、TEXTBLOCK、HASHTBL、TRY、COM_ERR、PRINTなど、UWSC固有の構文をそれぞれの文法に合わせて解析します。
識別子
UWSCでは、文脈によって予約語として扱われる単語を識別子として使用する必要がある場合があります。
- expectIdentifierAllowKeyword
- 識別子を期待し、予約語であっても警告を表示した上で識別子として許可します。
- parseIdentifierAllowKeyword
- 識別子または予約語を1つ読み取り、その値とTokenの型を返します。
この処理により、UWSCの構文上必要となる識別子を文脈に応じて解析できます。
RESULTの判定
FUNCTIONなどでRESULTが使用されているかを確認するため、ASTを再帰的に走査してRESULT代入の有無を判定します。
- containsResult
- ASTノードを再帰的に走査し、ResultStatement(RESULT=の代入)が含まれているかを判定します。
この判定は、FUNCTIONの解析時にRESULTの使用状況を確認するために利用されます。
インターフェイス
ここでは、解析プログラムを構成する部品の仕様を説明します。インターフェイスとは、各部品がどのようなメソッドを持ち、どのような形のデータを受け渡すかを定めた取り決めのことです。
前半はプログラム側の仕様で、Lexer、Token、Parserの各クラスが持つメソッドを一覧にしています。解析プログラムの構造を知りたいときや、処理を追いかけたいときに参照してください。
後半はデータ側の仕様で、解析結果として出力されるASTの各ノードが、どのプロパティをどの型で持つかを定義しています。出力されたASTを読み取って利用するときに参照してください。
Lexerインターフェイス
LexerはソースコードをToken列へ変換するクラスです。
主なメソッドは以下です。
- __construct
- Lexerを初期化します。
- tokenize
- ソースコード全体を解析してToken列を生成します。
- readStringToken
- 文字列リテラルを読み取ります。
- readTextBlock
- TEXTBLOCKからENDTEXTBLOCKまでの特殊なテキストブロックを読み取ります。
- current
- 現在位置のTokenまたは文字を取得するために使用します。
- peek
- 現在位置を進めずに先のTokenや文字を確認します。
- advance
- Lexerの読み取り位置を進めます。
- readNumber
- 整数、小数、指数表記、$FF形式などの数値を読み取ります。
- peekChar
- 現在位置から指定位置の文字を確認します。
- readUtf8CharAt
- UTF-8文字を位置指定で取得します。
- isInvisibleUnicodeChar
- 不可視Unicode文字を判定します。
- isIdentifierStart
- 識別子の先頭として使用できる文字か判定します。
- isIdentifierChar
- 識別子の途中以降に使用できる文字か判定します。
- isIdentifierStartAt
- 指定位置が識別子の開始位置として有効か判定します。
- readIdentifier
- 識別子を読み取ります。
Tokenインターフェイス
TokenはLexerが生成する字句情報を保持します。
主なメソッドは以下です。
- __construct
- Tokenを生成します。
- toArray
- Tokenを配列形式へ変換します。
Tokenには、種類、値、位置情報など、Parserが構文解析に必要とする情報が保持されます。
Parserインターフェイス
ParserはToken列をUWSCの文法に従ってASTへ変換します。
Parserには、基本的なToken操作だけでなく、UWSC固有の構文を解析する多数のメソッドが実装されています。
Parserの基本インターフェイス
- __construct
- Parserを初期化します。
- checkParseGuard
- 解析処理が異常な状態になっていないかを確認します。
- guardStatementProgress
- 文の解析処理が進行していることを確認し、無限ループなどを防止します。
- getWarnings
- 解析中に登録された警告を取得します。
- addWarning
- 警告を追加します。
- tokenEndColumn
- Tokenの終了列を取得します。
- createLocation
- ASTノードの位置情報を生成します。
- createNode
- ASTノードを生成します。
- parse
- プログラム全体を解析します。
- calcIndex
- ASTノードのインデックス情報を計算します。
- attachIndexes
- ASTにインデックス情報を付加します。
- buildTokenHtml
- Token表示用HTMLを生成します。
Parserの静的解析インターフェイス
- applyPureFunction
- PURE_FUNCTIONSに登録された関数(ABS/INT/CEIL/ROUND/SQRT/POWER)を実際に計算します。
- evaluateNode
- ASTノードを再帰的に評価し、コンパイル時に確定する数値へ還元できるか判定します。
- resolveDimensionValue
- DIMの次元式を解決し、コンパイル時定数の整数値を返します。
- validateArraySize
- DIMノードの次元定義と初期化要素数を照合し、配列サイズが有効かを検証します。
- checkArraySizeLimit
- 配列の総要素数がUWSCインタプリタの確保上限を超えていないか検証します。
- trackAssignment
- 単純代入文の右辺を評価し、compileTimeValuesを更新または無効化します。
- collectAssignmentTargets
- ASTサブツリーを走査し、スカラー変数への代入対象の変数名を収集します。
- invalidateAssignedVars
- ループ本体をシミュレートできなかった場合に、代入された可能性のある変数を無効化します。
- simulateStraightLineStatement
- FOR...TO...NEXTの本体にある1文が、直線的な代入としてシミュレートできるかを判定・実行します。
- simulateForToLoop
- FOR...TO...NEXTの本体を、指定した反復回数だけ実際にシミュレート実行します。
- evaluateConditionNode
- WHILE/REPEATの条件式を、現在のcompileTimeValuesから静的評価します。
- simulateWhileLoop
- WHILE本体を、条件が真である間だけ最大反復回数までシミュレートします。
- simulateRepeatLoop
- REPEAT本体を少なくとも1回実行してから、UNTIL条件を評価するシミュレーションを行います。
これらは単純な構文解析だけでなく、配列サイズ、変数代入、ループなどを追跡するために使用されます。
Token操作インターフェイス
- peek
- 現在位置のTokenを確認します。
- peekAt
- 任意の位置のTokenを確認します。
- consume
- Tokenを消費して次へ進みます。
- expect
- 指定されたTokenが存在することを確認し、消費します。
- expectValue
- 指定された値を持つTokenを期待します。
- consumeLineEnd
- 行末を処理します。
- skipSeparators
- 区切り文字や空白などを処理します。
条件式・式の解析
- parseCondition
- 条件式のエントリポイントで、OR演算からのパースチェーンを開始します。
- parseConditionOr
- 条件式のOR演算を左結合でパースします。
- parseConditionXor
- 条件式のXOR演算を左結合でパースします。
- parseConditionAnd
- 条件式のAND演算を左結合でパースします。
- parseConditionComparison
- 条件式の比較演算子(=, <>, >, <, >=, <=)を左結合でパースします。
- parseExpression
- 一般式のエントリポイントです。代入式をパースした後、演算子なしで識別子等が続く場合はエラーにします。
- parseOr
- 一般式のOR演算を左結合でパースします。
- parseXor
- 一般式のXOR演算を左結合でパースします。
- parseAnd
- 一般式のAND演算を左結合でパースします。
- parseComparison
- 一般式の比較演算子(<>, >, <, >=, <=)を左結合でパースします。
- parseAdditive
- 加算・減算(+, -)を左結合でパースします。
- parseMultiplicative
- 乗算・除算・剰余(*, /, MOD)を左結合でパースします。
- parseUnary
- 単項演算子(-, +, !)をパースします。該当しなければparsePrimaryへ委譲します。
- parsePrimary
- 式の最小単位(数値・文字列・定数リテラル、識別子・関数・特殊変数、括弧式など)をパースします。
- parsePostfix
- 後置演算(メンバアクセス、関数呼び出し、配列アクセス)を連続してパースします。
- parseNot
- NOT演算子(!またはNOTキーワード)をパースします。
条件式、論理演算、比較、加減算、乗除算、単項演算、主式、後置演算などを段階的に解析します。
代入・引数・関数呼び出し
- parseAssignment
- 代入式(=)を右結合でパースします。
- parseArgumentList
- '(' から ')' までの関数引数リストをパースします。
- parseCall
- CALL文(外部.uwsファイルの呼び出し)を解析します。
- finishFunctionCall
- 確定したcallee式に対して引数リストを読み取り、関数呼び出しノードを生成します。
- parseAssign
- 識別子を左辺とする代入文を解析する旧実装です。関数呼び出しやプロパティチェーンにも対応します。
- parseParam
- PROCEDURE/FUNCTIONの引数(VAR修飾・配列次元・デフォルト値)を解析します。
- registerFunctionDefinition
- PROCEDURE/FUNCTIONの定義名を登録し、多重定義をエラーとして検出します。
これらは代入、引数リスト、関数呼び出し、関数定義、パラメータなどを処理します。
ASTノード
ASTには、UWSCの文、式、リテラル、宣言などを表現するノードが定義されています。
- CommentStatement
- 行単独で記述されたコメントを表す文ノードです。
- ExitStatement
- EXITおよびEXITEXITによるプログラム終了を表す文ノードです。
- BreakStatement
- BREAKによるループからの脱出を表す文ノードです。
- ContinueStatement
- CONTINUEによるループの次の周回への移行を表す文ノードです。
- ExpressionStatement
- 関数呼び出しや代入など、式を単独の文として扱うためのノードです。
- ResultStatement
- FUNCTION内でRESULTに戻り値を設定する代入を表すノードです。
- AssignmentExpression
- 変数、配列要素、メンバーなどへの代入式を表すノードです。
- LogicalExpression
- OR、XOR、ANDなどの論理演算を表すノードです。
- BinaryExpression
- 比較演算や加減算、乗除算などの二項演算を表すノードです。
- UnaryExpr
- 符号反転やNOTによる論理否定などの単項演算を表すノードです。
- Identifier
- 変数名、関数名、メンバー名などの識別子を表すノードです。
- GlobalThisMember
- GLOBALやTHISを基準としたメンバーアクセスを表すノードです。
- MemberExpression
- ドット演算子によるオブジェクトやモジュールなどのメンバーアクセスを表すノードです。
- NumberLiteral
- 整数、小数、16進数などの数値リテラルを表すノードです。
- StringLiteral
- ダブルクォートまたはシングルクォートで記述された文字列リテラルを表すノードです。
- ConstantLiteral
- TRUE、FALSEや各種組み込み定数など、CONSTANTとして認識された値を表すノードです。
- FunctionCall
- 組み込み関数、ユーザー定義関数、メソッドなどの関数呼び出しを表すノードです。
- IndexAccess
- 配列やハッシュテーブルなどへのインデックスアクセスを表すノードです。
- IfStatement
- IFおよびIFBによる条件分岐と、THEN・ELSEIF・ELSEの各節を表すノードです。
- ElseIfClause
- IF文に含まれるELSEIF節を表すノードです。
- BlockStatement
- 複数の文をひとまとまりのブロックとして表すノードです。
- ForInStatement
- FOR ... INによる配列やコレクションの反復処理を表すノードです。
- ForToStatement
- FOR ... TO ... STEPによる数値範囲の反復処理を表すノードです。
- WhileStatement
- WHILE ... WENDによる前判定型のループ処理を表すノードです。
- RepeatStatement
- REPEAT ... UNTILによる後判定型のループ処理を表すノードです。
- SelectStatement
- SELECT ... CASE ... DEFAULT ... SELENDによる条件分岐を表すノードです。
- CaseClause
- SELECT文内のCASE節と、その条件および実行する文を表すノードです。
- DefaultClause
- SELECT文でどのCASEにも一致しなかった場合に実行するDEFAULT節を表すノードです。
- DimDeclarator
- DIM宣言に含まれる個々の変数宣言を表すノードです。
- DimDeclaration
- DIMによるローカル変数の宣言全体を表すノードです。
- DimInitValue
- DIM宣言で指定された初期値と、必要に応じて配列の添字位置を表すノードです。
- HashtbleDeclaration
- HASHTBLによるハッシュテーブルの宣言を表すノードです。
- PublicDeclaration
- PUBLICによるグローバル変数の宣言を表すノードです。
- ConstDeclaration
- CONSTによる定数の宣言を表すノードです。
- CallStatement
- CALLによる外部UWSファイルの呼び出しを表すノードです。
- PrintStatement
- PRINTによる値の出力処理を表すノードです。
- WithStatement
- WITH ... ENDWITHによる対象オブジェクトを省略メンバー記法で扱うブロックを表すノードです。
- TextBlockStatement
- TEXTBLOCK ... ENDTEXTBLOCKによるテキストブロックを表すノードです。
- Option
- OPTION文に指定されたオプション名と値を表すAST上の構造です。
- ThreadStatement
- THREADによる非同期のスレッド処理を表すノードです。
- ComError
- COM_ERR_IGNからCOM_ERR_RETまでのCOMエラー処理ブロックを表すノードです。
- DllField
- DEF_DLLで使用する構造体引数の個々のフィールドを表すノードです。
- DllParam
- DEF_DLLで宣言するDLL関数の引数型を表す構造です。
- DllDeclaration
- DEF_DLLによる外部DLL関数の宣言を表すノードです。
- Param
- FUNCTIONまたはPROCEDUREの引数定義を表すノードです。
- FunctionDeclaration
- FUNCTION ... FENDによる戻り値を持つ関数定義を表すノードです。
- ProcedureDeclaration
- PROCEDURE ... FENDによる戻り値を持たない手続き定義を表すノードです。
- ModuleDeclaration
- MODULE ... ENDMODULEによるモジュール定義を表すノードです。
ASTの主要な役割
ASTでは、ソースコードを単なる文字列ではなく、構文上の意味を持った階層構造として扱います。
例えば、
IF 条件 THEN
処理
ENDIF
というコードは、IfStatementの中に条件とBlockStatementを持つような構造として表現できます。
また、
DIM A = 10
のようなコードでは、変数宣言、識別子、初期値などがそれぞれAST上の情報として保持されます。
ASTインターフェイス
インターフェイス(Interface)は、ASTノードや関連するデータ構造の形式を定義するための型定義です。 各インターフェイスは、その構造が持つプロパティ名とデータ型を定義し、構文解析によって生成されるASTがどのような構造を持つかを表します。インターフェイス同士は継承によって共通のプロパティを共有でき、個々のノード固有のプロパティを追加して定義します。
- InterfaceName
- インターフェイス名
- property
- プロパティ名。省略される可能性があるときはproperty?のようにプロパティ名のあとに?をつけます。
- Type
- 型名
- InterfaceName
- インターフェイス名
- ParentInterface
- 継承元のインターフェイス
- propertyName
- プロパティ名
- Type
- プロパティの型
- extends
- 親インターフェイスを継承し、そのプロパティを引き継ぐことを表します。
extendsを使用すると、親インターフェースのプロパティを継承しながら、新しいプロパティを追加して定義できます。ASTでは、多くのノードが共通のNodeインターフェースを継承し、共通のプロパティ(typeや位置情報など)を共有した上で、各ノード固有のプロパティを定義します。
ASTのインターフェイスは、Position、Location、Nodeを基礎として、Programや各種Statement・Expressionへ展開されます。以下では共通構造から個別ノードへ順に説明します。
Position
Positionは、ASTノードのソースコード上の位置を表すインターフェイスです。行番号と列番号を保持します。行番号・列番号はいずれも1始まりで、字句解析(Lexer)がトークンを生成する際に各トークンへ付与した位置情報がそのままASTノードへ引き継がれます。
- line
- ソースコード上の行番号を表します。
- column
- ソースコード上の列番号を表します。
Location
Locationは、ASTノードのソースコード上における開始位置と終了位置を表すインターフェイスです。ノードがソースコードのどの範囲に対応するかを示すために使われ、エディタ上でのハイライトやエラー位置の特定、AST Viewer上でのノード選択時のハイライト表示などに利用されます。
Node
Nodeは、ASTノードに共通する基本構造を定義するインターフェイスです。ノードの種類を示すtypeと、ソースコード上の位置を示すlocを持ちます。パーサ内ではcreateNode()メソッドが呼ばれるたびに、このNodeの形を満たすようにtypeとlocが自動的に付与され、個別のプロパティがそこへマージされます。ただし後述のとおり、一部のノード(ThreadStatement、ModuleDeclarationなど)はcreateNode()を経由せずに配列リテラルとして直接生成されるため、locを持ちません。
- type
- ASTノードの種類を表す文字列です。
- loc
- ASTノードがソースコード上のどの位置に対応するかを表す#locationです。
Program
Programは、解析対象となるプログラム全体を表すASTノードです。パーサの最上位ループがソースコード全体を先頭から順にparseStatement()し、その結果をbodyへ積み上げていくことで生成されます。ASTのルートノードは常にこのProgramであり、bodyには行コメント・宣言・制御構文などすべてのトップレベル文が並びます。
- type
- ノードの種類を表し、常にProgramです。
- body
- プログラム全体に含まれる文を格納した配列です。
CommentStatement
CommentStatementは、行単独で記述されたコメントを表す文ノードです。行末コメント(他の文の後ろに続くコメント)は独立したノードにはならず、対応する文の位置情報の範囲内に埋め込まれた扱いになります。あくまで「その行にコメントしか存在しない場合」にparseStatement()が生成する専用ノードです。
- type
- ノードの種類を表し、常にcommentです。
- value
- コメントの内容を表す文字列です。
ExitStatement
ExitStatementは、EXITおよびEXITEXITを表す文ノードです。EXITはUWSCスクリプトを即座に終了させる命令、EXITEXITはさらに強制的な終了を行う命令であり、どちらも構文上は後続のトークンを取らない単純な命令ですが、種類の区別をkindプロパティで保持します。
- type
- ノードの種類を表し、常にExitStatementです。
- kind
- 終了命令の種類を表します。exitはEXIT、exitexitはEXITEXITを表します。
BreakStatement
BreakStatementは、BREAK文を表すASTノードです。BREAKはFOR/WHILE/REPEATなどのループを脱出する命令で、levelに数値を指定することで多重ループを一度に何段階脱出するかを制御できます(省略時は1)。パーサはループの外側でBREAKが使われた場合やloopDepthを超えるlevelが指定された場合にはエラーとして扱い、ノードを生成しません。
- type
- ノードの種類を表し、常にBreakStatementです。
- level
- BREAKで指定された脱出レベルを表します。
ContinueStatement
ContinueStatementは、CONTINUE文を表すASTノードです。ループの残りの処理をスキップして次の周回へ進む命令で、BreakStatementと同様にlevelによって多重ループのどの階層まで作用するかを指定します。
- type
- ノードの種類を表し、常にContinueStatementです。
- level
- CONTINUEで指定された継続レベルを表します。
ExpressionStatement
ExpressionStatementは、式を単独の文として扱うためのASTノードです。UWSCでは関数呼び出しや代入式が単独で1行の文になることが多く(例:MsgBox("hello"))、parseStatement()は式を解析した結果がFunctionCallやASSIGNなど「文として成立しうる型」であればこのExpressionStatementでラップします。
- type
- ノードの種類を表し、常にExpressionStatementです。
- expression
- 文として実行される式を表します。
ResultStatement
ResultStatementは、FUNCTION内で戻り値を設定するRESULT = ...を表します。通常の代入(ASSIGN)とは区別され、代入の左辺が識別子RESULTである場合に限りこの専用ノードへ変換されます。ExpressionStatement.expressionとして現れるノードであり、FUNCTIONの本体内に最低1つ含まれていることをパーサがチェックします(含まれていない場合は構文エラー)。
- type
- ノードの種類を表し、常にResultStatementです。
- argument
- FUNCTIONの戻り値として設定する式を表します。
AssignmentExpression
AssignmentExpressionは、変数や配列要素、メンバへの代入を表すASTノードです。代入は式として定義されていますが、文としても扱われます。左辺に許可されるのはIdentifier(単純変数)、IndexAccess(配列要素)、MemberExpression(メンバアクセス)の3種類のみで、それ以外の式(数値リテラルや関数呼び出しなど)を左辺にした場合はパーサが構文エラーとして検出します。
- type
- ノードの種類を表し、常にASSIGNです。
- left
- 代入先を表します。識別子、配列アクセス、メンバアクセスのいずれかです。
- right
- 代入する値を生成する式を表します。
LogicalExpression
LogicalExpressionは、OR、XOR、ANDによる論理演算を表すASTノードです。優先順位は低い方からOR → XOR → AND → 比較演算子の順で、それぞれ左結合で構文解析されます。同じ優先順位の演算が連続する場合はネストしたLogicalExpressionとして表現されます。
- type
- ノードの種類を表し、常にLogicalExpressionです。
- operator
- 論理演算子を表します。OR、XOR、ANDのいずれかです。
- left
- 左辺の式を表します。
- right
- 右辺の式を表します。
BinaryExpression
BinaryExpressionは、比較、加減算、乗除算などの二項演算を表すASTノードです。比較演算子(= <> > < >= <=)と算術演算子(+ - * / MOD)の両方をこの1つのインターフェイスで表現しており、operatorプロパティの値によって区別します。算術演算は加減算より乗除算・MODの方が優先順位が高く、比較演算子は算術演算子よりさらに低い優先順位で解析されます。
- type
- ノードの種類を表し、常にBinaryExpressionです。
- operator
- 二項演算子を表します。比較演算子、算術演算子、MOD演算子が指定されます。
- left
- 演算子の左側にある式を表します。
- right
- 演算子の右側にある式を表します。
UnaryExpr
UnaryExprは、単項演算を表すASTノードです。-xのような符号反転や!x(またはNOTキーワード)による論理否定がこれにあたります。UWSCでは複数行にまたがる配列リテラルの継続表記として単項+が使われることもありますが、これは字句解析側で吸収されるため、UnaryExprのoperatorとしては現れません。
- type
- ノードの種類を表し、常にunaryです。
- operator
- 単項演算子を表します。-または!です。
- expr
- 単項演算子の対象となる式を表します。
Identifier
Identifierは、変数名などの識別子を表すASTノードです。UWSCでは変数の宣言(DIM/PUBLIC/CONST)やループ変数、関数の引数名など、あらゆる場面で識別子が使われ、それらは共通してこのIdentifierノードで表現されます。名前の大文字・小文字はソースコードに書かれた表記のまま保持され、比較を行う場合は呼び出し側でstrtoupper()相当の正規化が必要です。
- type
- ノードの種類を表し、常にidentifierです。
- name
- 識別子の名前を表します。
GlobalThisMember
GlobalThisMemberは、GLOBAL.xxxやTHIS.xxxのようなメンバアクセスを表します。GLOBALまたはTHIS自体を変数として使用する場合も含みます。通常のメンバアクセス(MemberExpression)とはtypeが異なり、両者ともにmemberという同じtype文字列を共有する点に注意が必要です(MemberExpressionはMemberExpressionというPascalCaseのtypeを持つため、実際には字面上区別できます)。GLOBAL/THISはモジュール・クラス内でのスコープ解決に使われる特別な識別子として扱われます。
- type
- ノードの種類を表し、常にmemberです。
- object
- GLOBALまたはTHISを表すIdentifierです。
- name
- アクセスするメンバ名を表します。
MemberExpression
MemberExpressionは、a.b.cのようなメンバアクセスを表すASTノードです。COMオブジェクトやモジュール内の変数・メソッドへのアクセス、ハッシュテーブルのプロパティ的な記法などに使われます。.が複数回連続する場合は、objectに前段のMemberExpressionがネストして格納され、左結合の木構造になります。
- type
- ノードの種類を表し、常にMemberExpressionです。
- object
- メンバアクセスの対象となる式を表します。
- property
- アクセスするプロパティ名をIdentifierで表します。
NumberLiteral
NumberLiteralは、数値リテラルを表すASTノードです。数値はvalueに文字列としてそのまま保持され、整数・小数・16進数などの区別や実際の数値への変換は評価側(AST消費側)の責務となります。
- type
- ノードの種類を表し、常にnumberです。
- value
- 数値リテラルの値を文字列として保持します。
StringLiteral
StringLiteralは、文字列リテラルを表すASTノードです。ダブルクォート・シングルクォートいずれで囲まれた文字列も、字句解析の段階でクォートが除去された内容がvalueに格納されます。
- type
- ノードの種類を表し、常にstringです。
- value
- 文字列リテラルの内容を表します。
ConstantLiteral
ConstantLiteralは、CONSTANTトークンから生成される定数を表すASTノードです。UWSCの組み込み定数(TRUE、FALSE、各種COM/DOM定数など)が字句解析の段階でCONSTANTとして識別され、構文解析ではこのConstantLiteralノードに変換されます。識別子(Identifier)とは異なるtype文字列を持つため、AST消費側は両者を区別して扱えます。
- type
- ノードの種類を表し、常にconstantです。
- name
- 定数名を表します。
FunctionCall
FunctionCallは、関数呼び出しを表すASTノードです。calleeには呼び出し対象の式(通常はIdentifierやMemberExpression)が入り、UWSCの組み込み関数・ユーザー定義関数・COMメソッド呼び出しなど、あらゆるname(...)形式の呼び出しがこのノードで表現されます。
- type
- ノードの種類を表し、常にFunctionCallです。
- callee
- 呼び出す関数を表す式です。
- arguments
- 関数に渡す引数の配列です。nullは連続したカンマなどによる空引数を表します。
IndexAccess
IndexAccessは、a[i]のような配列やインデックスによるアクセスを表すASTノードです。UWSCのHASHTBLではvar[index, HASH_KEY]のようにカンマ区切りで複数の値を一度に指定する記法があり、このような複数インデックスにも対応しています。
- type
- ノードの種類を表し、常にIndexAccessです。
- object
- インデックスアクセスの対象となる式を表します。
- index
- アクセスするインデックスを表す式です。
IfStatement
IfStatementは、IFおよびIFBによる条件分岐を表すASTノードです。THEN節、ELSEIF節、ELSE節を保持します。UWSCではTHENの後ろに改行せず処理を1つだけ書く「1行IF」と、改行してENDIFまでの複数文を書く「ブロックIF(IFB)」の2形式がありますが、いずれも同じIfStatementインターフェイスとして表現されます(1行IFで改行された場合は警告付きでブロックIFとして解析されます)。
- type
- ノードの種類を表し、常にIfStatementです。
- condition
- 条件判定に使用する式を表します。
- then
- 条件が成立した場合に実行されるTHEN節を表すBlockStatementです。
- elseif
- ELSEIF節を格納する配列です。
- else
- ELSE節を表します。ELSE節が存在しない場合はnullです。
このコードは以下のようなIfStatementとして解析されます(条件式・本文の内部構造は省略)。
ElseIfClause
ElseIfClauseは、IF文のELSEIF節を表すASTノードです。1つのIfStatementに対してELSEIFは0個以上繰り返し指定でき、それぞれが独立した条件式とTHEN節を持つため、elseif配列の要素として保持されます。
- type
- ノードの種類を表し、常にElseIfClauseです。
- condition
- ELSEIF節の条件式を表します。
- then
- 条件が成立した場合に実行される文を格納するBlockStatementです。
BlockStatement
BlockStatementは、複数の文をひとまとまりのブロックとして扱うASTノードです。THEN節、ELSE節、TRY節などの本体をラップするために使用されます。WhileStatementやRepeatStatementのbodyはBlockStatementでラップされず、文の配列がそのまま格納される点との違いに注意してください。
- type
- ノードの種類を表し、常にBlockStatementです。
- body
- ブロック内に含まれる文を格納した配列です。
ForInStatement
ForInStatementは、FOR ... INによる反復処理を表すASTノードです。配列やコレクションの各要素をvariableへ順に代入しながらbodyを繰り返し実行します。数値範囲を扱うForToStatementとは構文・意味の両方で異なるため、別インターフェイスとして定義されています。
- type
- ノードの種類を表し、常にForInStatementです。
- variable
- ループ変数を表すIdentifierです。
- target
- 反復処理の対象となる式を表します。
- body
- ループ内で実行される文を格納するBlockStatementです。
ForToStatement
ForToStatementは、FOR ... TO ... STEP ...による数値範囲の反復処理を表すASTノードです。STEPは省略可能で、省略時のstepはnullとなります(実行時の既定の増分は評価側の実装に委ねられます)。
- type
- ノードの種類を表し、常にForToStatementです。
- variable
- ループ変数を表すIdentifierです。
- from
- ループ変数の初期値を表します。
- to
- ループの終了値を表します。
- step
- ループごとの増減値を表します。STEPが指定されていない場合はnullです。
- body
- ループ内で実行される文を格納するBlockStatementです。
WhileStatement
WhileStatementは、WHILE ... WENDによるループ処理を表すASTノードです。条件を先頭で判定する前判定ループで、bodyはBlockStatementではなく文の配列としてそのまま保持される点が他のブロック系ノードと異なります。
- type
- ノードの種類を表し、常にWhileStatementです。
- condition
- ループを継続するかどうかを判定する条件式です。
- body
- ループ内で実行される文の配列です。BlockStatementではラップされません。
RepeatStatement
RepeatStatementは、REPEAT ... UNTILによるループ処理を表すASTノードです。条件を末尾で判定する後判定ループであり、少なくとも1回はbody内の処理が実行される点がWhileStatementとの意味的な違いです。
- type
- ノードの種類を表し、常にRepeatStatementです。
- condition
- ループの終了判定に使用する条件式です。
- body
- ループ内で実行される文の配列です。BlockStatementではラップされません。
SelectStatement
SelectStatementは、SELECT ... CASE ... DEFAULT ... SELENDによる条件分岐を表すASTノードです。expressionで判定した値をCASE節の各conditionsと順に比較し、一致した最初のCASE節が実行されます。どのCASEにも一致しない場合はDEFAULT節が実行されます(存在する場合)。
- type
- ノードの種類を表し、常にSelectStatementです。
- expression
- SELECTで判定対象となる式を表します。
- cases
- CASE節を格納する配列です。
- default
- DEFAULT節を表します。DEFAULT節が存在しない場合はnullです。
CaseClause
CaseClauseは、SELECT文内のCASE節を表すASTノードです。1つのCASEにカンマ区切りで複数の条件式を並べることができ(いずれか1つでも一致すればそのCASEが実行される)、それらはconditions配列にまとめて格納されます。
- type
- ノードの種類を表し、常にCaseClauseです。
- conditions
- CASE節で判定する条件式を格納した配列です。
- body
- CASE節に含まれる文の配列です。
DefaultClause
DefaultClauseは、SELECT文のDEFAULT節を表すASTノードです。どのCASE節の条件にも一致しなかった場合にのみ実行される文の集まりを保持します。
- type
- ノードの種類を表し、常にDefaultClauseです。
- body
- DEFAULT節に含まれる文の配列です。
DimDeclarator
DimDeclaratorは、DIM宣言における個々の変数宣言を表します。DIM文はDIM a, b[3], c = 1, 2のようにカンマ区切りで複数の変数を一度に宣言できるため、その1つ1つの宣言がDimDeclaratorとしてDimDeclaration.declarationsに並びます。配列の次元は先頭次元のみ省略でき、省略時や自動サイズ指定(-1)の場合は初期値の個数から要素数を逆算します。
- name
- 宣言する変数の名前を表します。
- dimensions
- 配列の次元を表す式の配列です。先頭の次元のみ省略でき、その場合はnullになります。
- init
- 変数の初期値を格納した配列です。初期値がない場合はnullです。
DimInitValue
DimInitValueは、DIM宣言で指定される初期値を表します。Expressionのフィールドに加えて、多次元配列ではindexを保持できます。多次元配列に初期値をフラットな並びで指定した場合(例:DIM a[1,1] = 1, 2, 3, 4)、各初期値がどの添字位置に対応するかをindexプロパティへ自動的に展開して格納します。
- index
- 多次元配列の初期値に対応するインデックスを表します。必要な場合のみ指定されます。
- [key: string]
- Expressionのフィールドなど、初期値を表すための任意のプロパティを保持します。
DimDeclaration
DimDeclarationは、DIMによる変数宣言を表すASTノードです。ローカルスコープの変数宣言を表し、宣言と同時に配列の次元指定・初期値指定を行うことができます。
- type
- ノードの種類を表し、常にDimDeclarationです。
- declarations
- DIMで宣言された変数の情報を格納する配列です。
HashtbleDeclaration
HashtbleDeclarationは、HASHTBLによるハッシュテーブル宣言を表すASTノードです。HASHTBL hash = HASH_CASECAREのようにオプションを指定できる点が、単なる変数宣言との違いです。
- type
- ノードの種類を表し、常にHashtbleDeclarationです。
- name
- ハッシュテーブルの名前を表します。
- option
- HASHTBL宣言に指定されたオプションを表します。指定されていない場合はnullです。
PublicDeclaration
PublicDeclarationは、PUBLICによる変数宣言を表すASTノードです。DIMとは異なりスクリプト全体(グローバルスコープ)から参照できる変数を宣言します。DimDeclarationと違い、PUBLICは1文で1変数のみを宣言する構文であるため、複数宣言のための配列(declarations)は持たず、name/initを直接プロパティとして持ちます。
- type
- ノードの種類を表し、常にPublicDeclarationです。
- name
- PUBLICで宣言する変数名を表します。
- init
- 変数の初期値を表す式です。初期値がない場合はnullです。
ConstDeclaration
ConstDeclarationは、CONSTによる定数宣言を表すASTノードです。宣言後に値を変更できない点がDIM/PUBLICとの意味的な違いであり、valueには必ず何らかの式が必要です(右辺を省略するとパーサがエラーを送出します)。
- type
- ノードの種類を表し、常にConstDeclarationです。
- name
- 定数名を表します。
- value
- 定数に設定する値を生成する式を表します。
CallStatement
CallStatementは、CALLによる外部UWSファイルの呼び出しを表すASTノードです。ファイル名の拡張子は.uwsのみ許可されており、拡張子が省略された場合はパーサが自動的に.uwsを補完します。呼び出し先へはCALL sub.uws(1, 2)のように引数を渡すことができます。
- type
- ノードの種類を表し、常にCallStatementです。
- file
- CALLで呼び出すUWSファイル名を表します。拡張子.uwsを含みます。
- args
- 呼び出し先へ渡す引数を格納した配列です。
PrintStatement
PrintStatementは、PRINTによる出力処理を表すASTノードです。デバッグ用に式の値を表示するための命令で、複数の値をまとめて渡すこともできます。
- type
- ノードの種類を表し、常にPrintStatementです。
- arguments
- PRINTで出力する式を格納した配列です。
WithStatement
WithStatementは、WITH ... ENDWITHによる処理を表すASTノードです。WITH対象のオブジェクトをスコープスタックへ積み、ブロック内で先頭の.から始まる省略メンバー記法(例:.Visible = TRUE)を使えるようにします。ネストしたWITHにも対応しており、内側のブロックでは直近のWITH対象が優先して解決されます。
- type
- ノードの種類を表し、常にWithStatementです。
- object
- WITHで対象となるオブジェクトを表す式です。
- body
- WITHブロック内で実行される文の配列です。
TextBlockStatement
TextBlockStatementは、TEXTBLOCK ... ENDTEXTBLOCKによるテキストブロックを表すASTノードです。ブロック内部はUWSCの構文としては解析されず、生のテキストとしてそのまま保持されます。名前を指定すると、そのブロックを識別子として参照できます(例:TEXTBLOCK MyText)。
- type
- ノードの種類を表し、常にTextBlockStatementです。
- name
- TEXTBLOCKに指定された名前を表します。名前が指定されていない場合はnullです。
- body
- テキストブロック内の生テキストを表します。改行で結合された文字列として保持されます。
TryStatement
TryStatementは、TRY ... EXCEPT/FINALLY ... ENDTRYによる例外処理構造を表すASTノードです。TRY節の実行中にエラーが発生した場合、EXCEPT節が指定されていればそちらへ処理が移り、FINALLY節が指定されていれば成功・失敗にかかわらず必ず実行されます。handlerTypeによってEXCEPTとFINALLYのどちらが後続しているかを区別します。
- type
- ノードの種類を表し、常にTryStatementです。
- tryBlock
- TRY節に含まれる文を格納するBlockStatementです。
- handlerType
- 後続する処理の種類を表します。EXCEPTまたはFINALLYのいずれかです。
- handlerBlock
- EXCEPTまたはFINALLY節に含まれる文を格納するBlockStatementです。
OptionValue
OptionValueは、OPTION文に指定される値の型を表すユニオン型です。数値、文字列、識別子のいずれかを保持します。OPTIONで指定できる値の種類はオプション名ごとに固定されているわけではなく、パーサはトークンの種類(NUMBER/STRING/IDENTIFIER)に応じて対応するOptionValueを生成します。
- type
- 値の種類を表します。number、string、identifierのいずれかです。
- value
- 数値または文字列型の値を表します。
- name
- 識別子型の値の名前を表します。
OptionStatement
OptionStatementは、OPTION文を表すASTノードです。EXPLICIT、SAMESTR、POSITION、LOGPATHなどのオプション名と、その値を保持します。値を取らないフラグ形式のOPTION(例:OPTION EXPLICIT)ではvalueがnullになり、値が必要なOPTION(例:OPTION POSITION = 0, 0)ではvalue.rightに単一のOptionValueまたはその配列が格納されます。
- type
- ノードの種類を表し、常にOptionStatementです。
- name
- OPTIONで指定されたオプション名を表します。
- value
- OPTIONに設定された値を表します。値が指定されていない場合はnullです。
- value.type
- 値の構造を表し、ソース定義では常にassignmentです。
- value.operator
- 代入演算子を表し、ソース定義では=です。
- value.right
- OPTIONに指定された値を表します。単一のOptionValueまたはOptionValueの配列です。
ThreadStatement
ThreadStatementは、THREADによるスレッド処理を表すASTノードです。他の多くのASTノードとは異なり、createNode()を経由しないためlocプロパティを持ちません。指定した関数を別スレッドとして非同期に実行するための命令です。
- type
- ノードの種類を表し、常にThreadStatementです。
- name
- THREADで実行する対象の名前を表します。
- arguments
- THREADに渡す引数を格納した配列です。
ComError
ComErrorは、COM_ERR_IGNからCOM_ERR_RETまでのCOMエラー処理ブロックを表すASTノードです。この区間内で発生したCOM関連のエラーを無視して処理を継続するための構文で、body内には通常の文がそのまま並びます。
- type
- ノードの種類を表し、常にComErrorです。
- body
- COMエラー処理ブロック内に含まれる文の配列です。
DllField
DEF_DLLの構造体引数{ }内の1フィールドを表すノードです。構造体はC言語のstructに相当する複合型で、各フィールドは型名のみを識別子として保持します(フィールド名自体は型名を兼ねており、値の受け渡しには使われません)。
- type
- ノード種別。フィールドは常に単純な識別子(型名)なので固定値 "identifier"。
- name
- フィールドの型名(例: "long", "hwnd", "str" など)。トークンの値をそのまま格納。
- line
- フィールドが出現したソースコード上の行番号(1始まり)。
DllParam
DllParamは、DEF_DLLで宣言するDLL関数の引数型を表すユニオン型です。構造体型またはプリミティブ型のいずれかを表します。プリミティブ型の引数には、先頭にVARを付けることで参照渡し(byref)を指定できます。
- type
- DLL引数の種類を表します。structまたはprimitiveです。
- fields
- 構造体型のDLL引数が持つフィールド名を格納した配列です。
- name
- プリミティブ型のDLL引数の型名を表します。
DllDeclaration
DllDeclarationは、DEF_DLLによるDLL関数宣言を表すASTノードです。外部DLLの関数をUWSCから呼び出せるようにするための宣言で、引数の型定義(構造体・プリミティブ)、戻り値の型、呼び出し先DLL名を保持します。
- type
- ノードの種類を表し、常にDllDeclarationです。
- line
- DLL宣言が記述された行番号を表します。
- name
- DLL関数の名前を表します。
- params
- DLL関数の引数定義を格納した配列です。
- return
- DLL関数の戻り値の型を表します。
- dll
- 呼び出し対象となるDLLファイル名を表します。
Param
Paramは、FUNCTIONまたはPROCEDUREの引数定義を表します。参照渡し(byref)、配列引数の次元数、デフォルト値の指定に対応しており、UWSCのFUNCTION f(a, VAR b, c[], d = 1)のような多様な引数宣言を1つの共通構造で表現します。
- name
- 引数名を表します。
- byref
- 引数を参照渡しするかどうかを表します。
- dimensions
- 引数に指定された配列次元の数を表します。
- default
- 引数のデフォルト値を表す式です。デフォルト値がない場合はnullです。
FunctionDeclaration
FunctionDeclarationは、FUNCTION ... FENDによる関数定義を表すASTノードです。戻り値を持つ点がPROCEDUREとの意味的な違いで、本体内には必ず1つ以上のRESULT代入(ResultStatement)が必要です(含まれない場合はパーサが構文エラーとして検出します)。モジュール・クラス直下で、モジュール名と同名のFUNCTIONを定義するとコンストラクタとして扱われます。
- type
- ノードの種類を表し、常にFUNCTIONです。
- name
- 関数名を表します。
- params
- 関数の引数定義を格納した配列です。
- body
- 関数本体に含まれる文の配列です。
ProcedureDeclaration
ProcedureDeclarationは、PROCEDURE ... FENDによるプロシージャ定義を表すASTノードです。戻り値を持たない点がFUNCTIONとの違いで、RESULT代入は不要です。こちらもモジュール・クラス直下でモジュール名と同名のPROCEDUREを定義するとコンストラクタとして扱われます。
- type
- ノードの種類を表し、常にPROCEDUREです。
- name
- プロシージャ名を表します。
- params
- プロシージャの引数定義を格納した配列です。
- body
- プロシージャ本体に含まれる文の配列です。
ModuleDeclaration
ModuleDeclarationは、MODULE ... ENDMODULEまたはCLASS ... ENDCLASSによるモジュール・クラス定義を表すASTノードです。parseBlock()がcreateNode()を使用しないためlocを持たず、代わりにlineを保持します。MODULEとCLASSは構文・機能ともにほぼ同一で、kindプロパティのみで区別されます。モジュール・クラス内で定義されたPROCEDURE/FUNCTIONは、そのモジュール階層でネームスペースが分けられ、モジュール名と同名の定義はコンストラクタとして扱われます。
- type
- ノードの種類を表し、常にmoduleです。
- kind
- 定義の種類を表します。moduleはMODULE、classはCLASSを表します。
- name
- モジュールまたはクラスの名前を表します。
- line
- モジュールまたはクラスの定義が記述された行番号を表します。
- body
- モジュールまたはクラスの内部に含まれる文の配列です。
参考文献
- JavaScript ASTを始める最初の一歩 | Web Scratch
- Appendix A. Syntax Tree Format — Esprima master documentation
- estree/es5.md at master · estree/estree · GitHub
- ESTree とは
公開日:
更新日:

