根據ECMAScript 規范:
在幾種情況下,詞法輸入元素的識別對消耗輸入元素的句法文法背景關系敏感。這需要詞法文法的多個目標符號。
兩個這樣的符號是InputElementDiv和InputElementRegExp。
在 ECMAScript 中, 的含義/取決于它出現的背景關系。根據背景關系,a/可以是除法運算子、正則運算式文本的開頭或注釋分隔符。詞法分析器自身無法區分除法運算子和正則運算式文字,因此它必須依賴來自決議器的背景關系資訊。
我想了解為什么這需要在詞法語法中使用多個目標符號。我對語言設計了解不多,所以我不知道這是由于某種語法的正式要求,還是只是約定俗成。
問題
- 為什么不像這樣使用單個目標符號:
InputElement ::
[...]
DivPunctuator
RegularExpressionLiteral
[...]
讓決議器告訴詞法分析器使用哪個產生式(DivPunctuatorvs RegExLiteral),而不是使用哪個目標符號(InputElementDivvs InputElementRegExp)?
在詞匯語法中使用多個目標符號的其他語言有哪些?
我們將如何對 ECMAScript 詞法語法進行分類?從 CSG 的正式定義的意義上來說,它不是背景關系相關的(即,其產生式的 LHS 沒有被終結符和非終結符的背景關系所包圍)。
uj5u.com熱心網友回復:
在該術語的形式語言定義中,說詞法產生“對消耗輸入元素的句法語法背景關系敏感”并不能使語法背景關系敏感。事實上,在幾乎所有非平凡的語法中都有“對句法語法背景關系敏感”的產生式。這是決議的本質:句法背景關系有效地提供了一組潛在可擴展的非終結符,這些在不同的句法背景關系中會有所不同,這意味著,例如,在大多數語言中,不能在需要運算式的地方輸入陳述句(盡管通常情況下,運算式是陳述句的一種表現形式)。
但是,不同之處并不涉及相同非終結符的不同擴展。“背景關系無關”語言所要求的是,無論非終結符出現在何處,非終結符的可能派生集合都是相同的集合。因此背景關系可以提供不同的非終結符選擇,但是每個非終結符都可以在不考慮其背景關系的情況下進行擴展。這就是語法沒有背景關系的意義。
正如您所注意到的,背景關系敏感性通常在文法中通過左側有模式而不是單個非終結符的文法抽象出來。在最初的定義中,背景關系——除了要擴展的非終結符之外的所有東西——都需要原封不動地通過產生式;只能擴展一個非終結符,但可能的擴展取決于背景關系,如產生式所示。上面隱含的是,有些語法可以用 BNF 撰寫,但它們甚至不符合背景關系敏感規則(或其他等效規則)。所以它不是一個二元劃分,無論是背景關系無關的還是背景關系相關的。一個文法可能兩者都不是(并且,由于空背景關系仍然是一個背景關系,任何背景關系無關文法也是背景關系敏感的)。最重要的是,當數學家說話時,他們使用單詞的方式有時是出乎意料的。但它總是有一個明確的基本定義。
在形式語言理論中,沒有詞法和句法產生式;只是制作。如果詞法產生式和句法產生式都沒有背景關系,那么整個文法就沒有背景關系。然而,從實際的角度來看,組合語法更難決議,原因有很多,我不打算在這里討論。事實證明,在詞法和句法分析器之間進行劃分,為一種語言撰寫語法并對其進行決議會更容易一些。
在經典模式中,詞法分析做第一,這樣分析器沒有看到單個字符。相反,句法分析是用“詞匯標記”的“字母表”(在非常擴展的意義上)完成的。這非常方便——例如,這意味著詞法分析可以簡單地洗掉空格和注釋,這極大地簡化了句法文法的撰寫。但它也降低了通用性,正是因為句法決議器不能“指導”詞法分析器做任何事情。詞法分析器在句法分析器意識到它的需求之前就已經完成了它要做的事情。
如果決議器能夠引導詞法分析器,它將以與引導自身相同的方式進行。在某些作品中,令牌非終結符將包括InputElementDiv和 而在其他作品中InputElementRegExp將是可接受的非終端。正如我所指出的,這不是背景關系敏感——它只是背景關系無關文法的正常功能——但它確實需要修改程式的組織以允許詞法分析器考慮決議器的目標. 這通常被(從業者,而不是理論家)稱為“詞匯反饋”,有時被稱為價值中立性較低的術語;它有時被認為是語言設計中的一個弱點,因為它違反了整齊分離的詞法分析器/決議器架構。C 是一個非常激烈的例子,而且確實存在人類難以決議的 C 程式,這是某種跡象。但是 ECMAScript 并沒有真正遇到這個問題。人們通常無需付出任何明顯的智力努力就可以區分除法運算子和正則運算式分隔符。而且,雖然實作 ECMAScript 決議器所需的詞法反饋確實使架構變得不那么整潔,但這也不是一項艱巨的任務。
無論如何,詞法語法中的“目標符號”只是 ECMAScript 參考文獻的作者決定使用的一個短語。那些“目標符號”只是普通的詞匯非終結符,就像任何其他產生式一樣,所以說有“多個目標符號”和說“決議器指示詞法分析器使用不同的產生式”沒有區別,我希望解決您提出的問題。
筆記
兩種背景關系中的詞匯差異不僅僅是
/含義不同。如果僅此而已,則根本不需要詞匯反饋。問題在于標記化本身發生了變化。如果操作是可行的,那么/=在a /=4/gi;是單個標記(復合賦值運算子),并且
gi是單個識別符號標記。但是,如果那時正則運算式文字是可能的(事實并非如此,因為正則運算式文字不能跟在識別符號之后),那么 the/和 the=將是單獨的標記, andg也是i。一些程式員更喜歡從一組產品構建的決議器(但不是寫這篇文章的人:-));它們通常被稱為“無掃描儀決議器”。在 ECMAScript 的無掃描器決議器中,不會有詞法反饋,因為沒有單獨的詞法分析。
形式語言理論的理論純度與撰寫實際編程語言的作業決議器的實際細節之間確實存在分歧。理論模型非常有用,如果不了解它們,就很難撰寫決議器。但是很少有決議器嚴格遵守模型,這沒關系。同樣,通俗地稱為“常規”的東西 運算式”在正式語言意義上根本不是正則的;一些“正則運算式”運算子甚至不是背景關系無關的(反向參考)。因此,假設某些理論結果(“正則運算式”)將是一個巨大的錯誤運算式可以在線性時間和常數空間中識別”)實際上是“正則運算式”庫。我不認為決議理論是計算機科學的唯一一個分支,它展示了這種二分法。
uj5u.com熱心網友回復:
為什么不像這樣使用單個目標符號:
InputElement ::
...
DivPunctuator
RegularExpressionLiteral
...
讓決議器告訴詞法分析器使用哪個產生式(DivPunctuator vs RegExLiteral),而不是使用哪個目標符號(InputElementDiv vs InputElementRegExp)?
請注意, DivPunctuator 和 RegExLiteral 本身不是產生式,而是非終結符。在這種情況下,它們是您為 InputElement 提議的產品中的右側(替代品)。因此,我將您的問題重新表述為:為什么不讓句法決議器告訴詞法決議器使用這兩種替代方案中的哪一種?(或者等效地,要抑制這兩個中的哪一個。)
在 ECMAScript 規范中,有一種機制可以實作這一點:語法引數(在第 5.1.5 節中解釋)。
例如,您可以定義引數Div,其中:
Div表示“斜線應被識別為 DivPunctuator”,并且~Div表示“斜線應該被識別為 RegExLiteral 的開始”。
那么你的生產就會變成
InputElement[Div] ::
...
[ Div] DivPunctuator
[~Div] RegularExpressionLiteral
...
但是請注意,句法決議器仍然必須告訴詞法決議器使用InputElement[ Div]或InputElement[~Div]作為目標符號,因此您回到規范的當前解決方案,模重命名。
在詞匯語法中使用多個目標符號的其他語言有哪些?
我認為大多數人都不會嘗試定義派生所有標記(或輸入元素)的單個符號,更不用說將其分成像 ECMAScript 的 InputElementFoo 這樣的變體,因此可能很難找到另一種在其規范中具有類似內容的語言.
相反,簡單地為不同型別的標記(例如識別符號、數字文字)的語法定義規則,然后從語法產生式中參考它們是很常見的。所以這有點像有多個詞匯目標符號,但不是(我會說)你問的那種感覺。
我們將如何對 ECMAScript 詞法語法進行分類?
它基本上是背景關系無關的,加上一些擴展。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/364384.html
