Skip to content

Commit

Permalink
Merge pull request #75 from rycont/fix-similar-function-header-parsin…
Browse files Browse the repository at this point in the history
…g-error

Fix similar function header parsing error
  • Loading branch information
rycont authored Jan 26, 2025
2 parents 9a01d23 + 7d5d3d0 commit 222c446
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 159 deletions.
2 changes: 1 addition & 1 deletion core/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
},
"name": "@dalbit-yaksok/core",
"exports": "./mod.ts",
"version": "0.2.0-RC.7"
"version": "0.2.0-RC.8"
}
33 changes: 33 additions & 0 deletions core/prepare/parse/dynamicRule/functions/declare-rule/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Expression, Identifier } from '../../../../../node/base.ts'
import { type Token, TOKEN_TYPE } from '../../../../tokenize/token.ts'
import type { PatternUnit } from '../../../type.ts'

export function functionHeaderToPattern(tokens: Token[]): PatternUnit[] {
const units = tokens.map(mapTokenToPatternUnit).filter(Boolean)
return units as NonNullable<(typeof units)[number]>[]
}

function mapTokenToPatternUnit(token: Token): PatternUnit | null {
if (token.type === TOKEN_TYPE.IDENTIFIER) {
return {
type: Identifier,
value: token.value,
}
}

if (token.type === TOKEN_TYPE.OPENING_PARENTHESIS) {
return {
type: Expression,
value: '(',
}
}

if (token.type === TOKEN_TYPE.CLOSING_PARENTHESIS) {
return {
type: Expression,
value: ')',
}
}

return null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Evaluable, Expression, Identifier } from '../../../../../node/base.ts'
import { DeclareFFI, FFIBody } from '../../../../../node/ffi.ts'
import { EOL } from '../../../../../node/misc.ts'
import { Token } from '../../../../tokenize/token.ts'
import { PatternUnit, Rule } from '../../../type.ts'
import { functionHeaderToPattern } from './common.ts'

const PREFIX: PatternUnit[] = [
{
type: Identifier,
value: '번역',
},
{
type: Expression,
value: '(',
},
{
type: Evaluable,
},
{
type: Expression,
value: ')',
},
{
type: Expression,
value: ',',
},
]

const SUFFIX: PatternUnit[] = [
{
type: EOL,
},
{
type: FFIBody,
},
]

export function tokensToFFIDeclareRule(headerTokens: Token[]): Rule {
const headerPattern = functionHeaderToPattern(headerTokens)
const pattern = [...PREFIX, ...headerPattern, ...SUFFIX]

return {
pattern,
factory: (nodes, matchedTokens) => {
const runtime = (nodes[2] as Identifier).value
const body = (nodes[nodes.length - 1] as FFIBody).code
const name = headerTokens
.map((token) => token.value)
.join('')
.trim()

return new DeclareFFI(
{
name,
runtime,
body,
},
matchedTokens,
)
},
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Expression, Identifier } from '../../../../../node/base.ts'
import { Block } from '../../../../../node/block.ts'
import { DeclareFunction } from '../../../../../node/function.ts'
import { EOL } from '../../../../../node/misc.ts'
import { Token } from '../../../../tokenize/token.ts'
import { PatternUnit, Rule } from '../../../type.ts'
import { functionHeaderToPattern } from './common.ts'

const PREFIX: PatternUnit[] = [
{
type: Identifier,
value: '약속',
},
{
type: Expression,
value: ',',
},
]

const SUFFIX: PatternUnit[] = [
{
type: EOL,
},
{
type: Block,
},
]

export function tokensToYaksokDeclareRule(headerTokens: Token[]): Rule {
const headerPattern = functionHeaderToPattern(headerTokens)
const pattern = [...PREFIX, ...headerPattern, ...SUFFIX]

return {
pattern,
factory: (nodes, matchedNodes) => {
const body = nodes[nodes.length - 1] as Block

const name = headerTokens
.map((token) => token.value)
.join('')
.trim()

return new DeclareFunction(
{
body,
name,
},
matchedNodes,
)
},
}
}
29 changes: 9 additions & 20 deletions core/prepare/parse/dynamicRule/functions/get-function-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,8 @@ import {
} from '../../../../type/function-template.ts'
import { Token, TOKEN_TYPE } from '../../../tokenize/token.ts'

export function getFunctionTemplatesFromTokens(
tokens: Token[],
functionDeclareRanges: [number, number][],
type: string,
) {
const functionTemplatesTokens = functionDeclareRanges.map(([start, end]) =>
tokens.slice(start, end),
)

const functionTemplates = functionTemplatesTokens.map((tokens) =>
convertTokensToFunctionTemplate(tokens, type),
)

return functionTemplates
}

function convertTokensToFunctionTemplate(
export function convertTokensToFunctionTemplate(
_tokens: Token[],
type: string,
): FunctionTemplate {
const tokens = _tokens.map((token) => ({ ...token }))

Expand All @@ -52,9 +35,16 @@ function convertTokensToFunctionTemplate(
}
}

if (token.value.includes('/')) {
return {
type: 'static',
value: [...token.value.split('/'), token.value],
}
}

return {
type: 'static',
value: [...token.value.split('/'), token.value],
value: [token.value],
}
})
.filter(Boolean) as FunctionTemplatePiece[]
Expand All @@ -69,7 +59,6 @@ function convertTokensToFunctionTemplate(
return {
name: functionName,
pieces,
type,
}
}

Expand Down
40 changes: 21 additions & 19 deletions core/prepare/parse/dynamicRule/functions/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { getFunctionTemplatesFromTokens } from './get-function-templates.ts'
import { convertTokensToFunctionTemplate } from './get-function-templates.ts'
import { tokensToFFIDeclareRule } from './declare-rule/ffi-declare-rule.ts'
import { createFunctionInvokeRule } from './invoke-rule.ts'
import { getFunctionDeclareRanges } from '../../../../util/get-function-declare-ranges.ts'

import { getFunctionDeclareRanges } from '../../../../util/get-function-declare-ranges.ts'
import type { Token } from '../../../tokenize/token.ts'
import { tokensToYaksokDeclareRule } from './declare-rule/yaksok-declare-rule.ts'

export function createLocalDynamicRules(
tokens: Token[],
functionDeclareRanges: [number, number][] = getFunctionDeclareRanges(
tokens,
),
functionDeclareRanges = getFunctionDeclareRanges(tokens),
) {
const yaksokTemplates = getFunctionTemplatesFromTokens(
tokens,
functionDeclareRanges,
'yaksok',
)
const getTokensFromRange = getTokensFromRangeFactory(tokens)

const ffiTemplates = getFunctionTemplatesFromTokens(
tokens,
functionDeclareRanges,
'ffi',
)
const yaksokHeaders = functionDeclareRanges.yaksok.map(getTokensFromRange)
const ffiHeaders = functionDeclareRanges.ffi.map(getTokensFromRange)

const invokingRules = [...yaksokHeaders, ...ffiHeaders]
.map(convertTokensToFunctionTemplate)
.flatMap(createFunctionInvokeRule)
.toSorted((a, b) => b.pattern.length - a.pattern.length)

const yaksokInvokeRules = yaksokTemplates.flatMap(createFunctionInvokeRule)
const ffiInvokeRules = ffiTemplates.flatMap(createFunctionInvokeRule)
const ffiDeclareRules = ffiHeaders.map(tokensToFFIDeclareRule)

const allRules = [...yaksokInvokeRules, ...ffiInvokeRules].toSorted(
const yaksokDeclareRules = yaksokHeaders.map(tokensToYaksokDeclareRule)
const declareRules = [...ffiDeclareRules, ...yaksokDeclareRules].toSorted(
(a, b) => b.pattern.length - a.pattern.length,
)

return allRules
return [declareRules, invokingRules]
}

const getTokensFromRangeFactory =
(tokens: Token[]) => (range: [number, number]) =>
tokens.slice(range[0], range[1])
2 changes: 1 addition & 1 deletion core/prepare/parse/dynamicRule/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ export function createDynamicRule(codeFile: CodeFile) {

const mentioningRules = getRulesFromMentioningFile(codeFile)

return [...mentioningRules, ...localRules]
return [...localRules, mentioningRules]
}
7 changes: 4 additions & 3 deletions core/prepare/parse/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { convertTokensToNodes } from '../lex/convert-tokens-to-nodes.ts'
import { getTokensFromNodes } from '../../util/merge-tokens.ts'
import { createDynamicRule } from './dynamicRule/index.ts'
import { SetVariable } from '../../node/variable.ts'
import { YaksokError } from '../../error/common.ts'
import { callParseRecursively } from './srParse.ts'
import { Identifier } from '../../node/base.ts'
import { parseIndent } from './parse-indent.ts'
import { Block } from '../../node/block.ts'

import type { CodeFile } from '../../type/code-file.ts'
import type { Rule } from './type.ts'
import { getTokensFromNodes } from '../../util/merge-tokens.ts'
import { YaksokError } from '../../error/common.ts'

interface ParseResult {
ast: Block
Expand All @@ -19,7 +19,8 @@ interface ParseResult {
export function parse(codeFile: CodeFile): ParseResult {
try {
const dynamicRules = createDynamicRule(codeFile)
const indentedNodes = parseIndent(convertTokensToNodes(codeFile.tokens))
const nodes = convertTokensToNodes(codeFile.tokens)
const indentedNodes = parseIndent(nodes)

const childNodes = callParseRecursively(indentedNodes, dynamicRules)
const childTokens = getTokensFromNodes(childNodes)
Expand Down
89 changes: 0 additions & 89 deletions core/prepare/parse/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,95 +289,6 @@ export const BASIC_RULES: Rule[][] = [
],
factory: (_nodes, tokens) => new RangeOperator(tokens),
},
{
pattern: [
{
type: Identifier,
value: '약속',
},
{
type: Expression,
value: ',',
},
{
type: FunctionInvoke,
},
{
type: EOL,
},
{
type: Block,
},
],
factory: (nodes, tokens) => {
const [_, __, functionInvoke, ___, body] = nodes as [
unknown,
unknown,
FunctionInvoke,
unknown,
Block,
]

const functionName = functionInvoke.name

return new DeclareFunction(
{
body,
name: functionName,
},
tokens,
)
},
flags: [RULE_FLAGS.IS_STATEMENT],
},
{
pattern: [
{
type: Identifier,
value: '번역',
},
{
type: ValueWithParenthesis,
},
{
type: Expression,
value: ',',
},
{
type: FunctionInvoke,
},
{
type: EOL,
},
{
type: FFIBody,
},
],
factory: (nodes, tokens) => {
const [_, runtimeNode, __, functionInvoke, ___, body] =
nodes as [
unknown,
ValueWithParenthesis,
unknown,
FunctionInvoke,
unknown,
FFIBody,
]

const functionName = functionInvoke.name
const runtime = (runtimeNode.value as Identifier).value

return new DeclareFFI(
{
body: body.code,
name: functionName,
runtime,
},
tokens,
)
},
flags: [RULE_FLAGS.IS_STATEMENT],
},
],
]

Expand Down
Loading

0 comments on commit 222c446

Please sign in to comment.